src/issuer/configuration/issuance/dto/chained-as-config.dto.ts
Configuration for the upstream OIDC provider (e.g., Keycloak). EUDIPLO will delegate user authentication to this provider.
Properties |
|
| clientId |
Type : string
|
Decorators :
@ApiProperty({description: 'The client ID registered with the upstream provider', example: 'eudiplo-chained-as'})
|
|
The client ID registered with the upstream provider for EUDIPLO. |
| Optional clientSecret |
Type : string
|
Decorators :
@ApiPropertyOptional({description: 'The client secret for confidential clients'})
|
|
The client secret for confidential clients. Optional for public clients using PKCE only. |
| issuer |
Type : string
|
Decorators :
@ApiProperty({description: 'The OIDC issuer URL of the upstream provider', example: 'https://auth.example.com/realms/myrealm'})
|
|
The OIDC issuer URL of the upstream provider. Example : |
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { Type } from "class-transformer";
import {
IsBoolean,
IsNumber,
IsOptional,
IsString,
IsUrl,
Min,
ValidateNested,
} from "class-validator";
/**
* Configuration for the upstream OIDC provider (e.g., Keycloak).
* EUDIPLO will delegate user authentication to this provider.
*/
export class UpstreamOidcConfig {
/**
* The OIDC issuer URL of the upstream provider.
* @example "https://auth.example.com/realms/myrealm"
*/
@ApiProperty({
description: "The OIDC issuer URL of the upstream provider",
example: "https://auth.example.com/realms/myrealm",
})
@IsUrl({ require_tld: false })
issuer!: string;
/**
* The client ID registered with the upstream provider for EUDIPLO.
*/
@ApiProperty({
description: "The client ID registered with the upstream provider",
example: "eudiplo-chained-as",
})
@IsString()
clientId!: string;
/**
* The client secret for confidential clients.
* Optional for public clients using PKCE only.
*/
@ApiPropertyOptional({
description: "The client secret for confidential clients",
})
@IsOptional()
@IsString()
clientSecret?: string;
/**
* The scopes to request from the upstream provider.
* @default ["openid", "profile"]
*/
@ApiPropertyOptional({
description: "Scopes to request from the upstream provider",
default: ["openid", "profile"],
})
@IsOptional()
@IsString({ each: true })
scopes?: string[];
}
/**
* Configuration for the tokens issued by EUDIPLO in chained AS mode.
*/
export class ChainedAsTokenConfig {
/**
* The lifetime of access tokens in seconds.
* @default 3600 (1 hour)
*/
@ApiPropertyOptional({
description: "Access token lifetime in seconds",
default: 3600,
})
@IsOptional()
@IsNumber()
@Min(60)
lifetimeSeconds?: number;
/**
* The key ID to use for signing tokens.
* Must reference a key configured in the crypto service.
*/
@ApiPropertyOptional({
description: "Key ID for token signing",
})
@IsOptional()
@IsString()
signingKeyId?: string;
}
/**
* Configuration for enabling "Chained Authorization Server" mode.
*
* In this mode, EUDIPLO acts as the Authorization Server for wallets,
* but delegates user authentication to an upstream OIDC provider (e.g., Keycloak).
*
* Benefits:
* - No modifications required to the upstream OIDC provider
* - EUDIPLO can include `issuer_state` in access tokens for session correlation
* - EUDIPLO handles wallet attestation and OID4VCI-specific requirements
* - DPoP binding is managed by EUDIPLO
*
* Flow:
* 1. Wallet receives credential offer with `authorization_server = EUDIPLO`
* 2. Wallet calls EUDIPLO PAR/authorize endpoints
* 3. EUDIPLO redirects user to upstream OIDC provider for login
* 4. User authenticates with upstream provider
* 5. Upstream provider redirects back to EUDIPLO callback
* 6. EUDIPLO exchanges upstream code for tokens, extracts user identity
* 7. EUDIPLO issues its own access token with `issuer_state`, DPoP binding, etc.
* 8. Wallet uses EUDIPLO-issued token for credential requests
*/
export class ChainedAsConfig {
/**
* Whether chained AS mode is enabled.
* When enabled, EUDIPLO acts as the AS and delegates to upstream for authentication.
*/
@ApiProperty({
description: "Enable chained AS mode",
default: false,
})
@IsBoolean()
enabled!: boolean;
/**
* Configuration for the upstream OIDC provider.
* Required when enabled is true.
*/
@ApiPropertyOptional({
description: "Upstream OIDC provider configuration",
type: () => UpstreamOidcConfig,
})
@IsOptional()
@ValidateNested()
@Type(() => UpstreamOidcConfig)
upstream?: UpstreamOidcConfig;
/**
* Configuration for tokens issued by EUDIPLO.
*/
@ApiPropertyOptional({
description: "Token configuration",
type: () => ChainedAsTokenConfig,
})
@IsOptional()
@ValidateNested()
@Type(() => ChainedAsTokenConfig)
token?: ChainedAsTokenConfig;
/**
* Whether to require DPoP for token requests.
* When true, wallets must provide DPoP proofs.
* @default true
*/
@ApiPropertyOptional({
description: "Require DPoP binding for tokens",
default: true,
})
@IsOptional()
@IsBoolean()
requireDPoP?: boolean;
}