in packages/better-auth/src/plugins/sso/index.ts [80:361]
createOIDCProvider: createAuthEndpoint(
"/sso/register",
{
method: "POST",
body: z.object({
providerId: z.string({
description:
"The ID of the provider. This is used to identify the provider during login and callback",
}),
issuer: z.string({
description:
"The issuer url of the provider (e.g. https://idp.example.com)",
}),
domain: z.string({
description:
"The domain of the provider. This is used for email matching",
}),
clientId: z.string({
description: "The client ID",
}),
clientSecret: z.string({
description: "The client secret",
}),
authorizationEndpoint: z
.string({
description: "The authorization endpoint",
})
.optional(),
tokenEndpoint: z
.string({
description: "The token endpoint",
})
.optional(),
userInfoEndpoint: z
.string({
description: "The user info endpoint",
})
.optional(),
tokenEndpointAuthentication: z
.enum(["client_secret_post", "client_secret_basic"])
.optional(),
jwksEndpoint: z
.string({
description: "The JWKS endpoint",
})
.optional(),
discoveryEndpoint: z.string().optional(),
scopes: z
.array(z.string(), {
description:
"The scopes to request. Defaults to ['openid', 'email', 'profile', 'offline_access']",
})
.optional(),
pkce: z
.boolean({
description: "Whether to use PKCE for the authorization flow",
})
.default(true)
.optional(),
mapping: z
.object({
id: z.string({
description:
"The field in the user info response that contains the id. Defaults to 'sub'",
}),
email: z.string({
description:
"The field in the user info response that contains the email. Defaults to 'email'",
}),
emailVerified: z
.string({
description:
"The field in the user info response that contains whether the email is verified. defaults to 'email_verified'",
})
.optional(),
name: z.string({
description:
"The field in the user info response that contains the name. Defaults to 'name'",
}),
image: z
.string({
description:
"The field in the user info response that contains the image. Defaults to 'picture'",
})
.optional(),
extraFields: z.record(z.string()).optional(),
})
.optional(),
organizationId: z
.string({
description:
"If organization plugin is enabled, the organization id to link the provider to",
})
.optional(),
overrideUserInfo: z
.boolean({
description:
"Override user info with the provider info. Defaults to false",
})
.default(false)
.optional(),
}),
use: [sessionMiddleware],
metadata: {
openapi: {
summary: "Register an OIDC provider",
description:
"This endpoint is used to register an OIDC provider. This is used to configure the provider and link it to an organization",
responses: {
"200": {
description: "OIDC provider created successfully",
content: {
"application/json": {
schema: {
type: "object",
properties: {
issuer: {
type: "string",
format: "uri",
description: "The issuer URL of the provider",
},
domain: {
type: "string",
description:
"The domain of the provider, used for email matching",
},
oidcConfig: {
type: "object",
properties: {
issuer: {
type: "string",
format: "uri",
description: "The issuer URL of the provider",
},
pkce: {
type: "boolean",
description:
"Whether PKCE is enabled for the authorization flow",
},
clientId: {
type: "string",
description: "The client ID for the provider",
},
clientSecret: {
type: "string",
description:
"The client secret for the provider",
},
authorizationEndpoint: {
type: "string",
format: "uri",
nullable: true,
description: "The authorization endpoint URL",
},
discoveryEndpoint: {
type: "string",
format: "uri",
description: "The discovery endpoint URL",
},
userInfoEndpoint: {
type: "string",
format: "uri",
nullable: true,
description: "The user info endpoint URL",
},
scopes: {
type: "array",
items: { type: "string" },
nullable: true,
description:
"The scopes requested from the provider",
},
tokenEndpoint: {
type: "string",
format: "uri",
nullable: true,
description: "The token endpoint URL",
},
tokenEndpointAuthentication: {
type: "string",
enum: [
"client_secret_post",
"client_secret_basic",
],
nullable: true,
description:
"Authentication method for the token endpoint",
},
jwksEndpoint: {
type: "string",
format: "uri",
nullable: true,
description: "The JWKS endpoint URL",
},
mapping: {
type: "object",
nullable: true,
properties: {
id: {
type: "string",
description:
"Field mapping for user ID (defaults to 'sub')",
},
email: {
type: "string",
description:
"Field mapping for email (defaults to 'email')",
},
emailVerified: {
type: "string",
nullable: true,
description:
"Field mapping for email verification (defaults to 'email_verified')",
},
name: {
type: "string",
description:
"Field mapping for name (defaults to 'name')",
},
image: {
type: "string",
nullable: true,
description:
"Field mapping for image (defaults to 'picture')",
},
extraFields: {
type: "object",
additionalProperties: { type: "string" },
nullable: true,
description: "Additional field mappings",
},
},
required: ["id", "email", "name"],
},
},
required: [
"issuer",
"pkce",
"clientId",
"clientSecret",
"discoveryEndpoint",
],
description: "OIDC configuration for the provider",
},
organizationId: {
type: "string",
nullable: true,
description:
"ID of the linked organization, if any",
},
userId: {
type: "string",
description:
"ID of the user who registered the provider",
},
providerId: {
type: "string",
description: "Unique identifier for the provider",
},
redirectURI: {
type: "string",
format: "uri",
description:
"The redirect URI for the provider callback",
},
},
required: [
"issuer",
"domain",
"oidcConfig",
"userId",
"providerId",
"redirectURI",
],
},
},
},
},
},
},
},
},