0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-06 20:40:08 -05:00

refactor(core,schemas): refactor the sso connector factory type (#5541)

* refactor(core,schemas): refactor the sso connector factory type

refactor the sso connector factory type and add providerType to the config data

* fix(core): fix ut

fix ut

* refactor(schemas): add the providerType to the providerDetails return type

add the new providerType property to the providerDetails return type
This commit is contained in:
simeng-li 2024-03-27 11:10:48 +08:00 committed by GitHub
parent 592d4672f0
commit 92d45f2432
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 113 additions and 98 deletions

View file

@ -7,7 +7,7 @@ import {
singleSignOnConnectorSessionGuard,
singleSignOnInteractionIdentifierResultGuard,
type SingleSignOnInteractionIdentifierResult,
} from '#src/sso/types/session.js';
} from '#src/sso/index.js';
import assertThat from '#src/utils/assert-that.js';
/**

View file

@ -6,7 +6,7 @@ import RequestError from '#src/errors/RequestError/index.js';
import { type WithLogContext } from '#src/middleware/koa-audit-log.js';
import { OidcSsoConnector } from '#src/sso/OidcSsoConnector/index.js';
import { ssoConnectorFactories } from '#src/sso/index.js';
import { type SingleSignOnConnectorData } from '#src/sso/types/index.js';
import { type SingleSignOnConnectorData } from '#src/sso/types/connector.js';
import { createMockLogContext } from '#src/test-utils/koa-audit-log.js';
import { createMockProvider } from '#src/test-utils/oidc-provider.js';
import { MockTenant } from '#src/test-utils/tenant.js';

View file

@ -13,8 +13,7 @@ import { z } from 'zod';
import RequestError from '#src/errors/RequestError/index.js';
import { type WithLogContext } from '#src/middleware/koa-audit-log.js';
import { type WithInteractionDetailsContext } from '#src/routes/interaction/middleware/koa-interaction-details.js';
import { ssoConnectorFactories } from '#src/sso/index.js';
import { type SingleSignOnConnectorSession } from '#src/sso/types/index.js';
import { ssoConnectorFactories, type SingleSignOnConnectorSession } from '#src/sso/index.js';
import type Queries from '#src/tenants/Queries.js';
import type TenantContext from '#src/tenants/TenantContext.js';
import assertThat from '#src/utils/assert-that.js';

View file

@ -20,11 +20,12 @@ const mockTenantId = 'mock_tenant_id';
describe('parseFactoryDetail', () => {
it.each(Object.values(SsoProviderName))('should return correct detail for %s', (providerName) => {
const { logo, logoDark, description, name } = ssoConnectorFactories[providerName];
const { logo, logoDark, description, name, providerType } = ssoConnectorFactories[providerName];
const detail = parseFactoryDetail(ssoConnectorFactories[providerName], 'en');
expect(detail).toEqual({
providerName,
providerType,
logo,
logoDark,
description: description.en,
@ -35,11 +36,13 @@ describe('parseFactoryDetail', () => {
it.each(Object.values(SsoProviderName))(
'should return correct detail for %s with unknown locale',
(providerName) => {
const { logo, logoDark, description, name } = ssoConnectorFactories[providerName];
const { logo, logoDark, description, name, providerType } =
ssoConnectorFactories[providerName];
const detail = parseFactoryDetail(ssoConnectorFactories[providerName], 'zh');
expect(detail).toEqual({
providerName,
providerType,
logo,
logoDark,
description: description.en,

View file

@ -11,7 +11,7 @@ import { trySafe } from '@silverhand/essentials';
import RequestError from '#src/errors/RequestError/index.js';
import SamlConnector from '#src/sso/SamlConnector/index.js';
import { type SingleSignOnFactory, ssoConnectorFactories } from '#src/sso/index.js';
import { type SingleSignOnConnectorData } from '#src/sso/types/index.js';
import { type SingleSignOnConnectorData } from '#src/sso/types/connector.js';
const isKeyOfI18nPhrases = (key: string, phrases: I18nPhrases): key is keyof I18nPhrases =>
key in phrases;
@ -20,10 +20,11 @@ export const parseFactoryDetail = (
factory: SingleSignOnFactory<SsoProviderName>,
locale: string
) => {
const { providerName, logo, logoDark, description, name } = factory;
const { providerName, logo, logoDark, description, name, providerType } = factory;
return {
providerName,
providerType,
logo,
logoDark,
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- falsy value expected
@ -61,7 +62,7 @@ export const fetchConnectorProviderDetails = async (
): Promise<SsoConnectorWithProviderConfig> => {
const { providerName } = connector;
const { logo, logoDark, constructor, name } = ssoConnectorFactories[providerName];
const { logo, logoDark, constructor, name, providerType } = ssoConnectorFactories[providerName];
/*
Safely fetch and parse the detailed connector config from provider.
@ -76,6 +77,7 @@ export const fetchConnectorProviderDetails = async (
...connector,
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- falsy value expected
name: (isKeyOfI18nPhrases(locale, name) && name[locale]) || name.en,
providerType,
providerLogo: logo,
providerLogoDark: logoDark,
providerConfig,

View file

@ -1,4 +1,4 @@
import { SsoProviderName } from '@logto/schemas';
import { SsoProviderName, SsoProviderType } from '@logto/schemas';
import { SamlSsoConnector } from '../SamlSsoConnector/index.js';
import { type SingleSignOnFactory } from '../index.js';
@ -8,6 +8,7 @@ export class AzureAdSsoConnector extends SamlSsoConnector {}
export const azureAdSsoConnectorFactory: SingleSignOnFactory<SsoProviderName.AZURE_AD> = {
providerName: SsoProviderName.AZURE_AD,
providerType: SsoProviderType.SAML,
logo: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTUuMDY5MzQgMTguNzA5N0M1LjU4NjY3IDE5LjAzMjMgNi40NDY2NyAxOS4zOTEgNy4zNTYgMTkuMzkxQzguMTg0IDE5LjM5MSA4Ljk1MzM0IDE5LjE1MSA5LjU5MDY3IDE4Ljc0MTdDOS41OTA2NyAxOC43NDE3IDkuNTkyIDE4Ljc0MTcgOS41OTMzNCAxOC43NDAzTDEyIDE3LjIzNjNWMjIuNjY3QzExLjYxODcgMjIuNjY3IDExLjIzNDcgMjIuNTYzIDEwLjkwMTMgMjIuMzU1TDUuMDY5MzQgMTguNzA5N1oiIGZpbGw9IiMyMjUwODYiLz4KPHBhdGggZD0iTTEwLjQ3MDcgMi4wMDkwMUwwLjQ3MDY2MiAxMy4yODlDLTAuMzAxMzM4IDE0LjE2MSAtMC4xMDAwMDUgMTUuNDc4MyAwLjkwMTMyOCAxNi4xMDM3QzAuOTAxMzI4IDE2LjEwMzcgNC42MDI2NiAxOC40MTcgNS4wNjkzMyAxOC43MDlDNS41ODY2NiAxOS4wMzE3IDYuNDQ2NjYgMTkuMzkwMyA3LjM1NTk5IDE5LjM5MDNDOC4xODM5OSAxOS4zOTAzIDguOTUzMzMgMTkuMTUwMyA5LjU5MDY2IDE4Ljc0MUM5LjU5MDY2IDE4Ljc0MSA5LjU5MTk5IDE4Ljc0MSA5LjU5MzMzIDE4LjczOTdMMTIgMTcuMjM1N0w2LjE4MTMzIDEzLjU5ODNMMTIuMDAxMyA3LjAzMzAxVjEuMzMzMDFDMTEuNDM2IDEuMzMzMDEgMTAuODcwNyAxLjU1ODM0IDEwLjQ3MDcgMi4wMDkwMVoiIGZpbGw9IiM2NkRERkYiLz4KPHBhdGggZD0iTTYuMTgxMjcgMTMuNTk5NUw2LjI1MDYxIDEzLjY0MjJMMTEuOTk5OSAxNy4yMzY4SDEyLjAwMTNWNy4wMzU1MUwxMS45OTk5IDcuMDM0MThMNi4xODEyNyAxMy41OTk1WiIgZmlsbD0iI0NCRjhGRiIvPgo8cGF0aCBkPSJNMjMuMDk4NyAxNi4xMDRDMjQuMSAxNS40Nzg3IDI0LjMwMTMgMTQuMTYxMyAyMy41MjkzIDEzLjI4OTNMMTYuOTY4IDUuODg4QzE2LjQzODcgNS42NDEzMyAxNS44NDUzIDUuNSAxNS4yMTczIDUuNUMxMy45ODQgNS41IDEyLjg4MTMgNi4wMzIgMTIuMTQ4IDYuODY4TDEyLjAwMjcgNy4wMzJMMTcuODIxMyAxMy41OTczTDEyLjAwMTMgMTcuMjM0N1YyMi42NjUzQzEyLjM4NCAyMi42NjUzIDEyLjc2NTMgMjIuNTYxMyAxMy4wOTg3IDIyLjM1MzNMMjMuMDk4NyAxNi4xMDI3VjE2LjEwNFoiIGZpbGw9IiMwNzQ3OTMiLz4KPHBhdGggZD0iTTEyLjAwMTMgMS4zMzMwMVY3LjAzMzAxTDEyLjE0NjcgNi44NjkwMUMxMi44OCA2LjAzMzAxIDEzLjk4MjcgNS41MDEwMSAxNS4yMTYgNS41MDEwMUMxNS44NDUzIDUuNTAxMDEgMTYuNDM3MyA1LjY0MzY3IDE2Ljk2NjcgNS44ODkwMUwxMy41MjggMi4wMTAzNEMxMy4xMjkzIDEuNTU5NjcgMTIuNTY0IDEuMzM0MzQgMTIgMS4zMzQzNEwxMi4wMDEzIDEuMzMzMDFaIiBmaWxsPSIjMDI5NEU0Ii8+CjxwYXRoIGQ9Ik0xNy44MiAxMy41OTkyTDEyLjAwMTMgNy4wMzUxNlYxNy4yMzUyTDE3LjgyIDEzLjU5OTJaIiBmaWxsPSIjOTZCQ0MyIi8+Cjwvc3ZnPgo=',
logoDark:
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTUuMDY5MzQgMTguNzA5N0M1LjU4NjY3IDE5LjAzMjMgNi40NDY2NyAxOS4zOTEgNy4zNTYgMTkuMzkxQzguMTg0IDE5LjM5MSA4Ljk1MzM0IDE5LjE1MSA5LjU5MDY3IDE4Ljc0MTdDOS41OTA2NyAxOC43NDE3IDkuNTkyIDE4Ljc0MTcgOS41OTMzNCAxOC43NDAzTDEyIDE3LjIzNjNWMjIuNjY3QzExLjYxODcgMjIuNjY3IDExLjIzNDcgMjIuNTYzIDEwLjkwMTMgMjIuMzU1TDUuMDY5MzQgMTguNzA5N1oiIGZpbGw9IiMyMjUwODYiLz4KPHBhdGggZD0iTTEwLjQ3MDcgMi4wMDkwMUwwLjQ3MDY2MiAxMy4yODlDLTAuMzAxMzM4IDE0LjE2MSAtMC4xMDAwMDUgMTUuNDc4MyAwLjkwMTMyOCAxNi4xMDM3QzAuOTAxMzI4IDE2LjEwMzcgNC42MDI2NiAxOC40MTcgNS4wNjkzMyAxOC43MDlDNS41ODY2NiAxOS4wMzE3IDYuNDQ2NjYgMTkuMzkwMyA3LjM1NTk5IDE5LjM5MDNDOC4xODM5OSAxOS4zOTAzIDguOTUzMzMgMTkuMTUwMyA5LjU5MDY2IDE4Ljc0MUM5LjU5MDY2IDE4Ljc0MSA5LjU5MTk5IDE4Ljc0MSA5LjU5MzMzIDE4LjczOTdMMTIgMTcuMjM1N0w2LjE4MTMzIDEzLjU5ODNMMTIuMDAxMyA3LjAzMzAxVjEuMzMzMDFDMTEuNDM2IDEuMzMzMDEgMTAuODcwNyAxLjU1ODM0IDEwLjQ3MDcgMi4wMDkwMVoiIGZpbGw9IiM2NkRERkYiLz4KPHBhdGggZD0iTTYuMTgxMjcgMTMuNTk5NUw2LjI1MDYxIDEzLjY0MjJMMTEuOTk5OSAxNy4yMzY4SDEyLjAwMTNWNy4wMzU1MUwxMS45OTk5IDcuMDM0MThMNi4xODEyNyAxMy41OTk1WiIgZmlsbD0iI0NCRjhGRiIvPgo8cGF0aCBkPSJNMjMuMDk4NyAxNi4xMDRDMjQuMSAxNS40Nzg3IDI0LjMwMTMgMTQuMTYxMyAyMy41MjkzIDEzLjI4OTNMMTYuOTY4IDUuODg4QzE2LjQzODcgNS42NDEzMyAxNS44NDUzIDUuNSAxNS4yMTczIDUuNUMxMy45ODQgNS41IDEyLjg4MTMgNi4wMzIgMTIuMTQ4IDYuODY4TDEyLjAwMjcgNy4wMzJMMTcuODIxMyAxMy41OTczTDEyLjAwMTMgMTcuMjM0N1YyMi42NjUzQzEyLjM4NCAyMi42NjUzIDEyLjc2NTMgMjIuNTYxMyAxMy4wOTg3IDIyLjM1MzNMMjMuMDk4NyAxNi4xMDI3VjE2LjEwNFoiIGZpbGw9IiMwNzQ3OTMiLz4KPHBhdGggZD0iTTEyLjAwMTMgMS4zMzMwMVY3LjAzMzAxTDEyLjE0NjcgNi44NjkwMUMxMi44OCA2LjAzMzAxIDEzLjk4MjcgNS41MDEwMSAxNS4yMTYgNS41MDEwMUMxNS44NDUzIDUuNTAxMDEgMTYuNDM3MyA1LjY0MzY3IDE2Ljk2NjcgNS44ODkwMUwxMy41MjggMi4wMTAzNEMxMy4xMjkzIDEuNTU5NjcgMTIuNTY0IDEuMzM0MzQgMTIgMS4zMzQzNEwxMi4wMDEzIDEuMzMzMDFaIiBmaWxsPSIjMDI5NEU0Ii8+CjxwYXRoIGQ9Ik0xNy44MiAxMy41OTkyTDEyLjAwMTMgNy4wMzUxNlYxNy4yMzUyTDE3LjgyIDEzLjU5OTJaIiBmaWxsPSIjOTZCQ0MyIi8+Cjwvc3ZnPgo=',

View file

@ -1,4 +1,4 @@
import { SsoProviderName } from '@logto/schemas';
import { SsoProviderName, SsoProviderType } from '@logto/schemas';
import { conditional } from '@silverhand/essentials';
import camelcaseKeys from 'camelcase-keys';
@ -65,6 +65,7 @@ export class AzureOidcSsoConnector extends OidcSsoConnector {
export const azureOidcSsoConnectorFactory: SingleSignOnFactory<SsoProviderName.AZURE_AD_OIDC> = {
providerName: SsoProviderName.AZURE_AD_OIDC,
providerType: SsoProviderType.OIDC,
logo: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTUuMDY5MzQgMTguNzA5N0M1LjU4NjY3IDE5LjAzMjMgNi40NDY2NyAxOS4zOTEgNy4zNTYgMTkuMzkxQzguMTg0IDE5LjM5MSA4Ljk1MzM0IDE5LjE1MSA5LjU5MDY3IDE4Ljc0MTdDOS41OTA2NyAxOC43NDE3IDkuNTkyIDE4Ljc0MTcgOS41OTMzNCAxOC43NDAzTDEyIDE3LjIzNjNWMjIuNjY3QzExLjYxODcgMjIuNjY3IDExLjIzNDcgMjIuNTYzIDEwLjkwMTMgMjIuMzU1TDUuMDY5MzQgMTguNzA5N1oiIGZpbGw9IiMyMjUwODYiLz4KPHBhdGggZD0iTTEwLjQ3MDcgMi4wMDkwMUwwLjQ3MDY2MiAxMy4yODlDLTAuMzAxMzM4IDE0LjE2MSAtMC4xMDAwMDUgMTUuNDc4MyAwLjkwMTMyOCAxNi4xMDM3QzAuOTAxMzI4IDE2LjEwMzcgNC42MDI2NiAxOC40MTcgNS4wNjkzMyAxOC43MDlDNS41ODY2NiAxOS4wMzE3IDYuNDQ2NjYgMTkuMzkwMyA3LjM1NTk5IDE5LjM5MDNDOC4xODM5OSAxOS4zOTAzIDguOTUzMzMgMTkuMTUwMyA5LjU5MDY2IDE4Ljc0MUM5LjU5MDY2IDE4Ljc0MSA5LjU5MTk5IDE4Ljc0MSA5LjU5MzMzIDE4LjczOTdMMTIgMTcuMjM1N0w2LjE4MTMzIDEzLjU5ODNMMTIuMDAxMyA3LjAzMzAxVjEuMzMzMDFDMTEuNDM2IDEuMzMzMDEgMTAuODcwNyAxLjU1ODM0IDEwLjQ3MDcgMi4wMDkwMVoiIGZpbGw9IiM2NkRERkYiLz4KPHBhdGggZD0iTTYuMTgxMjcgMTMuNTk5NUw2LjI1MDYxIDEzLjY0MjJMMTEuOTk5OSAxNy4yMzY4SDEyLjAwMTNWNy4wMzU1MUwxMS45OTk5IDcuMDM0MThMNi4xODEyNyAxMy41OTk1WiIgZmlsbD0iI0NCRjhGRiIvPgo8cGF0aCBkPSJNMjMuMDk4NyAxNi4xMDRDMjQuMSAxNS40Nzg3IDI0LjMwMTMgMTQuMTYxMyAyMy41MjkzIDEzLjI4OTNMMTYuOTY4IDUuODg4QzE2LjQzODcgNS42NDEzMyAxNS44NDUzIDUuNSAxNS4yMTczIDUuNUMxMy45ODQgNS41IDEyLjg4MTMgNi4wMzIgMTIuMTQ4IDYuODY4TDEyLjAwMjcgNy4wMzJMMTcuODIxMyAxMy41OTczTDEyLjAwMTMgMTcuMjM0N1YyMi42NjUzQzEyLjM4NCAyMi42NjUzIDEyLjc2NTMgMjIuNTYxMyAxMy4wOTg3IDIyLjM1MzNMMjMuMDk4NyAxNi4xMDI3VjE2LjEwNFoiIGZpbGw9IiMwNzQ3OTMiLz4KPHBhdGggZD0iTTEyLjAwMTMgMS4zMzMwMVY3LjAzMzAxTDEyLjE0NjcgNi44NjkwMUMxMi44OCA2LjAzMzAxIDEzLjk4MjcgNS41MDEwMSAxNS4yMTYgNS41MDEwMUMxNS44NDUzIDUuNTAxMDEgMTYuNDM3MyA1LjY0MzY3IDE2Ljk2NjcgNS44ODkwMUwxMy41MjggMi4wMTAzNEMxMy4xMjkzIDEuNTU5NjcgMTIuNTY0IDEuMzM0MzQgMTIgMS4zMzQzNEwxMi4wMDEzIDEuMzMzMDFaIiBmaWxsPSIjMDI5NEU0Ii8+CjxwYXRoIGQ9Ik0xNy44MiAxMy41OTkyTDEyLjAwMTMgNy4wMzUxNlYxNy4yMzUyTDE3LjgyIDEzLjU5OTJaIiBmaWxsPSIjOTZCQ0MyIi8+Cjwvc3ZnPgo=',
logoDark:
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTUuMDY5MzQgMTguNzA5N0M1LjU4NjY3IDE5LjAzMjMgNi40NDY2NyAxOS4zOTEgNy4zNTYgMTkuMzkxQzguMTg0IDE5LjM5MSA4Ljk1MzM0IDE5LjE1MSA5LjU5MDY3IDE4Ljc0MTdDOS41OTA2NyAxOC43NDE3IDkuNTkyIDE4Ljc0MTcgOS41OTMzNCAxOC43NDAzTDEyIDE3LjIzNjNWMjIuNjY3QzExLjYxODcgMjIuNjY3IDExLjIzNDcgMjIuNTYzIDEwLjkwMTMgMjIuMzU1TDUuMDY5MzQgMTguNzA5N1oiIGZpbGw9IiMyMjUwODYiLz4KPHBhdGggZD0iTTEwLjQ3MDcgMi4wMDkwMUwwLjQ3MDY2MiAxMy4yODlDLTAuMzAxMzM4IDE0LjE2MSAtMC4xMDAwMDUgMTUuNDc4MyAwLjkwMTMyOCAxNi4xMDM3QzAuOTAxMzI4IDE2LjEwMzcgNC42MDI2NiAxOC40MTcgNS4wNjkzMyAxOC43MDlDNS41ODY2NiAxOS4wMzE3IDYuNDQ2NjYgMTkuMzkwMyA3LjM1NTk5IDE5LjM5MDNDOC4xODM5OSAxOS4zOTAzIDguOTUzMzMgMTkuMTUwMyA5LjU5MDY2IDE4Ljc0MUM5LjU5MDY2IDE4Ljc0MSA5LjU5MTk5IDE4Ljc0MSA5LjU5MzMzIDE4LjczOTdMMTIgMTcuMjM1N0w2LjE4MTMzIDEzLjU5ODNMMTIuMDAxMyA3LjAzMzAxVjEuMzMzMDFDMTEuNDM2IDEuMzMzMDEgMTAuODcwNyAxLjU1ODM0IDEwLjQ3MDcgMi4wMDkwMVoiIGZpbGw9IiM2NkRERkYiLz4KPHBhdGggZD0iTTYuMTgxMjcgMTMuNTk5NUw2LjI1MDYxIDEzLjY0MjJMMTEuOTk5OSAxNy4yMzY4SDEyLjAwMTNWNy4wMzU1MUwxMS45OTk5IDcuMDM0MThMNi4xODEyNyAxMy41OTk1WiIgZmlsbD0iI0NCRjhGRiIvPgo8cGF0aCBkPSJNMjMuMDk4NyAxNi4xMDRDMjQuMSAxNS40Nzg3IDI0LjMwMTMgMTQuMTYxMyAyMy41MjkzIDEzLjI4OTNMMTYuOTY4IDUuODg4QzE2LjQzODcgNS42NDEzMyAxNS44NDUzIDUuNSAxNS4yMTczIDUuNUMxMy45ODQgNS41IDEyLjg4MTMgNi4wMzIgMTIuMTQ4IDYuODY4TDEyLjAwMjcgNy4wMzJMMTcuODIxMyAxMy41OTczTDEyLjAwMTMgMTcuMjM0N1YyMi42NjUzQzEyLjM4NCAyMi42NjUzIDEyLjc2NTMgMjIuNTYxMyAxMy4wOTg3IDIyLjM1MzNMMjMuMDk4NyAxNi4xMDI3VjE2LjEwNFoiIGZpbGw9IiMwNzQ3OTMiLz4KPHBhdGggZD0iTTEyLjAwMTMgMS4zMzMwMVY3LjAzMzAxTDEyLjE0NjcgNi44NjkwMUMxMi44OCA2LjAzMzAxIDEzLjk4MjcgNS41MDEwMSAxNS4yMTYgNS41MDEwMUMxNS44NDUzIDUuNTAxMDEgMTYuNDM3MyA1LjY0MzY3IDE2Ljk2NjcgNS44ODkwMUwxMy41MjggMi4wMTAzNEMxMy4xMjkzIDEuNTU5NjcgMTIuNTY0IDEuMzM0MzQgMTIgMS4zMzQzNEwxMi4wMDEzIDEuMzMzMDFaIiBmaWxsPSIjMDI5NEU0Ii8+CjxwYXRoIGQ9Ik0xNy44MiAxMy41OTkyTDEyLjAwMTMgNy4wMzUxNlYxNy4yMzUyTDE3LjgyIDEzLjU5OTJaIiBmaWxsPSIjOTZCQ0MyIi8+Cjwvc3ZnPgo=',

View file

@ -1,14 +1,11 @@
import { ConnectorError, ConnectorErrorCodes } from '@logto/connector-kit';
import { SsoProviderName } from '@logto/schemas';
import { SsoProviderName, SsoProviderType } from '@logto/schemas';
import OidcConnector from '../OidcConnector/index.js';
import { type SingleSignOnFactory } from '../index.js';
import {
type CreateSingleSignOnSession,
type SingleSignOn,
type SingleSignOnConnectorData,
} from '../types/index.js';
import { type SingleSignOn, type SingleSignOnConnectorData } from '../types/connector.js';
import { basicOidcConnectorConfigGuard } from '../types/oidc.js';
import { type CreateSingleSignOnSession } from '../types/session.js';
// Google use static issue endpoint.
const googleIssuer = 'https://accounts.google.com';
@ -53,6 +50,7 @@ export const googleWorkspaceSsoConnectorConfigGuard = basicOidcConnectorConfigGu
export const googleWorkSpaceSsoConnectorFactory: SingleSignOnFactory<SsoProviderName.GOOGLE_WORKSPACE> =
{
providerName: SsoProviderName.GOOGLE_WORKSPACE,
providerType: SsoProviderType.OIDC,
logo: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yMy41MiAxMi4yNzI5QzIzLjUyIDExLjQyMiAyMy40NDM2IDEwLjYwMzggMjMuMzAxOCA5LjgxODM2SDEyVjE0LjQ2MDJIMTguNDU4MkMxOC4xOCAxNS45NjAyIDE3LjMzNDUgMTcuMjMxMSAxNi4wNjM2IDE4LjA4MlYyMS4wOTI5SDE5Ljk0MThDMjIuMjEwOSAxOS4wMDM4IDIzLjUyIDE1LjkyNzQgMjMuNTIgMTIuMjcyOVYxMi4yNzI5WiIgZmlsbD0iIzQyODVGNCIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTEyIDIzLjk5OTNDMTUuMjQgMjMuOTk5MyAxNy45NTY0IDIyLjkyNDggMTkuOTQxOCAyMS4wOTJMMTYuMDYzNiAxOC4wODExQzE0Ljk4OTEgMTguODAxMSAxMy42MTQ1IDE5LjIyNjYgMTIgMTkuMjI2NkM4Ljg3NDU1IDE5LjIyNjYgNi4yMjkwOSAxNy4xMTU3IDUuMjg1NDYgMTQuMjc5M0gxLjI3NjM3VjE3LjM4ODRDMy4yNTA5MSAyMS4zMTAyIDcuMzA5MDkgMjMuOTk5MyAxMiAyMy45OTkzVjIzLjk5OTNaIiBmaWxsPSIjMzRBODUzIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNS4yODU0NSAxNC4yODA0QzUuMDQ1NDUgMTMuNTYwNCA0LjkwOTA5IDEyLjc5MTMgNC45MDkwOSAxMi4wMDA0QzQuOTA5MDkgMTEuMjA5NSA1LjA0NTQ1IDEwLjQ0MDQgNS4yODU0NSA5LjcyMDQyVjYuNjExMzNIMS4yNzYzNkMwLjQ2MzYzNiA4LjIzMTMzIDAgMTAuMDY0MSAwIDEyLjAwMDRDMCAxMy45MzY4IDAuNDYzNjM2IDE1Ljc2OTUgMS4yNzYzNiAxNy4zODk1TDUuMjg1NDUgMTQuMjgwNFYxNC4yODA0WiIgZmlsbD0iI0ZCQkMwNSIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTEyIDQuNzcyNzNDMTMuNzYxOCA0Ljc3MjczIDE1LjM0MzYgNS4zNzgxOCAxNi41ODczIDYuNTY3MjdMMjAuMDI5MSAzLjEyNTQ1QzE3Ljk1MDkgMS4xODkwOSAxNS4yMzQ1IDAgMTIgMEM3LjMwOTA5IDAgMy4yNTA5MSAyLjY4OTA5IDEuMjc2MzcgNi42MTA5MUw1LjI4NTQ2IDkuNzJDNi4yMjkwOSA2Ljg4MzY0IDguODc0NTUgNC43NzI3MyAxMiA0Ljc3MjczVjQuNzcyNzNaIiBmaWxsPSIjRUE0MzM1Ii8+Cjwvc3ZnPgo=',
logoDark:
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yMy41MiAxMi4yNzI5QzIzLjUyIDExLjQyMiAyMy40NDM2IDEwLjYwMzggMjMuMzAxOCA5LjgxODM2SDEyVjE0LjQ2MDJIMTguNDU4MkMxOC4xOCAxNS45NjAyIDE3LjMzNDUgMTcuMjMxMSAxNi4wNjM2IDE4LjA4MlYyMS4wOTI5SDE5Ljk0MThDMjIuMjEwOSAxOS4wMDM4IDIzLjUyIDE1LjkyNzQgMjMuNTIgMTIuMjcyOVYxMi4yNzI5WiIgZmlsbD0iIzQyODVGNCIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTEyIDI0LjAwMDNDMTUuMjQgMjQuMDAwMyAxNy45NTY0IDIyLjkyNTcgMTkuOTQxOCAyMS4wOTNMMTYuMDYzNiAxOC4wODIxQzE0Ljk4OTEgMTguODAyMSAxMy42MTQ1IDE5LjIyNzUgMTIgMTkuMjI3NUM4Ljg3NDU1IDE5LjIyNzUgNi4yMjkwOSAxNy4xMTY2IDUuMjg1NDYgMTQuMjgwM0gxLjI3NjM3VjE3LjM4OTRDMy4yNTA5MSAyMS4zMTEyIDcuMzA5MDkgMjQuMDAwMyAxMiAyNC4wMDAzVjI0LjAwMDNaIiBmaWxsPSIjMzRBODUzIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNS4yODU0NSAxNC4yNzk0QzUuMDQ1NDUgMTMuNTU5NCA0LjkwOTA5IDEyLjc5MDQgNC45MDkwOSAxMS45OTk0QzQuOTA5MDkgMTEuMjA4NSA1LjA0NTQ1IDEwLjQzOTQgNS4yODU0NSA5LjcxOTQ0VjYuNjEwMzVIMS4yNzYzNkMwLjQ2MzYzNiA4LjIzMDM1IDAgMTAuMDYzMSAwIDExLjk5OTRDMCAxMy45MzU4IDAuNDYzNjM2IDE1Ljc2ODUgMS4yNzYzNiAxNy4zODg1TDUuMjg1NDUgMTQuMjc5NFYxNC4yNzk0WiIgZmlsbD0iI0ZCQkMwNSIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTEyIDQuNzcyNzNDMTMuNzYxOCA0Ljc3MjczIDE1LjM0MzYgNS4zNzgxOCAxNi41ODczIDYuNTY3MjdMMjAuMDI5MSAzLjEyNTQ1QzE3Ljk1MDkgMS4xODkwOSAxNS4yMzQ1IDAgMTIgMEM3LjMwOTA5IDAgMy4yNTA5MSAyLjY4OTA5IDEuMjc2MzcgNi42MTA5MUw1LjI4NTQ2IDkuNzJDNi4yMjkwOSA2Ljg4MzY0IDguODc0NTUgNC43NzI3MyAxMiA0Ljc3MjczVjQuNzcyNzNaIiBmaWxsPSIjRUE0MzM1Ii8+Cjwvc3ZnPgo=',

View file

@ -1,13 +1,13 @@
import { SsoProviderName } from '@logto/schemas';
import { SsoProviderName, SsoProviderType } from '@logto/schemas';
import OidcConnector from '../OidcConnector/index.js';
import { type SingleSignOnFactory } from '../index.js';
import { type SingleSignOn, type SingleSignOnConnectorData } from '../types/connector.js';
import {
SsoConnectorError,
SsoConnectorErrorCodes,
SsoConnectorConfigErrorCodes,
} from '../types/error.js';
import { type SingleSignOn, type SingleSignOnConnectorData } from '../types/index.js';
import { basicOidcConnectorConfigGuard } from '../types/oidc.js';
export class OidcSsoConnector extends OidcConnector implements SingleSignOn {
@ -36,6 +36,7 @@ export class OidcSsoConnector extends OidcConnector implements SingleSignOn {
export const oidcSsoConnectorFactory: SingleSignOnFactory<SsoProviderName.OIDC> = {
providerName: SsoProviderName.OIDC,
providerType: SsoProviderType.OIDC,
logo: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzk5MTRfMjA2MTMpIj4KPHBhdGggZD0iTTI0IDEzLjc5OTJMMjMuNCA4LjM5OTIyTDIxLjY2IDkuNTM5MjJDMjAuMDQgOC41MTkyMiAxOCA3Ljc5OTIyIDE1LjcyIDcuNDM5MjJDMTUuNzIgNy40MzkyMiAxNC41OCA3LjE5OTIyIDEzLjA4IDcuMTk5MjJDMTEuNTggNy4xOTkyMiAxMC4yIDcuMzc5MjIgMTAuMiA3LjM3OTIyQzQuMzggOC4wOTkyMiAwIDExLjM5OTIgMCAxNS4zNTkyQzAgMTkuNDM5MiA0LjUgMjIuNzk5MiAxMS40IDIzLjM5OTJWMjEuMDU5MkM2LjY2IDIwLjM5OTIgMy42NiAxOC4xNzkyIDMuNjYgMTUuMzU5MkMzLjY2IDEyLjcxOTIgNi40MiAxMC40OTkyIDEwLjIgOS43NzkyMkMxMC4yIDkuNzc5MjIgMTMuMTQgOS4xMTkyMiAxNS43MiA5Ljg5OTIyQzE2Ljk4IDEwLjE5OTIgMTguMTIgMTAuNjE5MiAxOS4wOCAxMS4yMTkyTDE2LjggMTIuNTk5MkwyNCAxMy43OTkyWiIgZmlsbD0iIzlFOUU5RSIvPgo8cGF0aCBkPSJNMTEuMzk5OSAyLjM5OTYxVjIzLjM5OTZMMTQuOTk5OSAyMS41OTk2VjAuNTk5NjA5TDExLjM5OTkgMi4zOTk2MVoiIGZpbGw9IiNGRjk4MDAiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF85OTE0XzIwNjEzIj4KPHJlY3Qgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=',
logoDark:
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzk5MTRfMjA2MTIpIj4KPHBhdGggZD0iTTI0IDEzLjc5OTJMMjMuNCA4LjM5OTIyTDIxLjY2IDkuNTM5MjJDMjAuMDQgOC41MTkyMiAxOCA3Ljc5OTIyIDE1LjcyIDcuNDM5MjJDMTUuNzIgNy40MzkyMiAxNC41OCA3LjE5OTIyIDEzLjA4IDcuMTk5MjJDMTEuNTggNy4xOTkyMiAxMC4yIDcuMzc5MjIgMTAuMiA3LjM3OTIyQzQuMzggOC4wOTkyMiAwIDExLjM5OTIgMCAxNS4zNTkyQzAgMTkuNDM5MiA0LjUgMjIuNzk5MiAxMS40IDIzLjM5OTJWMjEuMDU5MkM2LjY2IDIwLjM5OTIgMy42NiAxOC4xNzkyIDMuNjYgMTUuMzU5MkMzLjY2IDEyLjcxOTIgNi40MiAxMC40OTkyIDEwLjIgOS43NzkyMkMxMC4yIDkuNzc5MjIgMTMuMTQgOS4xMTkyMiAxNS43MiA5Ljg5OTIyQzE2Ljk4IDEwLjE5OTIgMTguMTIgMTAuNjE5MiAxOS4wOCAxMS4yMTkyTDE2LjggMTIuNTk5MkwyNCAxMy43OTkyWiIgZmlsbD0iIzlFOUU5RSIvPgo8cGF0aCBkPSJNMTEuMzk5OSAyLjM5OTYxVjIzLjM5OTZMMTQuOTk5OSAyMS41OTk2VjAuNTk5NjA5TDExLjM5OTkgMi4zOTk2MVoiIGZpbGw9IiNGRjk4MDAiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF85OTE0XzIwNjEyIj4KPHJlY3Qgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=',

View file

@ -1,4 +1,4 @@
import { SsoProviderName } from '@logto/schemas';
import { SsoProviderName, SsoProviderType } from '@logto/schemas';
import { OidcSsoConnector } from '../OidcSsoConnector/index.js';
import { type SingleSignOnFactory } from '../index.js';
@ -10,6 +10,7 @@ export class OktaSsoConnector extends OidcSsoConnector {}
export const oktaSsoConnectorFactory: SingleSignOnFactory<SsoProviderName.OKTA> = {
providerName: SsoProviderName.OKTA,
providerType: SsoProviderType.OIDC,
logo: logoBase64,
logoDark: logoDarkBase64,
description: {

View file

@ -1,4 +1,4 @@
import { SsoProviderName } from '@logto/schemas';
import { SsoProviderName, SsoProviderType } from '@logto/schemas';
import { conditional, trySafe } from '@silverhand/essentials';
import RequestError from '#src/errors/RequestError/index.js';
@ -6,7 +6,7 @@ import assertThat from '#src/utils/assert-that.js';
import SamlConnector from '../SamlConnector/index.js';
import { type SingleSignOnFactory } from '../index.js';
import { type SingleSignOn, type SingleSignOnConnectorData } from '../types/index.js';
import { type SingleSignOn, type SingleSignOnConnectorData } from '../types/connector.js';
import {
defaultAttributeMapping,
samlConnectorConfigGuard,
@ -105,6 +105,7 @@ export class SamlSsoConnector extends SamlConnector implements SingleSignOn {
export const samlSsoConnectorFactory: SingleSignOnFactory<SsoProviderName.SAML> = {
providerName: SsoProviderName.SAML,
providerType: SsoProviderType.SAML,
logo: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAgMjAuMDk4OEMwIDE3LjQ2MzIgMi41MTQzNCA3LjYzMDE1IDcuNzEyOTEgMS4wNDEwMkM0LjA0MzMzIDcuOTY4MDYgMS45MDg3MSAxMi42NTgzIDMuNDY1NzEgMTYuMzE0M0M0LjY4ODkxIDE5LjE4NjUgMTAuOTc0OCAxOC4yNzQxIDE0LjM3MjUgMTcuMTI1M0M4LjMyNDUxIDE5Ljg2MjMgMi4xMTc5NCAyMC4yMzQgMCAyMC4wOTg4WiIgZmlsbD0iI0MxMjcyRCIvPgo8cGF0aCBkPSJNMTEuMjYwNSAwLjc1QzEzLjU1NTcgMi4wNjc4MyAyMC44NjEzIDkuMTQ5ODMgMjQgMTYuOTIxN0MxOS44MDI2IDEwLjI5NzcgMTYuNzg1NSA2LjExNDE2IDEyLjgyMzMgNS42MjcxM0M5LjcxMDU1IDUuMjQ0NTIgNy4zNjIxMSAxMS4xMTQ0IDYuNjYzNyAxNC42MTUyQzcuMzA0MjQgOC4wMzc4IDEwLjA4MzggMi41MDY1IDExLjI2MDUgMC43NVoiIGZpbGw9IiNDMTI3MkQiLz4KPHBhdGggZD0iTTIyLjUzMiAyMC4wNzUyQzIwLjIzNjggMjEuMzkzMSAxMC40MTY4IDI0LjE0NDEgMi4wNzk1OSAyMi45NjE0QzkuOTQ2NiAyMi42NTgzIDE1LjA5ODMgMjIuMTUxNiAxNy41MDM1IDE4Ljk4MjZDMTkuMzkzMSAxNi40OTMxIDE1LjQ1NTYgMTEuNTM1NSAxMi43NTYzIDkuMTgzNTlDMTguMTYzOCAxMy4wMjQgMjEuNTkwNyAxOC4xODM2IDIyLjUzMiAyMC4wNzUyWiIgZmlsbD0iI0MxMjcyRCIvPgo8L3N2Zz4K',
logoDark:
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAgMjAuMDk4OEMwIDE3LjQ2MzIgMi41MTQzNCA3LjYzMDE1IDcuNzEyOTEgMS4wNDEwMkM0LjA0MzMzIDcuOTY4MDYgMS45MDg3MSAxMi42NTgzIDMuNDY1NzEgMTYuMzE0M0M0LjY4ODkxIDE5LjE4NjUgMTAuOTc0OCAxOC4yNzQxIDE0LjM3MjUgMTcuMTI1M0M4LjMyNDUxIDE5Ljg2MjMgMi4xMTc5NCAyMC4yMzQgMCAyMC4wOTg4WiIgZmlsbD0iI0MxMjcyRCIvPgo8cGF0aCBkPSJNMTEuMjYwNSAwLjc1QzEzLjU1NTcgMi4wNjc4MyAyMC44NjEzIDkuMTQ5ODMgMjQgMTYuOTIxN0MxOS44MDI2IDEwLjI5NzcgMTYuNzg1NSA2LjExNDE2IDEyLjgyMzMgNS42MjcxM0M5LjcxMDU1IDUuMjQ0NTIgNy4zNjIxMSAxMS4xMTQ0IDYuNjYzNyAxNC42MTUyQzcuMzA0MjQgOC4wMzc4IDEwLjA4MzggMi41MDY1IDExLjI2MDUgMC43NVoiIGZpbGw9IiNDMTI3MkQiLz4KPHBhdGggZD0iTTIyLjUzMTkgMjAuMDc1MkMyMC4yMzY3IDIxLjM5MzEgMTAuNDE2NyAyNC4xNDQxIDIuMDc5NDcgMjIuOTYxNEM5Ljk0NjQ4IDIyLjY1ODMgMTUuMDk4MSAyMi4xNTE2IDE3LjUwMzQgMTguOTgyNkMxOS4zOTI5IDE2LjQ5MzEgMTUuNDU1NSAxMS41MzU1IDEyLjc1NjIgOS4xODM1OUMxOC4xNjM2IDEzLjAyNCAyMS41OTA2IDE4LjE4MzYgMjIuNTMxOSAyMC4wNzUyWiIgZmlsbD0iI0MxMjcyRCIvPgo8L3N2Zz4K',

View file

@ -1,52 +1,15 @@
import { type I18nPhrases } from '@logto/connector-kit';
import { SsoProviderName } from '@logto/schemas';
import {
type AzureAdSsoConnector,
azureAdSsoConnectorFactory,
} from './AzureAdSsoConnector/index.js';
import {
type AzureOidcSsoConnector,
azureOidcSsoConnectorFactory,
} from './AzureOidcSsoConnector/index.js';
import {
type GoogleWorkspaceSsoConnector,
googleWorkSpaceSsoConnectorFactory,
type googleWorkspaceSsoConnectorConfigGuard,
} from './GoogleWorkspaceSsoConnector/index.js';
import { oidcSsoConnectorFactory, type OidcSsoConnector } from './OidcSsoConnector/index.js';
import { oktaSsoConnectorFactory, type OktaSsoConnector } from './OktaSsoConnector/index.js';
import { samlSsoConnectorFactory, type SamlSsoConnector } from './SamlSsoConnector/index.js';
import { type basicOidcConnectorConfigGuard } from './types/oidc.js';
import { type samlConnectorConfigGuard } from './types/saml.js';
import { azureAdSsoConnectorFactory } from './AzureAdSsoConnector/index.js';
import { azureOidcSsoConnectorFactory } from './AzureOidcSsoConnector/index.js';
import { googleWorkSpaceSsoConnectorFactory } from './GoogleWorkspaceSsoConnector/index.js';
import { oidcSsoConnectorFactory } from './OidcSsoConnector/index.js';
import { oktaSsoConnectorFactory } from './OktaSsoConnector/index.js';
import { samlSsoConnectorFactory } from './SamlSsoConnector/index.js';
import { type SingleSignOnFactory } from './types/index.js';
type SingleSignOnConstructor = {
[SsoProviderName.OIDC]: typeof OidcSsoConnector;
[SsoProviderName.SAML]: typeof SamlSsoConnector;
[SsoProviderName.AZURE_AD]: typeof AzureAdSsoConnector;
[SsoProviderName.GOOGLE_WORKSPACE]: typeof GoogleWorkspaceSsoConnector;
[SsoProviderName.OKTA]: typeof OktaSsoConnector;
[SsoProviderName.AZURE_AD_OIDC]: typeof AzureOidcSsoConnector;
};
export type SingleSignOnConnectorConfig = {
[SsoProviderName.OIDC]: typeof basicOidcConnectorConfigGuard;
[SsoProviderName.SAML]: typeof samlConnectorConfigGuard;
[SsoProviderName.AZURE_AD]: typeof samlConnectorConfigGuard;
[SsoProviderName.GOOGLE_WORKSPACE]: typeof googleWorkspaceSsoConnectorConfigGuard;
[SsoProviderName.OKTA]: typeof basicOidcConnectorConfigGuard;
[SsoProviderName.AZURE_AD_OIDC]: typeof basicOidcConnectorConfigGuard;
};
export type SingleSignOnFactory<T extends SsoProviderName> = {
providerName: T;
logo: string;
logoDark: string;
description: I18nPhrases;
name: I18nPhrases; // This `name` is for console and experience display use, while `providerName` is for internal use.
configGuard: SingleSignOnConnectorConfig[T];
constructor: SingleSignOnConstructor[T];
};
export { type SingleSignOnFactory, type SingleSignOnConnectorConfig } from './types/index.js';
export * from './types/session.js';
export const ssoConnectorFactories: {
[key in SsoProviderName]: SingleSignOnFactory<key>;

View file

@ -0,0 +1,20 @@
import { type SsoProviderName, type JsonObject, type SsoConnector } from '@logto/schemas';
// Pick the required fields from SsoConnector Schema
// providerName must be supported by the SSO connector factories
export type SingleSignOnConnectorData = Pick<SsoConnector, 'config' | 'id'> & {
providerName: SsoProviderName;
};
/**
* Single sign-on connector interface
* @interface SingleSignOn
*
* @property {SsoConnector} data - SSO connector data schema
* @method {getConfig} getConfig - Get the full-list of SSO config from the SSO provider
*/
export abstract class SingleSignOn {
abstract data: SingleSignOnConnectorData;
abstract getConfig: () => Promise<JsonObject>;
abstract getIssuer: () => Promise<string>;
}

View file

@ -1,22 +1,44 @@
import { type SsoProviderName, type JsonObject, type SsoConnector } from '@logto/schemas';
import { type I18nPhrases } from '@logto/connector-kit';
import { type SsoProviderType, type SsoProviderName } from '@logto/schemas';
export * from './session.js';
import { type AzureAdSsoConnector } from '../AzureAdSsoConnector/index.js';
import { type AzureOidcSsoConnector } from '../AzureOidcSsoConnector/index.js';
import {
type googleWorkspaceSsoConnectorConfigGuard,
type GoogleWorkspaceSsoConnector,
} from '../GoogleWorkspaceSsoConnector/index.js';
import { type OidcSsoConnector } from '../OidcSsoConnector/index.js';
import { type OktaSsoConnector } from '../OktaSsoConnector/index.js';
import { type SamlSsoConnector } from '../SamlSsoConnector/index.js';
/**
* Single sign-on connector interface
* @interface SingleSignOn
*
* @property {SsoConnector} data - SSO connector data schema
* @method {getConfig} getConfig - Get the full-list of SSO config from the SSO provider
*/
export abstract class SingleSignOn {
abstract data: SingleSignOnConnectorData;
abstract getConfig: () => Promise<JsonObject>;
abstract getIssuer: () => Promise<string>;
}
import { type basicOidcConnectorConfigGuard } from './oidc.js';
import { type samlConnectorConfigGuard } from './saml.js';
// Pick the required fields from SsoConnector Schema
// providerName must be supported by the SSO connector factories
export type SingleSignOnConnectorData = Pick<SsoConnector, 'config' | 'id'> & {
providerName: SsoProviderName;
type SingleSignOnConstructor = {
[SsoProviderName.OIDC]: typeof OidcSsoConnector;
[SsoProviderName.SAML]: typeof SamlSsoConnector;
[SsoProviderName.AZURE_AD]: typeof AzureAdSsoConnector;
[SsoProviderName.GOOGLE_WORKSPACE]: typeof GoogleWorkspaceSsoConnector;
[SsoProviderName.OKTA]: typeof OktaSsoConnector;
[SsoProviderName.AZURE_AD_OIDC]: typeof AzureOidcSsoConnector;
};
export type SingleSignOnConnectorConfig = {
[SsoProviderName.OIDC]: typeof basicOidcConnectorConfigGuard;
[SsoProviderName.SAML]: typeof samlConnectorConfigGuard;
[SsoProviderName.AZURE_AD]: typeof samlConnectorConfigGuard;
[SsoProviderName.GOOGLE_WORKSPACE]: typeof googleWorkspaceSsoConnectorConfigGuard;
[SsoProviderName.OKTA]: typeof basicOidcConnectorConfigGuard;
[SsoProviderName.AZURE_AD_OIDC]: typeof basicOidcConnectorConfigGuard;
};
export type SingleSignOnFactory<T extends SsoProviderName> = {
providerName: T;
providerType: SsoProviderType;
logo: string;
logoDark: string;
description: I18nPhrases;
name: I18nPhrases; // This `name` is for console and experience display use, while `providerName` is for internal use.
configGuard: SingleSignOnConnectorConfig[T];
constructor: SingleSignOnConstructor[T];
};

View file

@ -29,16 +29,8 @@ export const singleSignOnConnectorSessionGuard = z.object({
export type SingleSignOnConnectorSession = z.infer<typeof singleSignOnConnectorSessionGuard>;
export const samlConnectorAssertionSessionGuard = z.object({
state: z.string(),
redirectUri: z.string(),
connectorId: z.string(),
});
export type CreateSingleSignOnSession = (storage: SingleSignOnConnectorSession) => Promise<void>;
export type GetSingleSignOnSession = () => Promise<SingleSignOnConnectorSession>;
/**
* Single sign on interaction identifier session
*

View file

@ -10,7 +10,7 @@ import {
import {
type SingleSignOnConnectorSession,
singleSignOnConnectorSessionGuard,
} from '#src/sso/types/index.js';
} from '#src/sso/index.js';
import { type ExtendedSocialUserInfo } from '#src/sso/types/saml.js';
import assertThat from './assert-that.js';

View file

@ -23,6 +23,11 @@ export enum SsoProviderName {
AZURE_AD_OIDC = 'AzureAdOidc',
}
export enum SsoProviderType {
OIDC = 'oidc',
SAML = 'saml',
}
export const singleSignOnDomainBlackList = Object.freeze([
'gmail.com',
'yahoo.com',
@ -51,6 +56,7 @@ export type SupportedSsoConnector = Omit<SsoConnector, 'providerName'> & {
const ssoConnectorProviderDetailGuard = z.object({
providerName: z.nativeEnum(SsoProviderName),
providerType: z.nativeEnum(SsoProviderType),
logo: z.string(),
logoDark: z.string(),
description: z.string(),
@ -65,13 +71,18 @@ export type SsoConnectorProvidersResponse = z.infer<typeof ssoConnectorProviders
// API response guard for all the SSO connectors CRUD APIs
export const ssoConnectorWithProviderConfigGuard = SsoConnectors.guard
.omit({ providerName: true })
// Must be a supported SSO provider name. Overwrite the providerName string type to enum.
.extend({ providerName: z.nativeEnum(SsoProviderName) })
.merge(
// Static provider details
z.object({
name: z.string(), // For display purpose, generate from i18n key name defined by SSO factory.
providerName: z.nativeEnum(SsoProviderName),
name: z.string(),
providerType: z.nativeEnum(SsoProviderType),
providerLogo: z.string(),
providerLogoDark: z.string(),
// SSO connection config parsed from the provider.
// - OIDC: connection config fetched from the OIDC provider.
// - SAML: connection config fetched from the metadata url or metadata file.
providerConfig: z.record(z.unknown()).optional(),
})
);