Skip to content
The Auth.js project is now part of Better Auth.

providers/azure-devops

AzureDevOpsProfile

See

Azure DevOps Services REST API 7.0 · Profiles · Get

Extends

Indexable

[key: string]: any

Properties

coreAttributes

coreAttributes: {  Avatar: {  value: {  value: string;  };  }; };
Avatar
Avatar: {  value: {  value: string;  }; };
Avatar.value
Avatar.value: {  value: string; };
Avatar.value.value
Avatar.value.value: string;

displayName

displayName: string;

emailAddress

emailAddress: string;

id

id: string;

default()

function default<P>(options): OAuthConfig<P>

Type Parameters

Type Parameter
P extends AzureDevOpsProfile

Parameters

ParameterType
optionsOAuthUserConfig<P> & { scope: string; }

Returns

OAuthConfig<P>

Deprecated

While still available, Microsoft is no longer supporting Azure DevOps OAuth and recommends using Microsoft Entra ID instead.

Documentation

Microsoft Docs · Azure DevOps · Authorize access to REST APIs with OAuth 2.0

Configuration

Register application

Provide the required details:

  • Company name
  • Application name
  • Application website
  • Authorization callback URL
    • https://example.com/api/auth/callback/azure-devops for production
    • https://localhost/api/auth/callback/azure-devops for development
  • Authorized scopes
    • Required minimum is User profile (read)

Click ‘Create Application’

⚠️

You are required to use HTTPS even for the localhost

⚠️

You will have to delete and create a new application to change the scopes later

The following data is relevant for the next step:

  • App ID
  • Client Secret (after clicking the ‘Show’ button, ignore App Secret entry above it)
  • Authorized Scopes

Set up the environment variables

In .env.local create the following entries:

AZURE_DEVOPS_APP_ID=<copy App ID value here> AZURE_DEVOPS_CLIENT_SECRET=<copy generated client secret value here> AZURE_DEVOPS_SCOPE=<copy space separated Authorized Scopes list here>

Example

import AzureDevOps from "@auth/core/providers/azure-devops" ... providers: [  AzureDevOps({  clientId: process.env.AZURE_DEVOPS_APP_ID,  clientSecret: process.env.AZURE_DEVOPS_CLIENT_SECRET,  scope: process.env.AZURE_DEVOPS_SCOPE,  }), ] ...

Refresh token rotation

Use the main guide as your starting point with the following considerations:

async jwt({ token, user, account }) {  ...  // The token has an absolute expiration time  const accessTokenExpires = account.expires_at * 1000  ... }   async function refreshAccessToken(token) {  ...  const response = await fetch(  "https://app.vssps.visualstudio.com/oauth2/token",  {  headers: { "Content-Type": "application/x-www-form-urlencoded" },  method: "POST",  body: new URLSearchParams({  client_assertion_type:  "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",  client_assertion: process.env.AZURE_DEVOPS_CLIENT_SECRET,  grant_type: "refresh_token",  assertion: token.refreshToken,  redirect_uri:  process.env.NEXTAUTH_URL + "/api/auth/callback/azure-devops",  }),  }  )  ...  // The refreshed token comes with a relative expiration time  const accessTokenExpires = Date.now() + newToken.expires_in * 1000  ... }
Auth.js © Better Auth Inc. - 2025