src/issuer/configuration/issuance/dto/chained-as-config.dto.ts
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:
issuer_state in access tokens for session correlationFlow:
authorization_server = EUDIPLOissuer_state, DPoP binding, etc.
Properties |
|
| enabled |
Type : boolean
|
Decorators :
@ApiProperty({description: 'Enable chained AS mode', default: false})
|
|
Whether chained AS mode is enabled. When enabled, EUDIPLO acts as the AS and delegates to upstream for authentication. |
| Optional requireDPoP |
Type : boolean
|
Decorators :
@ApiPropertyOptional({description: 'Require DPoP binding for tokens', default: true})
|
|
Whether to require DPoP for token requests. When true, wallets must provide DPoP proofs. |
| Optional token |
Type : ChainedAsTokenConfig
|
Decorators :
@ApiPropertyOptional({description: 'Token configuration', type: () => ChainedAsTokenConfig})
|
|
Configuration for tokens issued by EUDIPLO. |
| Optional upstream |
Type : UpstreamOidcConfig
|
Decorators :
@ApiPropertyOptional({description: 'Upstream OIDC provider configuration', type: () => UpstreamOidcConfig})
|
|
Configuration for the upstream OIDC provider. Required when enabled is true. |
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;
}