From 5337929cba52be15db4699773d11b3dcc6865b25 Mon Sep 17 00:00:00 2001 From: Ben Fox Date: Thu, 25 Mar 2021 18:47:54 -0700 Subject: [PATCH 1/6] Apply Azure AD, B2C changes on next --- src/providers/azure-ad-b2c.js | 36 ++++++++++--- src/providers/azure-ad.js | 24 +++++++++ src/providers/index.js | 2 + www/docs/providers/azure-ad-b2c.md | 83 ++++++++++++++++++++++++------ www/docs/providers/azure-ad.md | 45 ++++++++++++++++ 5 files changed, 165 insertions(+), 25 deletions(-) create mode 100644 src/providers/azure-ad.js create mode 100644 www/docs/providers/azure-ad.md diff --git a/src/providers/azure-ad-b2c.js b/src/providers/azure-ad-b2c.js index fbf8dc40b6..d60bdf7cb7 100644 --- a/src/providers/azure-ad-b2c.js +++ b/src/providers/azure-ad-b2c.js @@ -1,5 +1,8 @@ export default (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', @@ -9,16 +12,33 @@ export default (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/', + 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 = '' + + // B2C "Display Name" + if (profile.name) { + name = profile.name + } + // B2C "Given Name" & "Surname" + else if (profile.given_name && profile.family_name){ + name = `${profile.given_name} ${profile.family_name}` + } + // B2C "Given Name" + else if (profile.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 + ...options } } diff --git a/src/providers/azure-ad.js b/src/providers/azure-ad.js new file mode 100644 index 0000000000..87447c092c --- /dev/null +++ b/src/providers/azure-ad.js @@ -0,0 +1,24 @@ +export default (options) => { + const tenant = options.tenantId ? 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 + } +} diff --git a/src/providers/index.js b/src/providers/index.js index e410108544..fdeb9ac126 100644 --- a/src/providers/index.js +++ b/src/providers/index.js @@ -1,6 +1,7 @@ import Apple from './apple' import Atlassian from './atlassian' import Auth0 from './auth0' +import AzureAD from './azure-ad' import AzureADB2C from './azure-ad-b2c' import Basecamp from './basecamp' import BattleNet from './battlenet' @@ -41,6 +42,7 @@ export default { Apple, Atlassian, Auth0, + AzureAD, AzureADB2C, Basecamp, BattleNet, diff --git a/www/docs/providers/azure-ad-b2c.md b/www/docs/providers/azure-ad-b2c.md index d1e8aa2694..1f31d3a4f6 100644 --- a/www/docs/providers/azure-ad-b2c.md +++ b/www/docs/providers/azure-ad-b2c.md @@ -5,39 +5,88 @@ title: Azure Active Directory B2C ## Documentation -https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow + -## Configuration +## 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 + +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 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. In `.env.local` create the follwing entries: ``` -AZURE_CLIENT_ID= -AZURE_CLIENT_SECRET= -AZURE_TENANT_ID= +AZURE_AD_B2C_TENANT_NAME= +AZURE_AD_B2C_CLIENT_ID= +AZURE_AD_B2C_CLIENT_SECRET= +AZURE_AD_B2C_PRIMARY_USER_FLOW= ``` -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`, }), ] ... diff --git a/www/docs/providers/azure-ad.md b/www/docs/providers/azure-ad.md new file mode 100644 index 0000000000..f1eb93e5f5 --- /dev/null +++ b/www/docs/providers/azure-ad.md @@ -0,0 +1,45 @@ +--- +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 +- 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 +- Create a new secret and remember / copy its value immediately, it will disappear. + +In `.env.local` create the follwing entries: + +``` +AZURE_AD_CLIENT_ID= +AZURE_AD_CLIENT_SECRET= +AZURE_AD_TENANT_ID= +``` + +In `pages/api/auth/[...nextauth].js` find or add the AZURE_AD entries: + +```js +import Providers from 'next-auth/providers'; +... +providers: [ + Providers.AzureAD({ + tenantId: process.env.AZURE_AD_TENANT_ID, + clientId: process.env.AZURE_AD_CLIENT_ID, + clientSecret: process.env.AZURE_AD_CLIENT_SECRET, + scope: 'offline_access User.Read', + }), +] +... + +``` From 839018c49141ff5f401b2d2373baae8714eb908f Mon Sep 17 00:00:00 2001 From: Ben Fox Date: Thu, 25 Mar 2021 19:20:32 -0700 Subject: [PATCH 2/6] Fix lint errors --- src/providers/azure-ad-b2c.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/providers/azure-ad-b2c.js b/src/providers/azure-ad-b2c.js index d60bdf7cb7..f4d4e32457 100644 --- a/src/providers/azure-ad-b2c.js +++ b/src/providers/azure-ad-b2c.js @@ -1,5 +1,4 @@ export default (options) => { - 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` @@ -20,25 +19,23 @@ export default (options) => { profile: (profile) => { let name = '' - // B2C "Display Name" if (profile.name) { + // B2C "Display Name" name = profile.name - } - // B2C "Given Name" & "Surname" - else if (profile.given_name && profile.family_name){ + } else if (profile.given_name && profile.family_name) { + // B2C "Given Name" & "Surname" name = `${profile.given_name} ${profile.family_name}` - } - // B2C "Given Name" - else if (profile.given_name) { + } else if (profile.given_name) { + // B2C "Given Name" name = `${profile.given_name}` } return { name, id: profile.oid, - email: profile.emails[0], + email: profile.emails[0] } }, - ...options + ...options } } From b0df359a1870862e30d0e5816a089a8b66fa2c8f Mon Sep 17 00:00:00 2001 From: Ben Fox Date: Tue, 30 Mar 2021 15:46:16 -0700 Subject: [PATCH 3/6] Add additional note to AzureAD docs regarding tenant config options. --- www/docs/providers/azure-ad.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/www/docs/providers/azure-ad.md b/www/docs/providers/azure-ad.md index f1eb93e5f5..4b2411fbfc 100644 --- a/www/docs/providers/azure-ad.md +++ b/www/docs/providers/azure-ad.md @@ -12,7 +12,11 @@ https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-c 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 @@ -26,17 +30,21 @@ AZURE_AD_CLIENT_ID= AZURE_AD_CLIENT_SECRET= AZURE_AD_TENANT_ID= ``` +**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 AZURE_AD entries: +In `pages/api/auth/[...nextauth].js` find or add the `AzureAD` entries: ```js import Providers from 'next-auth/providers'; ... providers: [ Providers.AzureAD({ - tenantId: process.env.AZURE_AD_TENANT_ID, 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', }), ] From 37b1bfb31e7fb4553a0fd5f40cb8da0389e6e8cc Mon Sep 17 00:00:00 2001 From: Ben Fox Date: Wed, 28 Apr 2021 17:15:53 -0700 Subject: [PATCH 4/6] Fix providers to be named default exports --- src/providers/azure-ad-b2c.js | 2 +- src/providers/azure-ad.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/providers/azure-ad-b2c.js b/src/providers/azure-ad-b2c.js index 0526c0717d..35fba4fed2 100644 --- a/src/providers/azure-ad-b2c.js +++ b/src/providers/azure-ad-b2c.js @@ -1,4 +1,4 @@ -export default (options) => { +export default function AzureADB2C(options) { 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` diff --git a/src/providers/azure-ad.js b/src/providers/azure-ad.js index 87447c092c..afdd03db26 100644 --- a/src/providers/azure-ad.js +++ b/src/providers/azure-ad.js @@ -1,5 +1,5 @@ -export default (options) => { - const tenant = options.tenantId ? options.tenantId : 'common' +export default function AzureAD(options) { + const tenant = options.tenantId ?? 'common' return { id: 'azure-ad', From cc653ad472a6e37dad862e467c52d192895fbe22 Mon Sep 17 00:00:00 2001 From: Ben Fox Date: Wed, 28 Apr 2021 17:20:08 -0700 Subject: [PATCH 5/6] Remove index.js --- src/providers/index.js | 81 ------------------------------------------ 1 file changed, 81 deletions(-) delete mode 100644 src/providers/index.js diff --git a/src/providers/index.js b/src/providers/index.js deleted file mode 100644 index fdeb9ac126..0000000000 --- a/src/providers/index.js +++ /dev/null @@ -1,81 +0,0 @@ -import Apple from './apple' -import Atlassian from './atlassian' -import Auth0 from './auth0' -import AzureAD from './azure-ad' -import AzureADB2C from './azure-ad-b2c' -import Basecamp from './basecamp' -import BattleNet from './battlenet' -import Box from './box' -import Bungie from './bungie' -import Cognito from './cognito' -import Credentials from './credentials' -import Discord from './discord' -import Email from './email' -import EVEOnline from './eveonline' -import Facebook from './facebook' -import Foursquare from './foursquare' -import FusionAuth from './fusionauth' -import GitHub from './github' -import GitLab from './gitlab' -import Google from './google' -import IdentityServer4 from './identity-server4' -import Instagram from './instagram' -import Kakao from './kakao' -import LINE from './line' -import LinkedIn from './linkedin' -import MailRu from './mailru' -import Medium from './medium' -import Netlify from './netlify' -import Okta from './okta' -import Osso from './osso' -import Reddit from './reddit' -import Salesforce from './salesforce' -import Slack from './slack' -import Spotify from './spotify' -import Strava from './strava' -import Twitch from './twitch' -import Twitter from './twitter' -import VK from './vk' -import Yandex from './yandex' - -export default { - Apple, - Atlassian, - Auth0, - AzureAD, - AzureADB2C, - Basecamp, - BattleNet, - Box, - Bungie, - Cognito, - Credentials, - Discord, - Email, - EVEOnline, - Facebook, - Foursquare, - FusionAuth, - GitHub, - GitLab, - Google, - IdentityServer4, - Instagram, - Kakao, - LINE, - LinkedIn, - MailRu, - Medium, - Netlify, - Okta, - Osso, - Reddit, - Salesforce, - Slack, - Spotify, - Strava, - Twitch, - Twitter, - VK, - Yandex -} From 730ab575a0813d53522e9e1e0f5aac5eeaca9fc9 Mon Sep 17 00:00:00 2001 From: Ben Fox Date: Thu, 10 Jun 2021 07:44:09 -0700 Subject: [PATCH 6/6] Add primary Azure AD B2C documentation link --- www/docs/providers/azure-ad-b2c.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/docs/providers/azure-ad-b2c.md b/www/docs/providers/azure-ad-b2c.md index f4374be81d..933c2aa553 100644 --- a/www/docs/providers/azure-ad-b2c.md +++ b/www/docs/providers/azure-ad-b2c.md @@ -5,7 +5,7 @@ title: Azure Active Directory B2C ## Documentation - +https://docs.microsoft.com/en-us/azure/active-directory-b2c/ ## Options