diff --git a/docs/docs/configuration/idp.mdx b/docs/docs/configuration/idp.mdx index 21ae756d..6d2475b5 100644 --- a/docs/docs/configuration/idp.mdx +++ b/docs/docs/configuration/idp.mdx @@ -366,3 +366,53 @@ A Microsoft Entra ID connection can be used for [authentication](/docs/configura +### Authentik + +[Auth.js Authentik Provider Docs](https://authjs.dev/getting-started/providers/authentik) + +An Authentik connection can be used for [authentication](/docs/configuration/auth). + + + + + To begin, you must create a OAuth2/OpenID Connect application in Authentik. For more information, see the [Authentik documentation](https://docs.goauthentik.io/add-secure-apps/applications/manage_apps/#create-an-application-and-provider-pair). + + When configuring your application: + - Set the provider type to "OAuth2/OpenID Connect" + - Set the client type to "Confidential" + - Add `/api/auth/callback/authentik` to the redirect URIs (ex. https://sourcebot.coolcorp.com/api/auth/callback/authentik) + + After creating the application, open the application details to obtain the client id, client secret, and issuer URL (typically in the format `https:///application/o//`). + + + The client id, secret, and issuer URL are provided to Sourcebot via environment variables. These can be named whatever you like + (ex. `AUTHENTIK_IDENTITY_PROVIDER_CLIENT_ID`, `AUTHENTIK_IDENTITY_PROVIDER_CLIENT_SECRET`, and `AUTHENTIK_IDENTITY_PROVIDER_ISSUER`) + + + Create a `identityProvider` object in the [config file](/docs/configuration/config-file) with the following fields: + + ```json wrap icon="code" + { + "$schema": "https://raw.githubusercontent.com/sourcebot-dev/sourcebot/main/schemas/v3/index.json", + "identityProviders": [ + { + "provider": "authentik", + "purpose": "sso", + "clientId": { + "env": "AUTHENTIK_IDENTITY_PROVIDER_CLIENT_ID" + }, + "clientSecret": { + "env": "AUTHENTIK_IDENTITY_PROVIDER_CLIENT_SECRET" + }, + "issuer": { + "env": "AUTHENTIK_IDENTITY_PROVIDER_ISSUER" + } + } + ] + } + ``` + + + + + diff --git a/docs/snippets/schemas/v3/identityProvider.schema.mdx b/docs/snippets/schemas/v3/identityProvider.schema.mdx index 30c172be..da75427d 100644 --- a/docs/snippets/schemas/v3/identityProvider.schema.mdx +++ b/docs/snippets/schemas/v3/identityProvider.schema.mdx @@ -647,6 +647,115 @@ "purpose", "audience" ] + }, + "AuthentikIdentityProviderConfig": { + "type": "object", + "additionalProperties": false, + "properties": { + "provider": { + "const": "authentik" + }, + "purpose": { + "const": "sso" + }, + "clientId": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "clientSecret": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "issuer": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + } + }, + "required": [ + "provider", + "purpose", + "clientId", + "clientSecret", + "issuer" + ] } }, "oneOf": [ @@ -1293,6 +1402,115 @@ "purpose", "audience" ] + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "provider": { + "const": "authentik" + }, + "purpose": { + "const": "sso" + }, + "clientId": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "clientSecret": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "issuer": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + } + }, + "required": [ + "provider", + "purpose", + "clientId", + "clientSecret", + "issuer" + ] } ] } diff --git a/docs/snippets/schemas/v3/index.schema.mdx b/docs/snippets/schemas/v3/index.schema.mdx index 413e51bd..f3da7ed4 100644 --- a/docs/snippets/schemas/v3/index.schema.mdx +++ b/docs/snippets/schemas/v3/index.schema.mdx @@ -5163,6 +5163,115 @@ "purpose", "audience" ] + }, + "AuthentikIdentityProviderConfig": { + "type": "object", + "additionalProperties": false, + "properties": { + "provider": { + "const": "authentik" + }, + "purpose": { + "const": "sso" + }, + "clientId": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "clientSecret": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "issuer": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + } + }, + "required": [ + "provider", + "purpose", + "clientId", + "clientSecret", + "issuer" + ] } }, "oneOf": [ @@ -5809,6 +5918,115 @@ "purpose", "audience" ] + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "provider": { + "const": "authentik" + }, + "purpose": { + "const": "sso" + }, + "clientId": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "clientSecret": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "issuer": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + } + }, + "required": [ + "provider", + "purpose", + "clientId", + "clientSecret", + "issuer" + ] } ] } diff --git a/packages/schemas/src/v3/identityProvider.schema.ts b/packages/schemas/src/v3/identityProvider.schema.ts index 708c3b4c..f3ff4258 100644 --- a/packages/schemas/src/v3/identityProvider.schema.ts +++ b/packages/schemas/src/v3/identityProvider.schema.ts @@ -646,6 +646,115 @@ const schema = { "purpose", "audience" ] + }, + "AuthentikIdentityProviderConfig": { + "type": "object", + "additionalProperties": false, + "properties": { + "provider": { + "const": "authentik" + }, + "purpose": { + "const": "sso" + }, + "clientId": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "clientSecret": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "issuer": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + } + }, + "required": [ + "provider", + "purpose", + "clientId", + "clientSecret", + "issuer" + ] } }, "oneOf": [ @@ -1292,6 +1401,115 @@ const schema = { "purpose", "audience" ] + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "provider": { + "const": "authentik" + }, + "purpose": { + "const": "sso" + }, + "clientId": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "clientSecret": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "issuer": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + } + }, + "required": [ + "provider", + "purpose", + "clientId", + "clientSecret", + "issuer" + ] } ] } as const; diff --git a/packages/schemas/src/v3/identityProvider.type.ts b/packages/schemas/src/v3/identityProvider.type.ts index 31d7a9a8..12cdb0ba 100644 --- a/packages/schemas/src/v3/identityProvider.type.ts +++ b/packages/schemas/src/v3/identityProvider.type.ts @@ -7,7 +7,8 @@ export type IdentityProviderConfig = | OktaIdentityProviderConfig | KeycloakIdentityProviderConfig | MicrosoftEntraIDIdentityProviderConfig - | GCPIAPIdentityProviderConfig; + | GCPIAPIdentityProviderConfig + | AuthentikIdentityProviderConfig; export interface GitHubIdentityProviderConfig { provider: "github"; @@ -255,3 +256,46 @@ export interface GCPIAPIdentityProviderConfig { googleCloudSecret: string; }; } +export interface AuthentikIdentityProviderConfig { + provider: "authentik"; + purpose: "sso"; + clientId: + | { + /** + * The name of the environment variable that contains the token. + */ + env: string; + } + | { + /** + * The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets + */ + googleCloudSecret: string; + }; + clientSecret: + | { + /** + * The name of the environment variable that contains the token. + */ + env: string; + } + | { + /** + * The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets + */ + googleCloudSecret: string; + }; + issuer: + | { + /** + * The name of the environment variable that contains the token. + */ + env: string; + } + | { + /** + * The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets + */ + googleCloudSecret: string; + }; +} diff --git a/packages/schemas/src/v3/index.schema.ts b/packages/schemas/src/v3/index.schema.ts index c7bf374d..f5676ac3 100644 --- a/packages/schemas/src/v3/index.schema.ts +++ b/packages/schemas/src/v3/index.schema.ts @@ -5162,6 +5162,115 @@ const schema = { "purpose", "audience" ] + }, + "AuthentikIdentityProviderConfig": { + "type": "object", + "additionalProperties": false, + "properties": { + "provider": { + "const": "authentik" + }, + "purpose": { + "const": "sso" + }, + "clientId": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "clientSecret": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "issuer": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + } + }, + "required": [ + "provider", + "purpose", + "clientId", + "clientSecret", + "issuer" + ] } }, "oneOf": [ @@ -5808,6 +5917,115 @@ const schema = { "purpose", "audience" ] + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "provider": { + "const": "authentik" + }, + "purpose": { + "const": "sso" + }, + "clientId": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "clientSecret": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + }, + "issuer": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string", + "description": "The name of the environment variable that contains the token." + } + }, + "required": [ + "env" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "googleCloudSecret": { + "type": "string", + "description": "The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets" + } + }, + "required": [ + "googleCloudSecret" + ], + "additionalProperties": false + } + ] + } + }, + "required": [ + "provider", + "purpose", + "clientId", + "clientSecret", + "issuer" + ] } ] } diff --git a/packages/schemas/src/v3/index.type.ts b/packages/schemas/src/v3/index.type.ts index 669a9511..f0e487c4 100644 --- a/packages/schemas/src/v3/index.type.ts +++ b/packages/schemas/src/v3/index.type.ts @@ -33,7 +33,8 @@ export type IdentityProviderConfig = | OktaIdentityProviderConfig | KeycloakIdentityProviderConfig | MicrosoftEntraIDIdentityProviderConfig - | GCPIAPIdentityProviderConfig; + | GCPIAPIdentityProviderConfig + | AuthentikIdentityProviderConfig; export interface SourcebotConfig { $schema?: string; @@ -1401,3 +1402,46 @@ export interface GCPIAPIdentityProviderConfig { googleCloudSecret: string; }; } +export interface AuthentikIdentityProviderConfig { + provider: "authentik"; + purpose: "sso"; + clientId: + | { + /** + * The name of the environment variable that contains the token. + */ + env: string; + } + | { + /** + * The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets + */ + googleCloudSecret: string; + }; + clientSecret: + | { + /** + * The name of the environment variable that contains the token. + */ + env: string; + } + | { + /** + * The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets + */ + googleCloudSecret: string; + }; + issuer: + | { + /** + * The name of the environment variable that contains the token. + */ + env: string; + } + | { + /** + * The resource name of a Google Cloud secret. Must be in the format `projects//secrets//versions/`. See https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets + */ + googleCloudSecret: string; + }; +} diff --git a/packages/web/public/authentik.svg b/packages/web/public/authentik.svg new file mode 100644 index 00000000..9933084d --- /dev/null +++ b/packages/web/public/authentik.svg @@ -0,0 +1 @@ + diff --git a/packages/web/src/ee/features/sso/sso.ts b/packages/web/src/ee/features/sso/sso.ts index a0fe415c..c43b3262 100644 --- a/packages/web/src/ee/features/sso/sso.ts +++ b/packages/web/src/ee/features/sso/sso.ts @@ -1,11 +1,12 @@ import type { IdentityProvider } from "@/auth"; import { onCreateUser } from "@/lib/authUtils"; import { prisma } from "@/prisma"; -import { GCPIAPIdentityProviderConfig, GitHubIdentityProviderConfig, GitLabIdentityProviderConfig, GoogleIdentityProviderConfig, KeycloakIdentityProviderConfig, MicrosoftEntraIDIdentityProviderConfig, OktaIdentityProviderConfig } from "@sourcebot/schemas/v3/index.type"; +import { AuthentikIdentityProviderConfig, GCPIAPIdentityProviderConfig, GitHubIdentityProviderConfig, GitLabIdentityProviderConfig, GoogleIdentityProviderConfig, KeycloakIdentityProviderConfig, MicrosoftEntraIDIdentityProviderConfig, OktaIdentityProviderConfig } from "@sourcebot/schemas/v3/index.type"; import { createLogger, env, getTokenFromConfig, hasEntitlement, loadConfig } from "@sourcebot/shared"; import { OAuth2Client } from "google-auth-library"; import type { User as AuthJsUser } from "next-auth"; import type { Provider } from "next-auth/providers"; +import Authentik from "next-auth/providers/authentik"; import Credentials from "next-auth/providers/credentials"; import GitHub from "next-auth/providers/github"; import Gitlab from "next-auth/providers/gitlab"; @@ -71,6 +72,13 @@ export const getEEIdentityProviders = async (): Promise => { const audience = await getTokenFromConfig(providerConfig.audience); providers.push({ provider: createGCPIAPProvider(audience), purpose: providerConfig.purpose }); } + if (identityProvider.provider === "authentik") { + const providerConfig = identityProvider as AuthentikIdentityProviderConfig; + const clientId = await getTokenFromConfig(providerConfig.clientId); + const clientSecret = await getTokenFromConfig(providerConfig.clientSecret); + const issuer = await getTokenFromConfig(providerConfig.issuer); + providers.push({ provider: createAuthentikProvider(clientId, clientSecret, issuer), purpose: providerConfig.purpose }); + } } // @deprecate in favor of defining identity providers throught the identityProvider object in the config file. This was done to allow for more control over @@ -268,4 +276,12 @@ const createGCPIAPProvider = (audience: string): Provider => { } }, }); +} + +export const createAuthentikProvider = (clientId: string, clientSecret: string, issuer: string): Provider => { + return Authentik({ + clientId: clientId, + clientSecret: clientSecret, + issuer: issuer, + }); } \ No newline at end of file diff --git a/packages/web/src/lib/utils.ts b/packages/web/src/lib/utils.ts index ea229977..4a58b6db 100644 --- a/packages/web/src/lib/utils.ts +++ b/packages/web/src/lib/utils.ts @@ -11,6 +11,7 @@ import googleLogo from "@/public/google.svg"; import oktaLogo from "@/public/okta.svg"; import keycloakLogo from "@/public/keycloak.svg"; import microsoftLogo from "@/public/microsoft_entra.svg"; +import authentikLogo from "@/public/authentik.svg"; import { ServiceError } from "./serviceError"; import { StatusCodes } from "http-status-codes"; import { ErrorCode } from "./errorCodes"; @@ -140,6 +141,15 @@ export const getAuthProviderInfo = (providerId: string): AuthProviderInfo => { src: microsoftLogo, }, }; + case "authentik": + return { + id: "authentik", + name: "Authentik", + displayName: "Authentik", + icon: { + src: authentikLogo, + }, + } case "credentials": return { id: "credentials", diff --git a/schemas/v3/identityProvider.json b/schemas/v3/identityProvider.json index de2e0d11..201c6ca2 100644 --- a/schemas/v3/identityProvider.json +++ b/schemas/v3/identityProvider.json @@ -170,6 +170,28 @@ } }, "required": ["provider", "purpose", "audience"] + }, + "AuthentikIdentityProviderConfig": { + "type": "object", + "additionalProperties": false, + "properties": { + "provider": { + "const": "authentik" + }, + "purpose": { + "const": "sso" + }, + "clientId": { + "$ref": "./shared.json#/definitions/Token" + }, + "clientSecret": { + "$ref": "./shared.json#/definitions/Token" + }, + "issuer": { + "$ref": "./shared.json#/definitions/Token" + } + }, + "required": ["provider", "purpose", "clientId", "clientSecret", "issuer"] } }, "oneOf": [ @@ -193,6 +215,9 @@ }, { "$ref": "#/definitions/GCPIAPIdentityProviderConfig" + }, + { + "$ref": "#/definitions/AuthentikIdentityProviderConfig" } ] }