From 8f38c82ed7651d5c1e905e265ab1deb835826ce1 Mon Sep 17 00:00:00 2001 From: Thomas Schuster Date: Sun, 26 May 2024 16:50:03 +0200 Subject: [PATCH] add azure ad authentication --- .env.sample | 14 +++++++- pages/api/v1/auth/[...nextauth].ts | 55 +++++++++++++++++++++++++----- pages/api/v1/logins/index.ts | 13 +++++++ types/enviornment.d.ts | 14 ++++++-- 4 files changed, 84 insertions(+), 12 deletions(-) diff --git a/.env.sample b/.env.sample index 30bc044..39b037b 100644 --- a/.env.sample +++ b/.env.sample @@ -84,7 +84,6 @@ AUTHELIA_CLIENT_ID="" AUTHELIA_CLIENT_SECRET="" AUTHELIA_WELLKNOWN_URL="" - # Authentik NEXT_PUBLIC_AUTHENTIK_ENABLED= AUTHENTIK_CUSTOM_NAME= @@ -92,6 +91,19 @@ AUTHENTIK_ISSUER= AUTHENTIK_CLIENT_ID= AUTHENTIK_CLIENT_SECRET= +# Azure AD B2C +NEXT_PUBLIC_AZURE_AD_B2C_ENABLED= +AZURE_AD_B2C_TENANT_NAME= +AZURE_AD_B2C_CLIENT_ID= +AZURE_AD_B2C_CLIENT_SECRET= +AZURE_AD_B2C_PRIMARY_USER_FLOW= + +# Azure AD +NEXT_PUBLIC_AZURE_AD_ENABLED= +AZURE_AD_CLIENT_ID= +AZURE_AD_CLIENT_SECRET= +AZURE_AD_TENANT_ID= + # Battle.net NEXT_PUBLIC_BATTLENET_ENABLED= BATTLENET_CUSTOM_NAME= diff --git a/pages/api/v1/auth/[...nextauth].ts b/pages/api/v1/auth/[...nextauth].ts index 91fe7a7..dfb69ef 100644 --- a/pages/api/v1/auth/[...nextauth].ts +++ b/pages/api/v1/auth/[...nextauth].ts @@ -1,27 +1,31 @@ import { prisma } from "@/lib/api/db"; -import NextAuth from "next-auth/next"; -import CredentialsProvider from "next-auth/providers/credentials"; -import bcrypt from "bcrypt"; -import EmailProvider from "next-auth/providers/email"; -import { PrismaAdapter } from "@auth/prisma-adapter"; -import { Adapter } from "next-auth/adapters"; import sendVerificationRequest from "@/lib/api/sendVerificationRequest"; -import { Provider } from "next-auth/providers"; import verifySubscription from "@/lib/api/verifySubscription"; +import { PrismaAdapter } from "@auth/prisma-adapter"; +import bcrypt from "bcrypt"; +import { randomBytes } from "crypto"; +import type { NextApiRequest, NextApiResponse } from "next"; +import { Adapter } from "next-auth/adapters"; +import NextAuth from "next-auth/next"; +import { Provider } from "next-auth/providers"; import FortyTwoProvider from "next-auth/providers/42-school"; import AppleProvider from "next-auth/providers/apple"; import AtlassianProvider from "next-auth/providers/atlassian"; import Auth0Provider from "next-auth/providers/auth0"; import AuthentikProvider from "next-auth/providers/authentik"; +import AzureAdProvider from "next-auth/providers/azure-ad"; +import AzureAdB2CProvider from "next-auth/providers/azure-ad-b2c"; import BattleNetProvider, { BattleNetIssuer, } from "next-auth/providers/battlenet"; import BoxProvider from "next-auth/providers/box"; import CognitoProvider from "next-auth/providers/cognito"; import CoinbaseProvider from "next-auth/providers/coinbase"; +import CredentialsProvider from "next-auth/providers/credentials"; import DiscordProvider from "next-auth/providers/discord"; import DropboxProvider from "next-auth/providers/dropbox"; import DuendeIDS6Provider from "next-auth/providers/duende-identity-server6"; +import EmailProvider from "next-auth/providers/email"; import EVEOnlineProvider from "next-auth/providers/eveonline"; import FacebookProvider from "next-auth/providers/facebook"; import FaceItProvider from "next-auth/providers/faceit"; @@ -64,8 +68,6 @@ import ZitadelProvider from "next-auth/providers/zitadel"; import ZohoProvider from "next-auth/providers/zoho"; import ZoomProvider from "next-auth/providers/zoom"; import * as process from "process"; -import type { NextApiRequest, NextApiResponse } from "next"; -import { randomBytes } from "crypto"; const emailEnabled = process.env.EMAIL_FROM && process.env.EMAIL_SERVER ? true : false; @@ -354,6 +356,41 @@ if (process.env.NEXT_PUBLIC_AUTHENTIK_ENABLED === "true") { }; } +// Azure AD B2C +if (process.env.NEXT_PUBLIC_AZURE_AD_ENABLED === "true") { + providers.push( + AzureAdB2CProvider({ + tenantId: 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, + authorization: { params: { scope: "offline_access openid" } }, + }) + ); + + const _linkAccount = adapter.linkAccount; + adapter.linkAccount = (account) => { + const { "not-before-policy": _, refresh_expires_in, ...data } = account; + return _linkAccount ? _linkAccount(data) : undefined; + }; + +// Azure AD +if (process.env.NEXT_PUBLIC_AZURE_AD_ENABLED === "true") { + providers.push( + AzureAdProvider({ + clientId: process.env.AZURE_AD_CLIENT_ID!, + clientSecret: process.env.AZURE_AD_CLIENT_SECRET!, + tenantId: process.env.AZURE_AD_TENANT_ID, + }) + ); + + const _linkAccount = adapter.linkAccount; + adapter.linkAccount = (account) => { + const { "not-before-policy": _, refresh_expires_in, ...data } = account; + return _linkAccount ? _linkAccount(data) : undefined; + }; +} + // Battle.net if (process.env.NEXT_PUBLIC_BATTLENET_ENABLED === "true") { providers.push( diff --git a/pages/api/v1/logins/index.ts b/pages/api/v1/logins/index.ts index d2ac875..6d2c998 100644 --- a/pages/api/v1/logins/index.ts +++ b/pages/api/v1/logins/index.ts @@ -55,6 +55,19 @@ export function getLogins() { name: process.env.AUTHENTIK_CUSTOM_NAME ?? "Authentik", }); } + // Azure AD B2C + if (process.env.NEXT_PUBLIC_AZURE_AD_B2C_ENABLED === "true") { + buttonAuths.push({ + method: "azure-ad-b2c", + name: process.env.AUTHENTIK_CUSTOM_NAME ?? "Azure AD B2C", + }); + // Azure AD + if (process.env.NEXT_PUBLIC_AZURE_AD_ENABLED === "true") { + buttonAuths.push({ + method: "azure-ad", + name: process.env.AUTHENTIK_CUSTOM_NAME ?? "Azure AD", + }); + } // Battle.net if (process.env.NEXT_PUBLIC_BATTLENET_ENABLED === "true") { buttonAuths.push({ diff --git a/types/enviornment.d.ts b/types/enviornment.d.ts index 32bc29d..575a491 100644 --- a/types/enviornment.d.ts +++ b/types/enviornment.d.ts @@ -93,8 +93,18 @@ declare global { AUTHENTIK_CLIENT_ID?: string; AUTHENTIK_CLIENT_SECRET?: string; - // TODO: Azure AD B2C - // TODO: Azure AD + // Azure AD B2C + NEXT_PUBLIC_AZURE_AD_B2C_ENABLED?: string; + AZURE_AD_B2C_TENANT_NAME?: string; + AZURE_AD_B2C_CLIENT_ID?: string; + AZURE_AD_B2C_CLIENT_SECRET?: string; + AZURE_AD_B2C_PRIMARY_USER_FLOW?: string; + + // Azure AD + NEXT_PUBLIC_AZURE_AD_ENABLED?: string; + AZURE_AD_CLIENT_ID?: string; + AZURE_AD_CLIENT_SECRET?: string; + AZURE_AD_TENANT_ID?: string; // Battle.net NEXT_PUBLIC_BATTLENET_ENABLED?: string;