Skip to content
33 changes: 25 additions & 8 deletions src/providers/azure-ad-b2c.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export default function AzureADB2C(options) {
const tenant = options.tenantId ? options.tenantId : "common"
const { tenantName, primaryUserFlow } = options
const authorizeUrl = `https://${tenantName}.b2clogin.com/${tenantName}.onmicrosoft.com/${primaryUserFlow}/oauth2/v2.0/authorize`
const tokenUrl = `https://${tenantName}.b2clogin.com/${tenantName}.onmicrosoft.com/${primaryUserFlow}/oauth2/v2.0/token`

return {
id: "azure-ad-b2c",
Expand All @@ -9,14 +11,29 @@ export default function AzureADB2C(options) {
params: {
grant_type: "authorization_code",
},
accessTokenUrl: `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token`,
authorizationUrl: `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/authorize?response_type=code&response_mode=query`,
profileUrl: "https://graph.microsoft.com/v1.0/me/",
profile(profile) {
accessTokenUrl: tokenUrl,
requestTokenUrl: tokenUrl,
authorizationUrl: `${authorizeUrl}?response_type=code+id_token&response_mode=query`,
profileUrl: 'https://graph.microsoft.com/oidc/userinfo',
idToken: true,
profile: (profile) => {
let name = ''

if (profile.name) {
// B2C "Display Name"
name = profile.name
} else if (profile.given_name && profile.family_name) {
// B2C "Given Name" & "Surname"
name = `${profile.given_name} ${profile.family_name}`
} else if (profile.given_name) {
// B2C "Given Name"
name = `${profile.given_name}`
}

return {
id: profile.id,
name: profile.displayName,
email: profile.userPrincipalName,
name,
id: profile.oid,
email: profile.emails[0]
}
},
...options,
Expand Down
24 changes: 24 additions & 0 deletions src/providers/azure-ad.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export default function AzureAD(options) {
const tenant = options.tenantId ?? 'common'

return {
id: 'azure-ad',
name: 'Azure Active Directory',
type: 'oauth',
version: '2.0',
params: {
grant_type: 'authorization_code'
},
accessTokenUrl: `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token`,
authorizationUrl: `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/authorize?response_type=code&response_mode=query`,
profileUrl: 'https://graph.microsoft.com/v1.0/me/',
profile: (profile) => {
return {
id: profile.id,
name: profile.displayName,
email: profile.userPrincipalName
}
},
...options
}
}
88 changes: 68 additions & 20 deletions www/docs/providers/azure-ad-b2c.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ title: Azure Active Directory B2C

## Documentation

https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow

## Configuration

https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-tenant
https://docs.microsoft.com/en-us/azure/active-directory-b2c/

## Options

Expand All @@ -19,34 +15,86 @@ The **Azure Active Directory Provider** comes with a set of default options:

You can override any of the options to suit your own use case.

## Example
## Configuration (Basic)

Basic configuration sets up Azure AD B2C to return an ID Token. This should be done as a prerequisite prior to running through the Advanced configuration.

Step 1: Azure AD B2C Tenant
https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-tenant

Step 2: App Registration
https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-register-applications

- In https://portal.azure.com/ -> Azure Active Directory create a new App Registration.
- Make sure to remember / copy
- Application (client) ID
- Directory (tenant) ID
- When asked for a redirection URL, use http://localhost:3000/api/auth/callback/azure-ad-b2c
- Create a new secret and remember / copy its value immediately, it will disappear.
Step 3: User Flow
https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows

Note: For the step "User attributes and token claims" you might minimally:
- Collect attribute:
- Email Address
- Display Name
- Given Name
- Surname
- Return claim:
- Email Addresses
- Display Name
- Given Name
- Surname
- Identity Provider
- Identity Provider Access Token
- User's Object ID

## Example

In `.env.local` create the following entries:

```
AZURE_CLIENT_ID=<copy Application (client) ID here>
AZURE_CLIENT_SECRET=<copy generated secret value here>
AZURE_TENANT_ID=<copy the tenant id here>
AZURE_AD_B2C_TENANT_NAME=<copy the B2C tenant name here from Step 1>
AZURE_AD_B2C_CLIENT_ID=<copy Application (client) ID here from Step 2>
AZURE_AD_B2C_CLIENT_SECRET=<copy generated secret value here from Step 2>
AZURE_AD_B2C_PRIMARY_USER_FLOW=<copy the name of the signin user flow you created from Step 3>
```

In `pages/api/auth/[...nextauth].js` find or add the AZURE entries:
In `pages/api/auth/[...nextauth].js` find or add the AZURE_AD_B2C entries:

```js
import Providers from 'next-auth/providers';
...
providers: [
Providers.AzureADB2C({
tenantName: process.env.AZURE_AD_B2C_TENANT_NAME,
clientId: process.env.AZURE_AD_B2C_CLIENT_ID,
clientSecret: process.env.AZURE_AD_B2C_CLIENT_SECRET,
primaryUserFlow: process.env.AZURE_AD_B2C_PRIMARY_USER_FLOW,
scope: `offline_access openid`,
}),
]
...

```

## Configuration (Advanced)

Advanced configuration sets up Azure AD B2C to return an Authorization Token. This builds on the steps completed in the Basic configuration above.

Step 4: Add a Web API application
https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-single-page-app-webapi?tabs=app-reg-ga

Note: this is a second app registration (similar to Step 2) but with different setup and configuration.

## Example

Nothing in `.env.local` needs to change here. The only update is in `pages/api/auth/[...nextauth].js` where you will need to add the additional scopes that were created in Step 4 above:

```js
import Providers from 'next-auth/providers';
...
providers: [
Providers.AzureADB2C({
clientId: process.env.AZURE_CLIENT_ID,
clientSecret: process.env.AZURE_CLIENT_SECRET,
scope: 'offline_access User.Read',
tenantId: process.env.AZURE_TENANT_ID,
tenantName: process.env.AZURE_AD_B2C_TENANT_NAME,
clientId: process.env.AZURE_AD_B2C_CLIENT_ID,
clientSecret: process.env.AZURE_AD_B2C_CLIENT_SECRET,
primaryUserFlow: process.env.AZURE_AD_B2C_PRIMARY_USER_FLOW,
scope: `https://${process.env.AZURE_AD_B2C_TENANT_NAME}.onmicrosoft.com/api/demo.read https://${process.env.AZURE_AD_B2C_TENANT_NAME}.onmicrosoft.com/api/demo.write offline_access openid`,
}),
]
...
Expand Down
53 changes: 53 additions & 0 deletions www/docs/providers/azure-ad.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
id: azure-ad
title: Azure Active Directory
---

## Documentation

https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow

## Configuration

https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app

## Example

### To allow specific Active Directory users access:
- In https://portal.azure.com/ -> Azure Active Directory create a new App Registration.
- Pay close attention to "Who can use this application or access this API?"
- This allows you to scope access to specific types of user accounts.
- Make sure to remember / copy
- Application (client) ID
- Directory (tenant) ID
- When asked for a redirection URL, use http://localhost:3000/api/auth/callback/azure-ad
- Create a new secret and remember / copy its value immediately, it will disappear.

In `.env.local` create the follwing entries:

```
AZURE_AD_CLIENT_ID=<copy Application (client) ID here>
AZURE_AD_CLIENT_SECRET=<copy generated secret value here>
AZURE_AD_TENANT_ID=<copy the tenant id here>
```
**Note**: Omit the `AZURE_TENANT_ID` if you created the App Registration for:
> Accounts in any organizational directory (Any Azure AD directory - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox)

That will default the tenant to use the `common` authorization endpoint. [For more details see here](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols#endpoints).

In `pages/api/auth/[...nextauth].js` find or add the `AzureAD` entries:

```js
import Providers from 'next-auth/providers';
...
providers: [
Providers.AzureAD({
clientId: process.env.AZURE_AD_CLIENT_ID,
clientSecret: process.env.AZURE_AD_CLIENT_SECRET,
tenantId: process.env.AZURE_AD_TENANT_ID, // omit this if it was omitted above.
scope: 'offline_access User.Read',
}),
]
...

```