SimpleAuthorizationService

class SimpleAuthorizationService @JvmOverloads constructor(strategy: AuthorizationServiceStrategy, codeService: CodeService = DefaultCodeService(), val publicContext: String = "https://wallet.a-sit.at/authorization-server", authorizationEndpointPath: String = "/authorize", tokenEndpointPath: String = "/token", pushedAuthorizationRequestEndpointPath: String = "/par", userInfoEndpointPath: String = "/userinfo", introspectionEndpointPath: String = "/introspect", challengeEndpointPath: String = "/challenge", issuerStateToCredentialOffer: MapStore<String, CredentialOffer> = DefaultMapStore(), codeToClientAuthRequest: MapStore<String, ClientAuthRequest> = DefaultMapStore(), refreshTokenToAuthRequest: MapStore<String, ClientAuthRequest> = DefaultMapStore(lifetime = 30.days), requestUriToPushedAuthorizationRequest: MapStore<String, PushedAuthorizationRequest> = DefaultMapStore(), tokenService: TokenService = TokenService.bearer(), clientAuthenticationService: ClientAuthenticationService = NoopClientAuthenticationService, requestParser: RequestParser = RequestParser( /** By default, do not retrieve authn requests referenced by `request_uri`. */ remoteResourceRetriever = { null }, /** Not necessary to load the authn request referenced by `request_uri`. */ buildRequestObjectParameters = { null } ), requirePushedAuthorizationRequests: Boolean = true, requestObjectSigningAlgorithms: Set<JwsAlgorithm.Signature>? = setOf(JwsAlgorithm.Signature.ES256), supportedSigningAlgorithms: Set<JwsAlgorithm.Signature> = DEFAULT_WALLET_ATTESTATION_ALGORITHMS, signIntrospectionJwt: SignJwtFun<TokenIntrospectionJwtPayload> = SignJwt(EphemeralKeyWithoutCert(), JwsHeaderCertOrJwk()), issuerStateService: CodeService = DefaultCodeService(), preAuthorizedCodeService: CodeService = DefaultCodeService(), supportTokenExchange: Boolean = false, clock: Clock = Clock.System) : OAuth2AuthorizationServerAdapter, AuthorizationService(source)

Simple authorization server implementation, to be used for OpenId4VciServer, with the actual authentication and authorization logic for credential schemes implemented in strategy.

Implemented from OpenID for Verifiable Credential Issuance 1.0 from 2025-09-16. Also implements necessary parts of OpenID4VC HAIP , Draft 03, 2025-02-07, e.g. OAuth 2.0 Pushed Authorization Requests, Proof Key for Code Exchange by OAuth Public Clients, OAuth 2.0 Demonstrating Proof of Possession (DPoP), OAuth 2.0 Attestation-Based Client Authentication OAuth 2.0 Token Introspection JWT Response for OAuth Token Introspection OAuth 2.0 Token Exchange

Constructors

Link copied to clipboard
constructor(strategy: AuthorizationServiceStrategy, codeService: CodeService = DefaultCodeService(), publicContext: String = "https://wallet.a-sit.at/authorization-server", authorizationEndpointPath: String = "/authorize", tokenEndpointPath: String = "/token", pushedAuthorizationRequestEndpointPath: String = "/par", userInfoEndpointPath: String = "/userinfo", introspectionEndpointPath: String = "/introspect", challengeEndpointPath: String = "/challenge", issuerStateToCredentialOffer: MapStore<String, CredentialOffer> = DefaultMapStore(), codeToClientAuthRequest: MapStore<String, ClientAuthRequest> = DefaultMapStore(), refreshTokenToAuthRequest: MapStore<String, ClientAuthRequest> = DefaultMapStore(lifetime = 30.days), requestUriToPushedAuthorizationRequest: MapStore<String, PushedAuthorizationRequest> = DefaultMapStore(), tokenService: TokenService = TokenService.bearer(), clientAuthenticationService: ClientAuthenticationService = NoopClientAuthenticationService, requestParser: RequestParser = RequestParser( /** By default, do not retrieve authn requests referenced by `request_uri`. */ remoteResourceRetriever = { null }, /** Not necessary to load the authn request referenced by `request_uri`. */ buildRequestObjectParameters = { null } ), requirePushedAuthorizationRequests: Boolean = true, requestObjectSigningAlgorithms: Set<JwsAlgorithm.Signature>? = setOf(JwsAlgorithm.Signature.ES256), supportedSigningAlgorithms: Set<JwsAlgorithm.Signature> = DEFAULT_WALLET_ATTESTATION_ALGORITHMS, signIntrospectionJwt: SignJwtFun<TokenIntrospectionJwtPayload> = SignJwt(EphemeralKeyWithoutCert(), JwsHeaderCertOrJwk()), issuerStateService: CodeService = DefaultCodeService(), preAuthorizedCodeService: CodeService = DefaultCodeService(), supportTokenExchange: Boolean = false, clock: Clock = Clock.System)

Types

Link copied to clipboard
object Companion

Properties

Link copied to clipboard
open override val publicContext: String

Used in several fields in OAuth2AuthorizationServerMetadata, to provide endpoint URLs to clients.

Functions

Link copied to clipboard

Provides a challenge for the challenge endpoint, send it converted with AttestationChallengeResponse.toHttpResponse. See OAuth 2.0 Attestation-Based Client Authentication

Link copied to clipboard
open suspend override fun authorize(input: RequestParameters, loadUserFun: OAuth2LoadUserFun): KmmResult<AuthenticationResponseResult.Redirect>

Builds the authentication response for this specific user from loadUserFun. Send this result converted with AuthenticationResponseResult.Redirect.toHttpResponse.

Link copied to clipboard
open suspend override fun getDpopNonce(): String?

If this is an internal AS, provide a fresh DPoP nonce for clients.

Link copied to clipboard
open suspend override fun getTokenInfo(authorizationHeader: String, httpRequest: RequestInfo?): KmmResult<TokenInfo>

Obtains information about the token, since we're in-memory here (as an OAuth2AuthorizationServerAdapter, we can directly access our tokenService.

Link copied to clipboard
open suspend override fun getUserInfo(authorizationHeader: String, httpRequest: RequestInfo?): KmmResult<JsonObject>

Obtains a JSON object representing at.asitplus.openid.OidcUserInfo from the Authorization Server, and since we're implementing OAuth2AuthorizationServerAdapter here, this is the same as userInfo, i.e. the access token is validated before any user info is returned.

Link copied to clipboard
open suspend override fun metadata(): OAuth2AuthorizationServerMetadata

Serve this result under /.well-known/openid-configuration, see OpenIdConstants.WellKnownPaths.OpenidConfiguration, and under /.well-known/oauth-authorization-server, see OpenIdConstants.WellKnownPaths.OauthAuthorizationServer, converted with OAuth2AuthorizationServerMetadata.toHttpResponse.

Link copied to clipboard

Offer some credential identifiers from strategy to clients with auth-code flow.

Link copied to clipboard
suspend fun offerWithPreAuthnForUserForSchemes(user: OidcUserInfoExtended, credentialIssuer: String, schemes: Set<Pair<CredentialScheme, CredentialRepresentation>> = emptySet(), transactionCode: String? = null, transactionCodeDescriptor: CredentialOfferGrantsPreAuthCodeTransactionCode? = transactionCode?.let { CredentialOfferGrantsPreAuthCodeTransactionCode(length = it.length) }): CredentialOffer

Offer all available schemes from strategy to clients.

Link copied to clipboard
open suspend override fun par(request: RequestParameters, httpRequest: RequestInfo? = null): KmmResult<PushedAuthenticationResponseParameters>
open suspend override fun par(input: String, httpRequest: RequestInfo? = null): KmmResult<PushedAuthenticationResponseParameters>

Pushed authorization request endpoint as defined in RFC 9126. Clients send their authorization request as HTTP POST with application/x-www-form-urlencoded to the AS.

Link copied to clipboard

Like par, but also provides a fresh DPoP nonce and, with attestation-based client authentication, a fresh attestation challenge for the success response headers; send it converted with toHttpResponse(). See RFC 9449 8. Authorization Server-Provided Nonce, OA-ABCA 6.2

Link copied to clipboard
suspend fun providePreAuthorizedCode(userInfo: OidcUserInfoExtended, configurationIds: Set<String>? = null, transactionCode: String? = null): String
Link copied to clipboard
open suspend override fun token(request: TokenRequestParameters, httpRequest: RequestInfo? = null): KmmResult<TokenResponseParameters>

Verifies the authorization code sent by the client and issues an access token, uses tokenService. Send the result of tokenWithDpopNonce converted with toHttpResponse(), which sets the headers the token response needs.

Link copied to clipboard
open suspend override fun tokenIntrospection(request: TokenIntrospectionRequest, httpRequest: RequestInfo? = null): KmmResult<TokenIntrospectionResult>

Answers with a TokenIntrospectionJwtResponse (RFC 9701) when the Accept header of httpRequest asks for application/token-introspection+jwt, which needs an AuthenticatedClient, the resource server, as aud (RFC 9701 5.); else with a TokenIntrospectionResponse.

Link copied to clipboard

Like token, but also provides a fresh DPoP nonce and, with attestation-based client authentication, a fresh attestation challenge for the success response headers; send it converted with toHttpResponse(). See RFC 9449 8. Authorization Server-Provided Nonce, OA-ABCA 6.2

Link copied to clipboard
open suspend override fun userInfo(authorizationHeader: String, httpRequest: RequestInfo? = null): KmmResult<JsonObject>

Returns the user info associated with this access token, when the token in authorizationHeader is correct.

Link copied to clipboard
suspend fun userInfoWithDpopNonce(authorizationHeader: String, httpRequest: RequestInfo? = null): KmmResult<ResponseWithDpopNonce<JsonObject>>

Like userInfo, but also provides a fresh DPoP nonce for the success response header; send it converted with toHttpResponse(). See RFC 9449 9. Resource Server-Provided Nonce

Link copied to clipboard
open suspend override fun validateAccessToken(authorizationHeader: String, httpRequest: RequestInfo?): KmmResult<ValidatedAccessToken>

Validates the access token sent to OpenId4VciServer.credential.