diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts index a4fef17cd..188af00b7 100644 --- a/backend/src/lib/api-docs/constants.ts +++ b/backend/src/lib/api-docs/constants.ts @@ -307,8 +307,40 @@ export const TOKEN_AUTH = { } as const; export const OIDC_AUTH = { + LOGIN: { + identityId: "The ID of the identity to login." + }, + ATTACH: { + identityId: "The ID of the identity to attach the configuration onto.", + oidcDiscoveryUrl: "The URL used to retrieve the OpenID Connect configuration from the identity provider.", + caCert: "The PEM-encoded CA cert for establishing secure communication with the Identity Provider endpoints.", + boundIssuer: "The unique identifier of the identity provider issuing the JWT.", + boundAudiences: "The list of intended recipients.", + boundClaims: "The attributes that should be present in the JWT for it to be valid.", + boundSubject: "The expected principal that is the subject of the JWT.", + accessTokenTrustedIps: "The IPs or CIDR ranges that access tokens can be used from.", + accessTokenTTL: "The lifetime for an acccess token in seconds.", + accessTokenMaxTTL: "The maximum lifetime for an acccess token in seconds.", + accessTokenNumUsesLimit: "The maximum number of times that an access token can be used." + }, + UPDATE: { + identityId: "The ID of the identity to update the auth method for.", + oidcDiscoveryUrl: "The new URL used to retrieve the OpenID Connect configuration from the identity provider.", + caCert: "The new PEM-encoded CA cert for establishing secure communication with the Identity Provider endpoints.", + boundIssuer: "The new unique identifier of the identity provider issuing the JWT.", + boundAudiences: "The new list of intended recipients.", + boundClaims: "The new attributes that should be present in the JWT for it to be valid.", + boundSubject: "The new expected principal that is the subject of the JWT.", + accessTokenTrustedIps: "The new IPs or CIDR ranges that access tokens can be used from.", + accessTokenTTL: "The new lifetime for an acccess token in seconds.", + accessTokenMaxTTL: "The new maximum lifetime for an acccess token in seconds.", + accessTokenNumUsesLimit: "The new maximum number of times that an access token can be used." + }, + RETRIEVE: { + identityId: "The ID of the identity to retrieve the auth method for." + }, REVOKE: { - identityId: "The ID of the identity to revoke." + identityId: "The ID of the identity to revoke the auth method for." } } as const; diff --git a/backend/src/server/routes/v1/identity-oidc-auth-router.ts b/backend/src/server/routes/v1/identity-oidc-auth-router.ts index 7ebcd339f..417947ad7 100644 --- a/backend/src/server/routes/v1/identity-oidc-auth-router.ts +++ b/backend/src/server/routes/v1/identity-oidc-auth-router.ts @@ -30,7 +30,7 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider) schema: { description: "Login with OIDC Auth", body: z.object({ - identityId: z.string().trim(), + identityId: z.string().trim().describe(OIDC_AUTH.LOGIN.identityId), jwt: z.string().trim() }), response: { @@ -85,16 +85,23 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider) } ], params: z.object({ - identityId: z.string().trim() + identityId: z.string().trim().describe(OIDC_AUTH.ATTACH.identityId) }), body: z.object({ + oidcDiscoveryUrl: z.string().url().min(1).describe(OIDC_AUTH.ATTACH.oidcDiscoveryUrl), + caCert: z.string().trim().default("").describe(OIDC_AUTH.ATTACH.caCert), + boundIssuer: z.string().min(1).describe(OIDC_AUTH.ATTACH.boundIssuer), + boundAudiences: validateOidcAuthAudiencesField.describe(OIDC_AUTH.ATTACH.boundAudiences), + boundClaims: validateOidcBoundClaimsField.describe(OIDC_AUTH.ATTACH.boundClaims), + boundSubject: z.string().optional().default("").describe(OIDC_AUTH.ATTACH.boundSubject), accessTokenTrustedIps: z .object({ ipAddress: z.string().trim() }) .array() .min(1) - .default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }]), + .default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }]) + .describe(OIDC_AUTH.ATTACH.accessTokenTrustedIps), accessTokenTTL: z .number() .int() @@ -102,21 +109,17 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider) .refine((value) => value !== 0, { message: "accessTokenTTL must have a non zero number" }) - .default(2592000), + .default(2592000) + .describe(OIDC_AUTH.ATTACH.accessTokenTTL), accessTokenMaxTTL: z .number() .int() .refine((value) => value !== 0, { message: "accessTokenMaxTTL must have a non zero number" }) - .default(2592000), - accessTokenNumUsesLimit: z.number().int().min(0).default(0), - oidcDiscoveryUrl: z.string().url().min(1), - caCert: z.string().trim().default(""), - boundIssuer: z.string().min(1), - boundAudiences: validateOidcAuthAudiencesField, - boundClaims: validateOidcBoundClaimsField, - boundSubject: z.string().optional().default("") + .default(2592000) + .describe(OIDC_AUTH.ATTACH.accessTokenMaxTTL), + accessTokenNumUsesLimit: z.number().int().min(0).default(0).describe(OIDC_AUTH.ATTACH.accessTokenNumUsesLimit) }), response: { 200: z.object({ @@ -176,17 +179,24 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider) } ], params: z.object({ - identityId: z.string().trim() + identityId: z.string().trim().describe(OIDC_AUTH.UPDATE.identityId) }), body: z .object({ + oidcDiscoveryUrl: z.string().url().min(1).describe(OIDC_AUTH.UPDATE.oidcDiscoveryUrl), + caCert: z.string().trim().default("").describe(OIDC_AUTH.UPDATE.caCert), + boundIssuer: z.string().min(1).describe(OIDC_AUTH.UPDATE.boundIssuer), + boundAudiences: validateOidcAuthAudiencesField.describe(OIDC_AUTH.UPDATE.boundAudiences), + boundClaims: validateOidcBoundClaimsField.describe(OIDC_AUTH.UPDATE.boundClaims), + boundSubject: z.string().optional().default("").describe(OIDC_AUTH.UPDATE.boundSubject), accessTokenTrustedIps: z .object({ ipAddress: z.string().trim() }) .array() .min(1) - .default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }]), + .default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }]) + .describe(OIDC_AUTH.UPDATE.accessTokenTrustedIps), accessTokenTTL: z .number() .int() @@ -194,21 +204,18 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider) .refine((value) => value !== 0, { message: "accessTokenTTL must have a non zero number" }) - .default(2592000), + .default(2592000) + .describe(OIDC_AUTH.UPDATE.accessTokenTTL), accessTokenMaxTTL: z .number() .int() .refine((value) => value !== 0, { message: "accessTokenMaxTTL must have a non zero number" }) - .default(2592000), - accessTokenNumUsesLimit: z.number().int().min(0).default(0), - oidcDiscoveryUrl: z.string().url().min(1), - caCert: z.string().trim().default(""), - boundIssuer: z.string().min(1), - boundAudiences: validateOidcAuthAudiencesField, - boundClaims: validateOidcBoundClaimsField, - boundSubject: z.string().optional().default("") + .default(2592000) + .describe(OIDC_AUTH.UPDATE.accessTokenMaxTTL), + + accessTokenNumUsesLimit: z.number().int().min(0).default(0).describe(OIDC_AUTH.UPDATE.accessTokenNumUsesLimit) }) .partial(), response: { @@ -267,7 +274,7 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider) } ], params: z.object({ - identityId: z.string() + identityId: z.string().describe(OIDC_AUTH.RETRIEVE.identityId) }), response: { 200: z.object({ diff --git a/docs/api-reference/endpoints/oidc-auth/attach.mdx b/docs/api-reference/endpoints/oidc-auth/attach.mdx new file mode 100644 index 000000000..c75bdc69f --- /dev/null +++ b/docs/api-reference/endpoints/oidc-auth/attach.mdx @@ -0,0 +1,4 @@ +--- +title: "Attach" +openapi: "POST /api/v1/auth/oidc-auth/identities/{identityId}" +--- diff --git a/docs/api-reference/endpoints/oidc-auth/login.mdx b/docs/api-reference/endpoints/oidc-auth/login.mdx new file mode 100644 index 000000000..baac1bef9 --- /dev/null +++ b/docs/api-reference/endpoints/oidc-auth/login.mdx @@ -0,0 +1,4 @@ +--- +title: "Login" +openapi: "POST /api/v1/auth/oidc-auth/login" +--- diff --git a/docs/api-reference/endpoints/oidc-auth/retrieve.mdx b/docs/api-reference/endpoints/oidc-auth/retrieve.mdx new file mode 100644 index 000000000..a870ffc03 --- /dev/null +++ b/docs/api-reference/endpoints/oidc-auth/retrieve.mdx @@ -0,0 +1,4 @@ +--- +title: "Retrieve" +openapi: "GET /api/v1/auth/oidc-auth/identities/{identityId}" +--- diff --git a/docs/api-reference/endpoints/oidc-auth/revoke.mdx b/docs/api-reference/endpoints/oidc-auth/revoke.mdx new file mode 100644 index 000000000..df46d6c45 --- /dev/null +++ b/docs/api-reference/endpoints/oidc-auth/revoke.mdx @@ -0,0 +1,4 @@ +--- +title: "Revoke" +openapi: "DELETE /api/v1/auth/oidc-auth/identities/{identityId}" +--- diff --git a/docs/api-reference/endpoints/oidc-auth/update.mdx b/docs/api-reference/endpoints/oidc-auth/update.mdx new file mode 100644 index 000000000..0d29c3db7 --- /dev/null +++ b/docs/api-reference/endpoints/oidc-auth/update.mdx @@ -0,0 +1,4 @@ +--- +title: "Update" +openapi: "PATCH /api/v1/auth/oidc-auth/identities/{identityId}" +--- diff --git a/docs/mint.json b/docs/mint.json index a0082782d..1f66220f4 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -497,6 +497,16 @@ "api-reference/endpoints/kubernetes-auth/revoke" ] }, + { + "group": "OIDC Auth", + "pages": [ + "api-reference/endpoints/oidc-auth/login", + "api-reference/endpoints/oidc-auth/attach", + "api-reference/endpoints/oidc-auth/retrieve", + "api-reference/endpoints/oidc-auth/update", + "api-reference/endpoints/oidc-auth/revoke" + ] + }, { "group": "Organizations", "pages": [