diff --git a/.github/ISSUE_TEMPLATE/2_bug_provider.yml b/.github/ISSUE_TEMPLATE/2_bug_provider.yml index 406084ea8d..63c72eb5db 100644 --- a/.github/ISSUE_TEMPLATE/2_bug_provider.yml +++ b/.github/ISSUE_TEMPLATE/2_bug_provider.yml @@ -29,6 +29,7 @@ body: - "Atlassian" - "Auth0" - "Authentik" + - "AuthKit" - "Azure Active Directory" - "Azure Active Directory B2C" - "Azure DevOps" diff --git a/apps/dev/express/src/config/auth.config.ts b/apps/dev/express/src/config/auth.config.ts index a85bb2d1f7..52e9ce8887 100644 --- a/apps/dev/express/src/config/auth.config.ts +++ b/apps/dev/express/src/config/auth.config.ts @@ -1,5 +1,6 @@ import Apple from "@auth/express/providers/apple" import Auth0 from "@auth/express/providers/auth0" +import AuthKit from "@auth/express/providers/authkit" import AzureB2C from "@auth/express/providers/azure-ad-b2c" import BoxyHQSAML from "@auth/express/providers/boxyhq-saml" import Cognito from "@auth/express/providers/cognito" @@ -31,6 +32,7 @@ export const authConfig = { providers: [ Apple, Auth0, + AuthKit, AzureB2C({ clientId: process.env.AUTH_AZURE_AD_B2C_ID, clientSecret: process.env.AUTH_AZURE_AD_B2C_SECRET, diff --git a/apps/examples/express/src/config/auth.config.ts b/apps/examples/express/src/config/auth.config.ts index 94c42713ba..0be08db64d 100644 --- a/apps/examples/express/src/config/auth.config.ts +++ b/apps/examples/express/src/config/auth.config.ts @@ -1,5 +1,6 @@ import Apple from "@auth/express/providers/apple" import Auth0 from "@auth/express/providers/auth0" +import AuthKit from "@auth/express/providers/authkit" import AzureB2C from "@auth/express/providers/azure-ad-b2c" import BoxyHQSAML from "@auth/express/providers/boxyhq-saml" import Cognito from "@auth/express/providers/cognito" @@ -30,6 +31,7 @@ export const authConfig = { providers: [ Apple, Auth0, + AuthKit, AzureB2C({ clientId: process.env.AUTH_AZURE_AD_B2C_ID, clientSecret: process.env.AUTH_AZURE_AD_B2C_SECRET, diff --git a/apps/examples/nextjs-pages/auth.ts b/apps/examples/nextjs-pages/auth.ts index aea046c8e0..d659f66315 100644 --- a/apps/examples/nextjs-pages/auth.ts +++ b/apps/examples/nextjs-pages/auth.ts @@ -3,6 +3,7 @@ import NextAuth from "next-auth" // import Apple from "next-auth/providers/apple" // import Auth0 from "next-auth/providers/auth0" // import Authentik from "next-auth/providers/authentik" +// import AuthKit from "next-auth/providers/authkit" // import AzureAD from "next-auth/providers/azure-ad" // import AzureB2C from "next-auth/providers/azure-ad-b2c" // import Battlenet from "next-auth/providers/battlenet" @@ -72,6 +73,7 @@ export const config = { // Apple, // Auth0, // Authentik, + // AuthKit, // AzureAD, // AzureB2C, // Battlenet, diff --git a/apps/examples/nextjs/auth.ts b/apps/examples/nextjs/auth.ts index fa7c049ea3..88714c207d 100644 --- a/apps/examples/nextjs/auth.ts +++ b/apps/examples/nextjs/auth.ts @@ -4,6 +4,7 @@ import "next-auth/jwt" import Apple from "next-auth/providers/apple" // import Atlassian from "next-auth/providers/atlassian" import Auth0 from "next-auth/providers/auth0" +import AuthKit from "next-auth/providers/authkit" import AzureB2C from "next-auth/providers/azure-ad-b2c" import BankIDNorway from "next-auth/providers/bankid-no" import BoxyHQSAML from "next-auth/providers/boxyhq-saml" @@ -56,6 +57,7 @@ export const { handlers, auth, signIn, signOut } = NextAuth({ Apple, // Atlassian, Auth0, + AuthKit, AzureB2C, BankIDNorway, BoxyHQSAML({ diff --git a/apps/examples/sveltekit/src/auth.ts b/apps/examples/sveltekit/src/auth.ts index 7924a1680a..bd0e89ee53 100644 --- a/apps/examples/sveltekit/src/auth.ts +++ b/apps/examples/sveltekit/src/auth.ts @@ -1,6 +1,7 @@ import { SvelteKitAuth } from "@auth/sveltekit" import Apple from "@auth/sveltekit/providers/apple" import Auth0 from "@auth/sveltekit/providers/auth0" +import AuthKit from "@auth/sveltekit/providers/authkit" import AzureB2C from "@auth/sveltekit/providers/azure-ad-b2c" import BoxyHQSAML from "@auth/sveltekit/providers/boxyhq-saml" import Cognito from "@auth/sveltekit/providers/cognito" @@ -32,6 +33,7 @@ export const { handle, signIn, signOut } = SvelteKitAuth({ providers: [ Apple, Auth0, + AuthKit, AzureB2C({ clientId: env.AUTH_AZURE_AD_B2C_ID, clientSecret: env.AUTH_AZURE_AD_B2C_SECRET, diff --git a/apps/proxy/api/[auth].ts b/apps/proxy/api/[auth].ts index 661070563a..5d74085e80 100644 --- a/apps/proxy/api/[auth].ts +++ b/apps/proxy/api/[auth].ts @@ -1,6 +1,7 @@ import { Auth, setEnvDefaults, type AuthConfig } from "@auth/core" import Apple from "@auth/core/providers/apple" import Auth0 from "@auth/core/providers/auth0" +import AuthKit from "@auth/core/providers/authkit" import AzureB2C from "@auth/core/providers/azure-ad-b2c" import BankId from "@auth/core/providers/bankid-no" import BoxyHQSAML from "@auth/core/providers/boxyhq-saml" @@ -34,6 +35,7 @@ const authConfig: AuthConfig = { providers: [ Apple, Auth0, + AuthKit, AzureB2C, BankId, BoxyHQSAML({ diff --git a/docs/pages/data/manifest.json b/docs/pages/data/manifest.json index 6915a8c969..6ba4cdc506 100644 --- a/docs/pages/data/manifest.json +++ b/docs/pages/data/manifest.json @@ -55,6 +55,7 @@ "asgardeo": "Asgardeo", "atlassian": "Atlassian", "authentik": "Authentik", + "authkit": "AuthKit", "azure-ad-b2c": "Azure Active Directory B2C", "azure-ad": "Azure Active Directory", "azure-devops": "Azure DevOps", diff --git a/docs/pages/getting-started/providers/authkit.mdx b/docs/pages/getting-started/providers/authkit.mdx new file mode 100644 index 0000000000..fa4dad0aad --- /dev/null +++ b/docs/pages/getting-started/providers/authkit.mdx @@ -0,0 +1,107 @@ +--- +title: WorkOS +--- + +import { Callout } from "nextra/components" +import { Code } from "@/components/Code" + + + +# AuthKit Provider + +## Resources + +- [WorkOS AuthKit documentation](https://workos.com/docs/reference/user-management) + +## Setup + +### Callback URL + + + + +```bash +https://example.com/api/auth/callback/authkit +``` + + + + +```bash +https://example.com/auth/callback/authkit +``` + + + + +```bash +https://example.com/auth/callback/authkit +``` + + + + +### Environment Variables + +``` +AUTH_AUTHKIT_ID +AUTH_AUTHKIT_SECRET +``` + +### Configuration + + + + +```ts filename="/auth.ts" +import NextAuth from "next-auth" +import AuthKit from "next-auth/providers/authkit" + +export const { handlers, auth, signIn, signOut } = NextAuth({ + providers: [AuthKit({ authkitProvider: "authkit", screenHint: "sign-in" })], +}) +``` + + + + +```ts filename="/src/routes/plugin@auth.ts" +import { QwikAuth$ } from "@auth/qwik" +import AuthKit from "@auth/qwik/providers/authkit" + +export const { onRequest, useSession, useSignIn, useSignOut } = QwikAuth$( + () => ({ + providers: [AuthKit({ authkitProvider: "authkit", screenHint: "sign-in" })], + }) +) +``` + + + + +```ts filename="/src/auth.ts" +import { SvelteKitAuth } from "@auth/sveltekit" +import AuthKit from "@auth/sveltekit/providers/authkit" + +export const { handle, signIn, signOut } = SvelteKitAuth({ + providers: [AuthKit({ authkitProvider: "authkit", screenHint: "sign-in" })], +}) +``` + + + + +```ts filename="/src/app.ts" +import { ExpressAuth } from "@auth/express" +import AuthKit from "@auth/express/providers/authkit" + +app.use( + "/auth/*", + ExpressAuth({ + providers: [AuthKit({ authkitProvider: "authkit", screenHint: "sign-in" })], + }) +) +``` + + + diff --git a/packages/core/src/providers/authkit.ts b/packages/core/src/providers/authkit.ts new file mode 100644 index 0000000000..16aca5c2c3 --- /dev/null +++ b/packages/core/src/providers/authkit.ts @@ -0,0 +1,91 @@ +/** + * @module providers/authkit + */ +import { JsonObject } from "oauth4webapi" +import type { OAuthConfig, OAuthUserConfig } from "./index.js" +/** + * - {@link https://api.workos.com/user_management/users/ | The returned profile object} + */ +export interface AuthKitProfile extends Record { + object: string + id: string + email: string + email_verified: boolean + first_name?: string | null + last_name?: string | null + profile_picture_url?: string | null + created_at: string + updated_at: string +} + +export default function AuthKit

( + options: OAuthUserConfig

& { + authkitProvider?: + | "authkit" + | "GoogleOAuth" + | "AppleOAuth" + | "MicrosoftOAuth" + | "GitHubOAuth" + screenHint?: "sign-in" | "sign-up" + } +): OAuthConfig

{ + return { + id: "authkit", + name: "AuthKit", + type: "oauth", + authorization: { + url: "https://api.workos.com/user_management/authorize", + params: { + provider: options.authkitProvider ?? "authkit", + screen_hint: options.screenHint ?? "sign-up", + }, + }, + token: { + url: "https://api.workos.com/user_management/authenticate", + async conform(res: Response) { + const data = await res.json() + if (data.token_type === "bearer") { + console.warn( + "token_type is 'bearer'. Redundant workaround, please open an issue." + ) + return res + } + return Response.json({ ...data, token_type: "bearer" }, res) + }, + }, + client: { + token_endpoint_auth_method: "client_secret_post", + }, + userinfo: { + url: "https://api.workos.com/user_management/users", + async request({ tokens, provider }) { + const response = await fetch( + `${provider.userinfo?.url}/${(tokens.user as JsonObject)?.id}`, + { + headers: { + Authorization: `Bearer ${provider.clientSecret}`, + }, + } + ) + return response.json() + }, + }, + profile(profile) { + let name = null + if (profile.first_name) { + name = profile.first_name + } + if (profile.last_name) { + name = name ? `${name} ${profile.last_name}` : profile.last_name + } + return { + id: profile.id, + name, + email: profile.email, + image: profile.profile_picture_url ?? null, + } + }, + style: { bg: "#6363f1", text: "#fff" }, + options, + } +}