Skip to content

Commit 5f25076

Browse files
committed
OID4VCI: Sign authn request only if AS supports it
1 parent dd92a47 commit 5f25076

File tree

5 files changed

+19
-14
lines changed

5 files changed

+19
-14
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ Release 5.7.0:
3838
Release 5.6.4:
3939
- OpenID for Verifiable Presentations:
4040
- Correctly handle requested attributes with nested paths, i.e. `address.formatted`
41+
- OAuth2.0:
42+
- In `OAuth2Client.createAuthRequest()` rename `wrapAsPar` to `wrapAsJar` to match its semantics
43+
- OpenID for Verifiable Credential Issuance:
44+
- Sign authn request as JAR only when AS supports it
4145

4246
Release 5.6.3:
4347
- OpenID for Verifiable Credential Issuance:

vck-openid-ktor/src/commonMain/kotlin/at/asitplus/wallet/lib/ktor/openid/OpenId4VciClient.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -484,15 +484,17 @@ class OpenId4VciClient(
484484
)
485485
val authorizationEndpointUrl = oauthMetadata.authorizationEndpoint
486486
?: throw Exception("no authorizationEndpoint in $oauthMetadata")
487+
val wrapAsJar = oauthMetadata.requestObjectSigningAlgorithmsSupported?.contains(JwsAlgorithm.Signature.ES256) == true
487488
val authRequest = oid4vciService.oauth2Client.createAuthRequest(
488489
state = state,
489490
authorizationDetails = if (scope == null) authorizationDetails else null,
490491
issuerState = issuerState,
491-
scope = scope
492+
scope = scope,
493+
wrapAsJar = wrapAsJar
492494
)
493-
val push = oauthMetadata.requirePushedAuthorizationRequests == true
495+
val requiresPar = oauthMetadata.requirePushedAuthorizationRequests == true
494496
val parEndpointUrl = oauthMetadata.pushedAuthorizationRequestEndpoint
495-
val authorizationUrl = if (parEndpointUrl != null && push) {
497+
val authorizationUrl = if (parEndpointUrl != null && requiresPar) {
496498
val authRequestAfterPar = pushAuthorizationRequest(
497499
authRequest = authRequest,
498500
state = state,

vck-openid/src/commonMain/kotlin/at/asitplus/wallet/lib/oauth2/OAuth2Client.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class OAuth2Client(
7979
* of [IssuerMetadata.credentialIssuer]
8080
* @param issuerState for OID4VCI flows the value from [CredentialOfferGrantsAuthCode.issuerState]
8181
* @param audience for PAR the value of the `issuer` of the Authorization Server
82-
* @param wrapAsPar whether to wrap the request as a PAR (i.e. a signed JWS)
82+
* @param wrapAsJar whether to wrap the request as a JAR (i.e. a signed JWS with the authn request as payload)
8383
*/
8484
suspend fun createAuthRequest(
8585
state: String,
@@ -88,7 +88,7 @@ class OAuth2Client(
8888
resource: String? = null,
8989
issuerState: String? = null,
9090
audience: String? = null,
91-
wrapAsPar: Boolean = true,
91+
wrapAsJar: Boolean = true,
9292
) = AuthenticationRequestParameters(
9393
responseType = GRANT_TYPE_CODE,
9494
state = state,
@@ -100,12 +100,12 @@ class OAuth2Client(
100100
redirectUrl = redirectUrl,
101101
codeChallenge = generateCodeVerifier(state),
102102
codeChallengeMethod = CODE_CHALLENGE_METHOD_SHA256
103-
).wrapIfNecessary(wrapAsPar, audience)
103+
).wrapIfNecessary(wrapAsJar, audience)
104104

105-
private suspend fun AuthenticationRequestParameters.wrapIfNecessary(wrapAsPar: Boolean, audience: String?) =
106-
if (signPushedAuthorizationRequest != null && wrapAsPar) wrapInPar(signPushedAuthorizationRequest, audience) else this
105+
private suspend fun AuthenticationRequestParameters.wrapIfNecessary(wrapAsJar: Boolean, audience: String?) =
106+
if (signPushedAuthorizationRequest != null && wrapAsJar) wrapInJar(signPushedAuthorizationRequest, audience) else this
107107

108-
private suspend fun AuthenticationRequestParameters.wrapInPar(
108+
private suspend fun AuthenticationRequestParameters.wrapInJar(
109109
signPushedAuthorizationRequest: SignJwtFun<AuthenticationRequestParameters>,
110110
audience: String?,
111111
) = AuthenticationRequestParameters(

vck-openid/src/commonTest/kotlin/at/asitplus/wallet/lib/oauth2/OAuth2ClientTest.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import io.kotest.matchers.nulls.shouldBeNull
1111
import io.kotest.matchers.nulls.shouldNotBeNull
1212
import io.kotest.matchers.shouldBe
1313
import io.kotest.matchers.types.shouldBeInstanceOf
14-
import kotlinx.serialization.json.JsonObject
1514

1615
class OAuth2ClientTest : FunSpec({
1716

@@ -83,7 +82,7 @@ class OAuth2ClientTest : FunSpec({
8382
val authnRequest = client.createAuthRequest(
8483
state = state,
8584
scope = scope,
86-
wrapAsPar = true
85+
wrapAsJar = true
8786
)
8887
val authnResponse = server.authorize(authnRequest).getOrThrow()
8988
.shouldBeInstanceOf<AuthenticationResponseResult.Redirect>()
@@ -104,7 +103,7 @@ class OAuth2ClientTest : FunSpec({
104103
val authnRequest = client.createAuthRequest(
105104
state = state,
106105
scope = scope,
107-
wrapAsPar = false
106+
wrapAsJar = false
108107
)
109108
val authnResponse = server.authorize(authnRequest).getOrThrow()
110109
.shouldBeInstanceOf<AuthenticationResponseResult.Redirect>()

vck-rqes/src/commonMain/kotlin/at/asitplus/wallet/lib/rqes/RqesOpenId4VpHolder.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ class RqesOpenId4VpHolder(
140140
): AuthenticationRequestParameters = oauth2Client.createAuthRequest(
141141
state = uuid4().toString(),
142142
scope = RqesOauthScope.SERVICE.value,
143-
wrapAsPar = wrapAsPar,
143+
wrapAsJar = wrapAsPar,
144144
).enrichAuthRequest(
145145
redirectUrl = redirectUrl,
146146
optionalParameters = optionalParameters
@@ -160,7 +160,7 @@ class RqesOpenId4VpHolder(
160160
): AuthenticationRequestParameters = oauth2Client.createAuthRequest(
161161
state = uuid4().toString(),
162162
authorizationDetails = setOf(getCscAuthenticationDetails(documentDigests, hashAlgorithm, documentLocation)),
163-
wrapAsPar = wrapAsPar,
163+
wrapAsJar = wrapAsPar,
164164
).enrichAuthRequest(
165165
redirectUrl = redirectUrl,
166166
optionalParameters = optionalParameters

0 commit comments

Comments
 (0)