Files
speckle-server/packages/server/modules/workspaces/helpers/sso.ts
T
andrewwallacespeckle d3931f1855 feat(fe2): Frontend SSO Integration (#3464)
* Readd work from old branch

* Improved Login.vue

* Replace watch with onResult

* Server: Error improvement

* FE Middleware

* Update style

* Delete Sso. Mixpanel events

* Updates

* Improved loading state

* Invites. Register sso page

* Middleware improvements. Session error no logout

* Changes from deisgns

* Swap button to LayoutMenu

* Improve middleware

* Remove typo

* Fix errormessage

* Remove edit functionality

* New composable file for sso

* Improved names for composables. Tidyups

* Reactive errors

* Reorder Login.vue

* Improved Typeguard

* Enum

* Comments from Mike

* Add error toast

* Remove FormButton from LoginButtonBase

* Use linkComponent prop

* Move workspace select to new component

* Fragmentation

* Fix loading useFetch

* use WorkspaceAvatar

* Feature flag sso button

* Update fragment name

* Skip middleware during auth flow

* Add rules to Workspace Selector

* Reactive useWorkspacePublicSsoCheck

* AuthRegisterNewsletter types

* v-bind on Select

* Fragment WrapperSecurity

* Remove useForm from Form.vue

* Reactive values in composables

* Prevent infinite loading when no invite found

* useWorkspaceSsoValidation maybeRef

* Added comment to requireSsoEnabled

* Bugfix

* Update Button.vue

* Fix form

* Update valid model middleware

* Update LoginButtonBase.vue

* NewsletterConset ref

* use setFieldValue

* Update Login.vue

* Swap mayberef to ref

* Comments from PR

* Changes from call with Fabs

* Fix session-error bug

* Fix circleci

* Small fix to index
2024-11-21 12:50:57 +00:00

82 lines
2.5 KiB
TypeScript

import { getEncryptionKeyPair } from '@/modules/automate/services/encryption'
import { getFrontendOrigin, getServerOrigin } from '@/modules/shared/helpers/envHelper'
import { buildDecryptor, buildEncryptor } from '@/modules/shared/utils/libsodium'
import { SsoVerificationCodeMissingError } from '@/modules/workspaces/errors/sso'
import { Request } from 'express'
declare module 'express-session' {
interface SessionData {
workspaceId?: string
}
}
/**
* Generate Speckle URL to redirect users to after they complete authorization
* with the given SSO provider.
*/
export const buildAuthRedirectUrl = (
workspaceSlug: string,
isValidationFlow: boolean
): URL => {
const urlFragments = [`/api/v1/workspaces/${workspaceSlug}/sso/oidc/callback`]
if (isValidationFlow) {
urlFragments.push('?validate=true')
}
return new URL(urlFragments.join(''), getServerOrigin())
}
/**
* Generate Speckle URL to redirect users to after successfully completing the
* SSO authorization flow.
* @remarks Append params to this URL to preserve information about errors
*/
export const buildFinalizeUrl = (workspaceSlug: string): URL => {
return new URL(`workspaces/${workspaceSlug}/sso`, getFrontendOrigin())
}
/**
* Generate Speckle URL to redirect users to after an error occurs during SSO.
*/
export const buildErrorUrl = (err: unknown, workspaceSlug: string) => {
const errorRedirectUrl = buildFinalizeUrl(workspaceSlug)
let errorMessage: string
if (err instanceof Error) {
errorMessage = `${err.message}`
} else {
errorMessage = `Unknown error: ${JSON.stringify(err)}`
}
errorRedirectUrl.searchParams.set('error', errorMessage)
return errorRedirectUrl.toString()
}
export const getEncryptor = () => async (data: string) => {
const encryptionKeyPair = await getEncryptionKeyPair()
const encryptor = await buildEncryptor(encryptionKeyPair.publicKey)
const encryptedData = await encryptor.encrypt(data)
encryptor.dispose()
return encryptedData
}
export const getDecryptor = () => async (data: string) => {
const encryptionKeyPair = await getEncryptionKeyPair()
const decryptor = await buildDecryptor(encryptionKeyPair)
const decryptedData = await decryptor.decrypt(data)
decryptor.dispose()
return decryptedData
}
export const parseCodeVerifier = async (req: Request<unknown>): Promise<string> => {
const encryptedCodeVerifier = req.session.codeVerifier
if (!encryptedCodeVerifier) throw new SsoVerificationCodeMissingError()
const codeVerifier = await getDecryptor()(encryptedCodeVerifier)
return codeVerifier
}