Skip to content

Commit

Permalink
Update and simplify default implementations.
Browse files Browse the repository at this point in the history
  • Loading branch information
dzarras committed Nov 24, 2023
1 parent 6a09843 commit e3cbd77
Show file tree
Hide file tree
Showing 14 changed files with 139 additions and 124 deletions.
21 changes: 21 additions & 0 deletions src/main/kotlin/eu/europa/ec/eudi/openid4vp/Dispatcher.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
*/
package eu.europa.ec.eudi.openid4vp

import eu.europa.ec.eudi.openid4vp.internal.dispatch.DefaultDispatcher
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import java.io.Serializable
import java.net.URI

Expand Down Expand Up @@ -72,4 +75,22 @@ fun interface Dispatcher {
* method returns an appropriate [redirect_uri][DispatchOutcome.RedirectURI]
*/
suspend fun dispatch(response: AuthorizationResponse): DispatchOutcome

companion object {

/**
* Factory method to create a [Dispatcher].
*
* @param ioCoroutineDispatcher the coroutine dispatcher to handle IO
* @param httpClientFactory a factory to obtain a Ktor http client
* @return a [Dispatcher]
*
* @see DefaultDispatcher
*/
fun make(
ioCoroutineDispatcher: CoroutineDispatcher = Dispatchers.IO,
httpClientFactory: KtorHttpClientFactory = DefaultHttpClientFactory,
): Dispatcher =
DefaultDispatcher(ioCoroutineDispatcher, httpClientFactory)
}
}
39 changes: 39 additions & 0 deletions src/main/kotlin/eu/europa/ec/eudi/openid4vp/Ktor.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2023 European Commission
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package eu.europa.ec.eudi.openid4vp

import io.ktor.client.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.json.*

/**
* Alias of a method that creates a [HttpClient]
*/
typealias KtorHttpClientFactory = () -> HttpClient

/**
* Factory which produces a [Ktor Http client][HttpClient]
* The actual engine will be peeked up by whatever
* it is available in classpath
*
* @see [Ktor Client]("https://ktor.io/docs/client-dependencies.html#engine-dependency)
*/
val DefaultHttpClientFactory: KtorHttpClientFactory = {
HttpClient {
install(ContentNegotiation) { json() }
expectSuccess = true
}
}
34 changes: 28 additions & 6 deletions src/main/kotlin/eu/europa/ec/eudi/openid4vp/SiopOpenId4Vp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package eu.europa.ec.eudi.openid4vp

import eu.europa.ec.eudi.openid4vp.internal.DefaultSiopOpenId4Vp
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers

Expand All @@ -38,20 +39,41 @@ interface SiopOpenId4Vp : AuthorizationRequestResolver, AuthorizationResponseBui
companion object {

/**
* Factory method to create a [SiopOpenId4Vp] based
* on ktor
* Factory method to create a [SiopOpenId4Vp].
*
* @param ioCoroutineDispatcher the coroutine dispatcher to handle IO
* @param walletOpenId4VPConfig wallet's configuration
* @param httpClientFactory a factory to obtain a Ktor http client
* @return a [SiopOpenId4Vp]
*
* @see SiopOpenId4VpKtor
* @see DefaultSiopOpenId4Vp
*/
fun ktor(
fun make(
walletOpenId4VPConfig: WalletOpenId4VPConfig,
ioCoroutineDispatcher: CoroutineDispatcher = Dispatchers.IO,
httpClientFactory: KtorHttpClientFactory = SiopOpenId4VpKtor.DefaultFactory,
): SiopOpenId4Vp = SiopOpenId4VpKtor(ioCoroutineDispatcher, walletOpenId4VPConfig, httpClientFactory)
httpClientFactory: KtorHttpClientFactory = DefaultHttpClientFactory,
): SiopOpenId4Vp =
make(
AuthorizationRequestResolver.make(ioCoroutineDispatcher, httpClientFactory, walletOpenId4VPConfig),
Dispatcher.make(ioCoroutineDispatcher, httpClientFactory),
AuthorizationResponseBuilder.make(walletOpenId4VPConfig),
)

/**
* Factory method to create a [SiopOpenId4Vp].
*
* @param authorizationResolver the [AuthorizationRequestResolver] instance to use
* @param dispatcher the [Dispatcher] instance to use
* @param authorizationResponseBuilder the [AuthorizationResponseBuilder] instance to use
* @return a [SiopOpenId4Vp]
*
* @see DefaultSiopOpenId4Vp
*/
fun make(
authorizationResolver: AuthorizationRequestResolver,
dispatcher: Dispatcher,
authorizationResponseBuilder: AuthorizationResponseBuilder,
): SiopOpenId4Vp =
DefaultSiopOpenId4Vp(authorizationResolver, dispatcher, authorizationResponseBuilder)
}
}
107 changes: 0 additions & 107 deletions src/main/kotlin/eu/europa/ec/eudi/openid4vp/SiopOpenId4VpKtor.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2023 European Commission
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package eu.europa.ec.eudi.openid4vp.internal

import eu.europa.ec.eudi.openid4vp.AuthorizationRequestResolver
import eu.europa.ec.eudi.openid4vp.AuthorizationResponseBuilder
import eu.europa.ec.eudi.openid4vp.Dispatcher
import eu.europa.ec.eudi.openid4vp.SiopOpenId4Vp

/**
* An implementation of [SiopOpenId4Vp].
*
*/
internal class DefaultSiopOpenId4Vp(
private val authorizationResolver: AuthorizationRequestResolver,
private val dispatcher: Dispatcher,
private val authorizationResponseBuilder: AuthorizationResponseBuilder,
) : SiopOpenId4Vp,
AuthorizationRequestResolver by authorizationResolver,
Dispatcher by dispatcher,
AuthorizationResponseBuilder by authorizationResponseBuilder
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import java.net.URL
*/
internal class DefaultDispatcher(
private val ioCoroutineDispatcher: CoroutineDispatcher = Dispatchers.IO,
private val httpClientFactory: KtorHttpClientFactory,
private val httpClientFactory: KtorHttpClientFactory = DefaultHttpClientFactory,
) : Dispatcher {
override suspend fun dispatch(response: AuthorizationResponse): DispatchOutcome =
when (response) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import java.net.URL

internal class ClientMetaDataResolver(
private val ioCoroutineDispatcher: CoroutineDispatcher = Dispatchers.IO,
private val httpClientFactory: KtorHttpClientFactory,
private val httpClientFactory: KtorHttpClientFactory = DefaultHttpClientFactory,
walletOpenId4VPConfig: WalletOpenId4VPConfig,
) {
private val clientMetadataValidator = ClientMetadataValidator(ioCoroutineDispatcher, walletOpenId4VPConfig)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ import com.nimbusds.jose.jwk.JWKSet
import eu.europa.ec.eudi.openid4vp.*
import eu.europa.ec.eudi.openid4vp.internal.success
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.IOException
import java.net.URL
import java.text.ParseException

internal class ClientMetadataValidator(
private val ioCoroutineDispatcher: CoroutineDispatcher,
private val ioCoroutineDispatcher: CoroutineDispatcher = Dispatchers.IO,
private val walletOpenId4VPConfig: WalletOpenId4VPConfig,
) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

internal class DefaultAuthorizationRequestResolver(
private val ioCoroutineDispatcher: CoroutineDispatcher,
private val ioCoroutineDispatcher: CoroutineDispatcher = Dispatchers.IO,
private val walletOpenId4VPConfig: WalletOpenId4VPConfig,
private val httpClientFactory: KtorHttpClientFactory,
private val httpClientFactory: KtorHttpClientFactory = DefaultHttpClientFactory,
private val validatedRequestObjectResolver: ValidatedRequestObjectResolver,
) : AuthorizationRequestResolver {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import eu.europa.ec.eudi.openid4vp.SupportedClientIdScheme.IsoX509
import eu.europa.ec.eudi.openid4vp.SupportedClientIdScheme.Preregistered
import eu.europa.ec.eudi.openid4vp.internal.success
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
Expand All @@ -50,7 +51,7 @@ import java.text.ParseException
* @param walletOpenId4VPConfig wallet's configuration
*/
internal class JarJwtSignatureValidator(
private val ioCoroutineDispatcher: CoroutineDispatcher,
private val ioCoroutineDispatcher: CoroutineDispatcher = Dispatchers.IO,
private val walletOpenId4VPConfig: WalletOpenId4VPConfig,
) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import java.net.URL
*/
internal class PresentationDefinitionResolver(
private val ioCoroutineDispatcher: CoroutineDispatcher = Dispatchers.IO,
private val httpClientFactory: KtorHttpClientFactory,
private val httpClientFactory: KtorHttpClientFactory = DefaultHttpClientFactory,
) {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class AuthorizationRequestResolverTest {
authorizationEncryptionEncValuesSupported = emptyList(),
)

private val resolver = SiopOpenId4Vp.ktor(walletConfig)
private val resolver = SiopOpenId4Vp.make(walletConfig)

private val clientMetadataJwksInline =
""" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.nimbusds.jose.jwk.JWKSet
import com.nimbusds.jose.jwk.KeyUse
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator
import com.nimbusds.oauth2.sdk.id.State
import eu.europa.ec.eudi.openid4vp.internal.dispatch.DefaultDispatcher
import eu.europa.ec.eudi.openid4vp.internal.request.ClientMetadataValidator
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.json.*
Expand Down Expand Up @@ -138,8 +139,11 @@ class AuthorizationResponseDispatcherTest {
}
}

val dispatcher = SiopOpenId4VpKtor.dispatcher { managedHttpClient }
when (val response = AuthorizationResponseBuilder.make(walletConfig).build(siopAuthRequestObject, idTokenConsensus)) {
val dispatcher = DefaultDispatcher(httpClientFactory = { managedHttpClient })
when (
val response =
AuthorizationResponseBuilder.make(walletConfig).build(siopAuthRequestObject, idTokenConsensus)
) {
is AuthorizationResponse.DirectPost -> {
dispatcher.dispatch(response)
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/kotlin/eu/europa/ec/eudi/openid4vp/Example.kt
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ private class Wallet(
get() = walletKeyPair.toPublicJWK()

private val siopOpenId4Vp: SiopOpenId4Vp by lazy {
SiopOpenId4Vp.ktor(walletConfig) { createHttpClient() }
SiopOpenId4Vp.make(walletConfig) { createHttpClient() }
}

suspend fun handle(uri: URI): DispatchOutcome {
Expand Down

0 comments on commit e3cbd77

Please sign in to comment.