Files
speckle-server/packages/server/modules/workspaces/clients/oidcProvider.ts
T
Gergő Jedlicska 7fbda629b7 feat(sso): early sso testing
* feat(workspaces): add workspace sso feature flag

* feat(workspaceSso): wip validate sso

* feat(workspaces): validate and add sso provider to the workspace with user sso sessions

* feat(workspaces): validate and add sso provider to the workspace with user sso sessions
2024-10-01 17:15:25 +01:00

82 lines
2.3 KiB
TypeScript

/* eslint-disable camelcase */
import { BaseError } from '@/modules/shared/errors'
import { OIDCProvider, OIDCProviderAttributes } from '@/modules/workspaces/domain/sso'
import { generators, Issuer, type Client } from 'openid-client'
export const getProviderAuthorizationUrl = async ({
provider,
redirectUrl,
codeVerifier
}: {
provider: OIDCProvider
redirectUrl: URL
codeVerifier: string
}): Promise<URL> => {
const { client } = await initializeIssuerAndClient({ provider, redirectUrl })
const code_challenge = generators.codeChallenge(codeVerifier)
return new URL(
client.authorizationUrl({
scope: 'openid email profile',
redirect_uri: redirectUrl.toString(),
code_challenge,
code_challenge_method: 'S256'
})
)
}
export const initializeIssuerAndClient = async ({
provider,
redirectUrl
}: {
provider: OIDCProvider
redirectUrl?: URL
}): Promise<{ issuer: Issuer; client: Client }> => {
const issuer = await Issuer.discover(provider.issuerUrl)
const client = new issuer.Client({
client_id: provider.clientId,
client_secret: provider.clientSecret,
redirect_uris: redirectUrl ? [redirectUrl.toString()] : [],
response_types: ['code']
})
return { issuer, client }
}
export const getOIDCProviderAttributes = async ({
provider
}: {
provider: OIDCProvider
}): Promise<OIDCProviderAttributes> => {
try {
const { issuer, client } = await initializeIssuerAndClient({ provider })
return {
issuer: {
claimsSupported: (issuer.claims_supported as string[] | undefined) ?? [],
grantTypesSupported:
(issuer.grant_types_supported as string[] | undefined) ?? [],
responseTypesSupported:
(issuer.response_types_supported as string[] | undefined) ?? []
},
client: {
grantTypes: (client.grant_types as string[] | undefined) ?? []
}
}
} catch (err) {
if (err instanceof Error) {
if ('code' in err) {
if (err.code === 'ECONNREFUSED')
throw new BaseError(
'cannot connect to the provider, pls check the connection url',
err
)
} else if ('error' in err) {
if (err.error === 'Realm does not exist')
throw new BaseError(
"The realm doesn't exist, please check your url and OIDC config",
err
)
}
}
throw err
}
}