| ms.topic | how-to |
|---|---|
| title | Use Azure DevOps OAuth 2.0 |
| description | Learn how to manage existing Azure DevOps OAuth 2.0 applications and plan migration to Microsoft Entra ID OAuth. |
| ms.subservice | azure-devops-security |
| ai-usage | ai-assisted |
| monikerRange | azure-devops |
| ms.author | chcomley |
| author | chcomley |
| ms.date | 07/14/2025 |
| ms.custom | sfi-image-nochange |
[!INCLUDE version-eq-azure-devops]
Important
Azure DevOps OAuth is deprecated and scheduled for removal in 2026. This documentation is for existing Azure DevOps OAuth apps only. New app registrations are no longer accepted as of April 2025.
For new applications: Use Microsoft Entra ID OAuth to integrate with Azure DevOps.
For existing apps: Plan your migration to Microsoft Entra ID OAuth before 2026.
This article explains how Azure DevOps OAuth 2.0 works for existing applications and provides guidance for maintaining and migrating your apps.
Azure DevOps OAuth 2.0 allows applications to access Azure DevOps resources on behalf of users. While this service is deprecated, existing applications continue to function until 2026.
Migration recommendation: Start planning your migration to Microsoft Entra ID OAuth to ensure continued service and access to enhanced security features.
Before working with Azure DevOps OAuth applications:
| Requirement | Description |
|---|---|
| Existing app registration | An existing Azure DevOps OAuth app (new registrations stopped April 2025) |
| Azure DevOps organization | Access to an Azure DevOps Services organization |
| HTTPS callback URL | Secure callback URL for your application |
| Migration plan | Strategy for migrating to Microsoft Entra ID OAuth before 2026 |
Note
New app registrations are no longer accepted. This section applies only to existing registered applications.
For existing applications, you can view and manage your app settings:
-
Go to your Visual Studio profile to access your app registrations.
-
Review your configured scopes and ensure they match your application's needs.
-
Verify your callback URL configuration and update if necessary.
:::image type="content" source="media/app-page.png" alt-text="Screenshot showing Application settings for your existing app.":::
-
Plan your migration timeline to Microsoft Entra ID OAuth before the 2026 deprecation deadline.
The authorization flow remains the same for existing Azure DevOps OAuth apps:
-
Direct users to the authorization URL with your app parameters:
https://app.vssps.visualstudio.com/oauth2/authorize ?client_id={app ID} &response_type=Assertion &state={state} &scope={scope} &redirect_uri={callback URL}Parameter Type Description client_idGUID The ID assigned to your app when it was registered response_typestring Must be Assertionstatestring A generated string value that correlates the callback with its authorization request scopestring Space-separated scopes registered with the app. See available scopes redirect_uriURL Callback URL for your app. Must exactly match the URL registered with the app Example authorization URL:
https://app.vssps.visualstudio.com/oauth2/authorize ?client_id=00001111-aaaa-2222-bbbb-3333cccc4444 &response_type=Assertion &state=User1 &scope=vso.work%20vso.code_write &redirect_uri=https://fabrikam.azurewebsites.net/myapp/oauth-callbackAfter user authorization, Azure DevOps redirects to your callback URL with the authorization code:
https://fabrikam.azurewebsites.net/myapp/oauth-callback ?code={authorization code} &state=User1
Use the authorization code to request an access token and refresh token:
URL
POST https://app.vssps.visualstudio.com/oauth2/tokenHeaders
Content-Type: application/x-www-form-urlencodedRequest body
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion={0}&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion={1}&redirect_uri={2}Parameter substitution:
{0}: URL-encoded client secret from app registration{1}: URL-encoded authorization code from callback{2}: Callback URL registered with the app
public string GenerateRequestPostData(string appSecret, string authCode, string callbackUrl)
{
return String.Format("client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion={0}&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion={1}&redirect_uri={2}",
HttpUtility.UrlEncode(appSecret),
HttpUtility.UrlEncode(authCode),
callbackUrl
);
}{
"access_token": "{ access token for the user }",
"token_type": "{ type of token }",
"expires_in": "{ time in seconds that the token remains valid }",
"refresh_token": "{ refresh token to use to acquire a new access token }"
}Important
Securely store the refresh token - Access tokens expire quickly, but refresh tokens allow you to get new access tokens without requiring user reauthorization.
Include the access token as a Bearer token in your API requests:
Authorization header format:
Authorization: Bearer {access_token}Example API request:
GET https://dev.azure.com/myaccount/myproject/_apis/build-release/builds?api-version=3.0
Authorization: Bearer {access_token}When access tokens expire, use the refresh token to get a new access token:
Request:
POST https://app.vssps.visualstudio.com/oauth2/token
Content-Type: application/x-www-form-urlencoded
Content-Length: 1654
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion={0}&grant_type=refresh_token&assertion={1}&redirect_uri={2}Parameter substitution:
{0}: URL-encoded client secret{1}: URL-encoded refresh token{2}: Callback URL registered with the app
Response:
{
"access_token": "{ new access token }",
"token_type": "{ type of token }",
"expires_in": "{ time in seconds that the token remains valid }",
"refresh_token": "{ new refresh token }"
}Important
Update your refresh token - A new refresh token is issued with each refresh. Store the new token and use it for future refresh operations.
You can find working examples in our Azure DevOps authentication samples repository.
Important
Secret rotation is critical for security. Application secrets expire every 60 days and must be rotated to maintain access.
Azure DevOps OAuth apps support dual secrets to enable zero-downtime rotation:
-
Generate a new secret in your Visual Studio profile or via the Registration Secret APIs.
:::image type="content" source="media/app-page-new-secret.png" alt-text="Screenshot of app page with secondary secret generated.":::
-
Confirm the action in the modal dialog.
:::image type="content" source="media/secret-regeneration-modal.png" alt-text="Screenshot confirming secret regeneration.":::
-
Update your application to use the new secret before the old one expires.
-
Test the new secret thoroughly before the old secret expires.
-
Repeat the process when the new secret approaches expiration.
If a secret is compromised:
- Immediately regenerate the secret in your profile.
- Update your application with the new secret.
- Monitor for unauthorized access in your application logs.
Warning
Regenerating a secret immediately invalidates the previous secret and all tokens created with it.
Warning
Deleting an app registration immediately breaks all applications using it and invalidates all associated tokens.
To delete an Azure DevOps OAuth app:
-
Go to your Visual Studio profile.
-
Select the correct tenant from the dropdown menu.
-
Find your app under Applications and services.
-
Select Delete on the application registration page.
:::image type="content" source="media/azdo-oauth-app-delete.png" alt-text="Screenshot of app metadata page with delete button highlighted":::
-
Confirm the deletion in the modal dialog.
After deletion, the app and all its tokens immediately stop working.
Important
Start planning your migration now. Azure DevOps OAuth is slated for removal in 2026.
- Review Microsoft Entra ID OAuth documentation
- Identify all apps using Azure DevOps OAuth in your organization
- Plan migration timeline allowing adequate testing time
- Update application architecture to support Microsoft Entra ID OAuth
- Test migration in a nonproduction environment
- Communicate changes to users and stakeholders
- Complete migration before 2026 deadline
Enhanced security features:
- Multifactor authentication support
- Conditional Access policies
- Advanced threat protection
- Enterprise identity integration
Better developer experience:
- Modern authentication libraries (MSAL)
- Consistent identity platform across Microsoft services
- Better token management and caching
Long-term support:
- Continued investment and feature development
- Enterprise compliance and governance features
A: No. New app registrations stopped in April 2025. Use Microsoft Entra ID OAuth for new applications.
A: Existing apps continue to function until Azure DevOps OAuth is fully deprecated in 2026. Plan your migration well before this deadline.
A: Azure DevOps OAuth only supports the web server flow and requires secure storage of client secrets, making it unsuitable for mobile apps. Microsoft Entra ID OAuth provides better mobile app support.
A: Common causes include:
- Incorrect
Content-Typeheader (should beapplication/x-www-form-urlencoded) - Malformed request body parameters
- Invalid or expired authorization code
- Mismatched callback URL
A: Check if your organization administrator disabled Third-party application access via OAuth at:
https://dev.azure.com/{your-org-name}/_settings/organizationPolicy
When disabled, OAuth authorization flows work, but API calls return TF400813: The user "<GUID>" is not authorized to access this resource.
A: Yes. Azure DevOps OAuth supports https://localhost callback URLs for local development and testing.
A: Implement proper error handling for:
- Authorization denial: No authorization code is returned in the callback
- Revoked authorization: API calls return 401 errors; re-request authorization from the user
A:
- Azure DevOps OAuth: Deprecated, Azure DevOps-specific, limited security features
- Microsoft Entra ID OAuth: Modern, enterprise-grade, enhanced security, long-term support
For existing applications:
[!div class="nextstepaction"] Plan migration to Microsoft Entra ID OAuth
For new applications:
[!div class="nextstepaction"] Get started with Microsoft Entra ID OAuth