From 1e4938a14cbf13a8f23207f410e4394712eee139 Mon Sep 17 00:00:00 2001 From: ndom91 Date: Sun, 7 Apr 2024 15:55:17 +0200 Subject: [PATCH 1/7] feat: add microsoft-entra-id provider --- docs/static/img/providers/entra.svg | 9 + .../core/src/providers/microsoft-entra-id.ts | 171 ++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 docs/static/img/providers/entra.svg create mode 100644 packages/core/src/providers/microsoft-entra-id.ts diff --git a/docs/static/img/providers/entra.svg b/docs/static/img/providers/entra.svg new file mode 100644 index 0000000000..0ed35fb73b --- /dev/null +++ b/docs/static/img/providers/entra.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/packages/core/src/providers/microsoft-entra-id.ts b/packages/core/src/providers/microsoft-entra-id.ts new file mode 100644 index 0000000000..4370e5f00c --- /dev/null +++ b/packages/core/src/providers/microsoft-entra-id.ts @@ -0,0 +1,171 @@ +/** + *
+ * Built-in Microsoft Entra ID integration. + * + * + * + *
+ * + * @module providers/microsoft-entra-id + */ +import type { OAuthConfig, OAuthUserConfig } from "./index.js" + +export interface MicrosoftEntraIDProfile extends Record { + sub: string + nickname: string + email: string + picture: string +} + +export type MicrosoftEntraIDOptions

= + OAuthUserConfig

& { + /** + * https://learn.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0&tabs=http#examples + * + * @default 48 + */ + profilePhotoSize?: 48 | 64 | 96 | 120 | 240 | 360 | 432 | 504 | 648 + /** @default "common" */ + tenantId?: string + } + +/** + * + * Add Microsoft Entra ID login to your page. + * + * ### Setup + * + * #### Callback URL + * ``` + * https://example.com/api/auth/callback/microsoft-entra-id + * ``` + * + * #### Configuration + *```js + * import Auth from "@auth/core" + * import MicrosoftEntra from "@auth/core/providers/microsoft-entra-id" + * + * const request = new Request(origin) + * const response = await Auth(request, { + * providers: [MicrosoftEntra({ clientId: MICROSOFT_ENTRA_CLIENT_ID, clientSecret: MICROSOFT_ENTRA_CLIENT_SECRET })], + * }) + * ``` + * + * ### Resources + * + * - [Microsoft Entra OAuth documentation](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow) + * - [Microsoft Entra OAuth apps](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app) + * + * @example + * + * ### To allow specific Active Directory users access: + * + * - In https://entra.microsoft.com/ select Identity from the left bar menu. + * - Next, go to "App Registration" in the left menu, and create a new one. + * - 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 + * - Only your tenant, all Microsoft tenants, or all Microsoft tenants and public Microsoft accounts (Skype, Xbox, Outlook.com, etc.) + * - When asked for a redirection URL, use `https://yourapplication.com/api/auth/callback/microsoft-entra-id` or for development `http://localhost:3000/api/auth/callback/microsoft-entra-id`. + * - After your App Registration is created, under "Client Credential" create your Client secret. + * - Now copy your: + * - Application (client) ID + * - Directory (tenant) ID + * - Client secret (value) + * + * In `.env.local` create the following entries: + * + * ``` + * MICROSOFT_ENTRA_CLIENT_ID= + * MICROSOFT_ENTRA_CLIENT_SECRET= + * MICROSOFT_ENTRA_TENANT_ID= + * ``` + * + * That will default the tenant to use the `common` authorization endpoint. [For more details see here](https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols#endpoints). + * + * :::note + * Microsoft Entra returns the profile picture in an ArrayBuffer, instead of just a URL to the image, so our provider converts it to a base64 encoded image string and returns that instead. See: https://learn.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0&tabs=http#examples. The default image size is 48x48 to avoid [running out of space](https://next-auth.js.org/faq#:~:text=What%20are%20the%20disadvantages%20of%20JSON%20Web%20Tokens%3F) in case the session is saved as a JWT. + * ::: + * + * In `pages/api/auth/[...nextauth].js` find or add the `MicrosoftEntraID` entries: + * + * ```js + * import MicrosoftEntraID from "next-auth/providers/microsoft-entra-id"; + * + * ... + * providers: [ + * MicrosoftEntraIDProvider({ + * clientId: process.env.MICROSOFT_ENTRA_CLIENT_ID, + * clientSecret: process.env.MICROSOFT_ENTRA_CLIENT_SECRET, + * tenantId: process.env.MICROSOFT_ENTRA_TENANT_ID, + * }), + * ] + * ... + * + * ``` + * + * ### Notes + * + * By default, Auth.js assumes that the MicrosoftEntra provider is + * based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification. + * + * :::tip + * + * The MicrosoftEntra provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/microsoft-entra-id.ts). + * To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options). + * + * ::: + * + * :::info **Disclaimer** + * + * If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue). + * + * Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from + * the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec, + * we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions). + * + * ::: + */ +export default function MicrosoftEntraID

( + options: MicrosoftEntraIDOptions

+): OAuthConfig

{ + const { tenantId = "common", profilePhotoSize = 48, ...rest } = options + rest.issuer ??= `https://login.microsoftonline.com/${tenantId}/v2.0` + return { + id: "microsoft-entra-id", + name: "Microsoft Entra ID", + type: "oidc", + wellKnown: `${rest.issuer}/.well-known/openid-configuration?appid=${options.clientId}`, + authorization: { + params: { + scope: "openid profile email User.Read", + }, + }, + async profile(profile, tokens) { + // https://learn.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0&tabs=http#examples + const response = await fetch( + `https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`, + { headers: { Authorization: `Bearer ${tokens.access_token}` } } + ) + + // Confirm that profile photo was returned + let image + // TODO: Do this without Buffer + if (response.ok && typeof Buffer !== "undefined") { + try { + const pictureBuffer = await response.arrayBuffer() + const pictureBase64 = Buffer.from(pictureBuffer).toString("base64") + image = `data:image/jpeg;base64, ${pictureBase64}` + } catch {} + } + + return { + id: profile.sub, + name: profile.name, + email: profile.email, + image: image ?? null, + } + }, + style: { logo: "/microsoft-entra.svg", text: "#fff", bg: "#0072c6" }, + options: rest, + } +} From a95aaa1a6e774ef057b8052a89df717d4fbba274 Mon Sep 17 00:00:00 2001 From: ndom91 Date: Sun, 7 Apr 2024 15:57:25 +0200 Subject: [PATCH 2/7] fix: add deprecation notices to azure-ad and azure-devops --- packages/core/src/providers/azure-ad.ts | 5 ++++- packages/core/src/providers/azure-devops.ts | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/core/src/providers/azure-ad.ts b/packages/core/src/providers/azure-ad.ts index e91273a982..b11dfbd540 100644 --- a/packages/core/src/providers/azure-ad.ts +++ b/packages/core/src/providers/azure-ad.ts @@ -18,7 +18,10 @@ export interface AzureADProfile extends Record { } /** - * Add AzureAd login to your page. + * + * @deprecated + * Azure Active Directory is now known as [Microsoft Entra ID](/getting-started/providers/microsoft-entra-id). + * Import this provider from the `providers/microsoft-entra-id` submodule instead of `providers/azure-ad`. * * ### Setup * diff --git a/packages/core/src/providers/azure-devops.ts b/packages/core/src/providers/azure-devops.ts index 38b592fc02..3f83e79760 100644 --- a/packages/core/src/providers/azure-devops.ts +++ b/packages/core/src/providers/azure-devops.ts @@ -9,6 +9,10 @@ export interface AzureDevOpsProfile extends Record { } /** + * + * @deprecated + * While still available, Microsoft is [no longer supporting](https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/oauth?view=azure-devops#available-oauth-models) Azure DevOps OAuth and recommends using [Microsoft Entra ID](/getting-started/providers/microsoft-entra-id) instead. + * * ## Documentation * * [Microsoft Docs](https://docs.microsoft.com/en-us) · [Azure DevOps](https://docs.microsoft.com/en-us/azure/devops/) · [Authorize access to REST APIs with OAuth 2.0](https://docs.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/oauth?view=azure-devops]) From ed745500ef60d9aabdd334792edf1f4b8f65dd31 Mon Sep 17 00:00:00 2001 From: ndom91 Date: Sun, 7 Apr 2024 15:58:18 +0200 Subject: [PATCH 3/7] chore: revert rmed line from azure-ad docs --- packages/core/src/providers/azure-ad.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/core/src/providers/azure-ad.ts b/packages/core/src/providers/azure-ad.ts index b11dfbd540..71043acb59 100644 --- a/packages/core/src/providers/azure-ad.ts +++ b/packages/core/src/providers/azure-ad.ts @@ -23,6 +23,8 @@ export interface AzureADProfile extends Record { * Azure Active Directory is now known as [Microsoft Entra ID](/getting-started/providers/microsoft-entra-id). * Import this provider from the `providers/microsoft-entra-id` submodule instead of `providers/azure-ad`. * + * Add Azure AD login to your page. + * * ### Setup * * #### Callback URL From 01336e83f70d2379630afb70765d92ecaedc9bc0 Mon Sep 17 00:00:00 2001 From: ndom91 Date: Sun, 7 Apr 2024 16:03:34 +0200 Subject: [PATCH 4/7] fix: rename entra logo to microsoft-entra-id.svg --- docs/static/img/providers/{entra.svg => microsoft-entra-id.svg} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/static/img/providers/{entra.svg => microsoft-entra-id.svg} (100%) diff --git a/docs/static/img/providers/entra.svg b/docs/static/img/providers/microsoft-entra-id.svg similarity index 100% rename from docs/static/img/providers/entra.svg rename to docs/static/img/providers/microsoft-entra-id.svg From 7879192157275e9326f8b2cbef9178f4ae4a8076 Mon Sep 17 00:00:00 2001 From: ndom91 Date: Sun, 7 Apr 2024 16:03:42 +0200 Subject: [PATCH 5/7] fix: update entra typedoc docs --- .../core/src/providers/microsoft-entra-id.ts | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/packages/core/src/providers/microsoft-entra-id.ts b/packages/core/src/providers/microsoft-entra-id.ts index 4370e5f00c..dcf19c8544 100644 --- a/packages/core/src/providers/microsoft-entra-id.ts +++ b/packages/core/src/providers/microsoft-entra-id.ts @@ -2,7 +2,7 @@ *

* Built-in Microsoft Entra ID integration. * - * + * * *
* @@ -33,21 +33,25 @@ export type MicrosoftEntraIDOptions

= * * Add Microsoft Entra ID login to your page. * - * ### Setup + * ## Setup * - * #### Callback URL + * ### Callback URL * ``` * https://example.com/api/auth/callback/microsoft-entra-id * ``` * - * #### Configuration - *```js - * import Auth from "@auth/core" - * import MicrosoftEntra from "@auth/core/providers/microsoft-entra-id" - * - * const request = new Request(origin) - * const response = await Auth(request, { - * providers: [MicrosoftEntra({ clientId: MICROSOFT_ENTRA_CLIENT_ID, clientSecret: MICROSOFT_ENTRA_CLIENT_SECRET })], + * ### Configuration + * ```ts + * import NextAuth from "next-auth" + * import Entra from "next-auth/providers/microsoft-entra-id" + * + * const { handlers, auth, signin, signout } = NextAuth({ + * providers: [ + * Entra({ + * clientId: process.env.AUTH_MICROSOFT_ENTRA_CLIENT_ID, + * clientSecret: process.env.AUTH_MICROSOFT_ENTRA_CLIENT_SECRET + * }) + * ], * }) * ``` * @@ -75,9 +79,9 @@ export type MicrosoftEntraIDOptions

= * In `.env.local` create the following entries: * * ``` - * MICROSOFT_ENTRA_CLIENT_ID= - * MICROSOFT_ENTRA_CLIENT_SECRET= - * MICROSOFT_ENTRA_TENANT_ID= + * AUTH_MICROSOFT_ENTRA_CLIENT_ID= + * AUTH_MICROSOFT_ENTRA_CLIENT_SECRET= + * AUTH_MICROSOFT_ENTRA_TENANT_ID= * ``` * * That will default the tenant to use the `common` authorization endpoint. [For more details see here](https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols#endpoints). @@ -86,20 +90,18 @@ export type MicrosoftEntraIDOptions

= * Microsoft Entra returns the profile picture in an ArrayBuffer, instead of just a URL to the image, so our provider converts it to a base64 encoded image string and returns that instead. See: https://learn.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0&tabs=http#examples. The default image size is 48x48 to avoid [running out of space](https://next-auth.js.org/faq#:~:text=What%20are%20the%20disadvantages%20of%20JSON%20Web%20Tokens%3F) in case the session is saved as a JWT. * ::: * - * In `pages/api/auth/[...nextauth].js` find or add the `MicrosoftEntraID` entries: + * In `app/api/auth/[...nextauth]/route.js` find or add the `Entra` entries: * * ```js - * import MicrosoftEntraID from "next-auth/providers/microsoft-entra-id"; + * import Entra from "next-auth/providers/microsoft-entra-id"; * - * ... * providers: [ - * MicrosoftEntraIDProvider({ - * clientId: process.env.MICROSOFT_ENTRA_CLIENT_ID, - * clientSecret: process.env.MICROSOFT_ENTRA_CLIENT_SECRET, - * tenantId: process.env.MICROSOFT_ENTRA_TENANT_ID, + * Entra({ + * clientId: process.env.AUTH_MICROSOFT_ENTRA_CLIENT_ID, + * clientSecret: process.env.AUTH_MICROSOFT_ENTRA_CLIENT_SECRET, + * tenantId: process.env.AUTH_MICROSOFT_ENTRA_TENANT_ID, * }), * ] - * ... * * ``` * @@ -110,7 +112,7 @@ export type MicrosoftEntraIDOptions

= * * :::tip * - * The MicrosoftEntra provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/microsoft-entra-id.ts). + * The Microsoft Entra ID provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/microsoft-entra-id.ts). * To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options). * * ::: @@ -165,7 +167,7 @@ export default function MicrosoftEntraID

( image: image ?? null, } }, - style: { logo: "/microsoft-entra.svg", text: "#fff", bg: "#0072c6" }, + style: { text: "#fff", bg: "#0072c6" }, options: rest, } } From 41a2f70d34ac3a794230e345d5e00243cabc76c1 Mon Sep 17 00:00:00 2001 From: ndom91 Date: Sun, 7 Apr 2024 16:17:11 +0200 Subject: [PATCH 6/7] fix: entra env vars --- .../core/src/providers/microsoft-entra-id.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/core/src/providers/microsoft-entra-id.ts b/packages/core/src/providers/microsoft-entra-id.ts index dcf19c8544..a0ac914541 100644 --- a/packages/core/src/providers/microsoft-entra-id.ts +++ b/packages/core/src/providers/microsoft-entra-id.ts @@ -48,8 +48,8 @@ export type MicrosoftEntraIDOptions

= * const { handlers, auth, signin, signout } = NextAuth({ * providers: [ * Entra({ - * clientId: process.env.AUTH_MICROSOFT_ENTRA_CLIENT_ID, - * clientSecret: process.env.AUTH_MICROSOFT_ENTRA_CLIENT_SECRET + * clientId: process.env.AUTH_MICROSOFT_ENTRA_ID_ID, + * clientSecret: process.env.AUTH_MICROSOFT_ENTRA_ID_SECRET * }) * ], * }) @@ -79,9 +79,9 @@ export type MicrosoftEntraIDOptions

= * In `.env.local` create the following entries: * * ``` - * AUTH_MICROSOFT_ENTRA_CLIENT_ID= - * AUTH_MICROSOFT_ENTRA_CLIENT_SECRET= - * AUTH_MICROSOFT_ENTRA_TENANT_ID= + * AUTH_MICROSOFT_ENTRA_ID_ID= + * AUTH_MICROSOFT_ENTRA_ID_SECRET= + * AUTH_MICROSOFT_ENTRA_ID_TENANT_ID= * ``` * * That will default the tenant to use the `common` authorization endpoint. [For more details see here](https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols#endpoints). @@ -97,9 +97,9 @@ export type MicrosoftEntraIDOptions

= * * providers: [ * Entra({ - * clientId: process.env.AUTH_MICROSOFT_ENTRA_CLIENT_ID, - * clientSecret: process.env.AUTH_MICROSOFT_ENTRA_CLIENT_SECRET, - * tenantId: process.env.AUTH_MICROSOFT_ENTRA_TENANT_ID, + * clientId: process.env.AUTH_MICROSOFT_ENTRA_ID_ID, + * clientSecret: process.env.AUTH_MICROSOFT_ENTRA_ID_SECRET, + * tenantId: process.env.AUTH_MICROSOFT_ENTRA_ID_TENANT_ID, * }), * ] * From 239d42ae961dd0bca60901cd4de32c327eb27033 Mon Sep 17 00:00:00 2001 From: ndom91 Date: Sun, 7 Apr 2024 16:19:49 +0200 Subject: [PATCH 7/7] fix: add note and link for entra "new name" --- packages/core/src/providers/microsoft-entra-id.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/core/src/providers/microsoft-entra-id.ts b/packages/core/src/providers/microsoft-entra-id.ts index a0ac914541..d41c8d4629 100644 --- a/packages/core/src/providers/microsoft-entra-id.ts +++ b/packages/core/src/providers/microsoft-entra-id.ts @@ -33,6 +33,10 @@ export type MicrosoftEntraIDOptions

= * * Add Microsoft Entra ID login to your page. * + * :::note + * Entra is the [new name](https://learn.microsoft.com/en-us/entra/fundamentals/new-name) Microsoft has given to what was previously known as "Azure AD" + * ::: + * * ## Setup * * ### Callback URL