Skip to content
This repository has been archived by the owner on Nov 20, 2023. It is now read-only.

Commit

Permalink
test: test same device credential issuance flow
Browse files Browse the repository at this point in the history
feat: implement vp_token auth in the course of an issuance flow
test: start test of issuance flow with implicit vp token exchange for ebsi conformance
  • Loading branch information
severinstampler committed Oct 11, 2023
1 parent 0dec24d commit 692fd60
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ abstract class OpenIDCredentialWallet<S: SIOPSession>(
println("location: $location")
location = if(location.parameters.contains("response_type") && location.parameters["response_type"] == ResponseType.id_token.name) {
executeIdTokenAuthorization(location, holderDid, client)
} else if(location.parameters.contains("response_type") && location.parameters["response_type"] == ResponseType.vp_token.name) {
executeVpTokenAuthorization(location, holderDid, client)
} else location

val code = location.parameters["code"] ?: throw AuthorizationError(authReq, AuthorizationErrorCode.server_error, "No authorization code received from server")
Expand Down Expand Up @@ -322,4 +324,17 @@ abstract class OpenIDCredentialWallet<S: SIOPSession>(
?: throw AuthorizationError(authReq, AuthorizationErrorCode.server_error, "Location parameter missing on http response for id_token response")
}

open fun executeVpTokenAuthorization(vpTokenRequestUri: Url, holderDid: String, client: OpenIDClientConfig): Url {
val authReq = AuthorizationRequest.fromHttpQueryString(vpTokenRequestUri.encodedQuery)
val tokenResp = processImplicitFlowAuthorization(authReq.copy(
clientId = client.clientID,
))
val httpResp = httpSubmitForm(Url(authReq.responseUri ?: authReq.redirectUri!!), parametersOf(tokenResp.toHttpParameters()))
return when(httpResp.status) {
HttpStatusCode.Found -> httpResp.headers[HttpHeaders.Location]
HttpStatusCode.OK -> httpResp.body?.let { AuthorizationDirectPostResponse.fromJSONString(it) }?.redirectUri
else -> null
}?.let { Url(it) } ?: throw AuthorizationError(authReq, AuthorizationErrorCode.invalid_request, "Request could not be executed")
}

}
4 changes: 3 additions & 1 deletion src/jvmTest/kotlin/id/walt/oid4vc/EBSITestWallet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class EBSITestWallet(config: CredentialWalletConfig): OpenIDCredentialWallet<SIO
KeyService.getService().addAlias(keyId, EBSI_WALLET_TEST_DID)
val didDoc = DidService.resolve(EBSI_WALLET_TEST_DID)
KeyService.getService().addAlias(keyId, didDoc.verificationMethod!!.first().id)
DidService.importDid(EBSI_WALLET_TEST_DID)
}
}
override fun resolveDID(did: String): String {
Expand Down Expand Up @@ -160,10 +161,11 @@ class EBSITestWallet(config: CredentialWalletConfig): OpenIDCredentialWallet<SIO
?: "VerifiableCredential"

DescriptorMapping(
id = type,
id = "same-device-in-time-credential",
format = VCFormat.jwt_vp, // jwt_vp_json
path = "$",
pathNested = DescriptorMapping(
id = type,
format = VCFormat.jwt_vc,
path = "$.vp.verifiableCredential[0]",
)
Expand Down
46 changes: 46 additions & 0 deletions src/jvmTest/kotlin/id/walt/oid4vc/EBSI_Conformance_Test.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package id.walt.oid4vc

import id.walt.credentials.w3c.VerifiableCredential
import id.walt.custodian.Custodian
import id.walt.oid4vc.providers.CredentialWalletConfig
import id.walt.oid4vc.providers.OpenIDClientConfig
import id.walt.oid4vc.requests.CredentialOfferRequest
import id.walt.oid4vc.util.randomUUID
import id.walt.servicematrix.ServiceMatrix
import io.kotest.common.runBlocking
import io.kotest.core.spec.style.AnnotationSpec
Expand All @@ -16,6 +19,7 @@ import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.util.*
import kotlinx.serialization.json.jsonPrimitive

class EBSI_Conformance_Test: AnnotationSpec() {

Expand Down Expand Up @@ -52,6 +56,30 @@ class EBSI_Conformance_Test: AnnotationSpec() {
credentialResponses.size shouldBe 1
credentialResponses[0].isDeferred shouldBe false
credentialResponses[0].credential shouldNotBe null
//val cred = VerifiableCredential.fromString(credentialResponses[0].credential!!.jsonPrimitive.content)
//Custodian.getService().storeCredential(cred.id ?: randomUUID(), cred)
}

@Test
fun testReceiveCredentialSameDevice() {
val initCredentialOfferUrl = URLBuilder("https://api-conformance.ebsi.eu/conformance/v3/issuer-mock/initiate-credential-offer?credential_type=CTWalletSameInTime").run {
parameters.appendAll(StringValues.build {
append("client_id", credentialWallet.TEST_DID)
append("credential_offer_endpoint", "openid-credential-offer://")
})
build()
}
val httpResp = runBlocking { ktorClient.get(initCredentialOfferUrl) }
httpResp.status shouldBe HttpStatusCode.Found
val inTimeCredentialOfferRequestUri = httpResp.headers[HttpHeaders.Location]!!
val credentialOfferRequest = CredentialOfferRequest.fromHttpQueryString(Url(inTimeCredentialOfferRequestUri).encodedQuery)
val credentialOffer = credentialWallet.resolveCredentialOffer(credentialOfferRequest)
val credentialResponses = credentialWallet.executeFullAuthIssuance(credentialOffer, credentialWallet.TEST_DID, ebsiClientConfig)
credentialResponses.size shouldBe 1
credentialResponses[0].isDeferred shouldBe false
credentialResponses[0].credential shouldNotBe null
//val cred = VerifiableCredential.fromString(credentialResponses[0].credential!!.jsonPrimitive.content)
//Custodian.getService().storeCredential(cred.id ?: randomUUID(), cred)
}

@Test
Expand Down Expand Up @@ -95,4 +123,22 @@ class EBSI_Conformance_Test: AnnotationSpec() {
preAuthCredentialResponses[0].isSuccess shouldBe true
preAuthCredentialResponses[0].credential shouldNotBe null
}

//@Test
fun testIssuanceWithPresentationExchange() {
val initIssuanceWithPresentationExchangeUrl = URLBuilder("https://api-conformance.ebsi.eu/conformance/v3/issuer-mock/initiate-credential-offer?credential_type=CTWalletQualificationCredential").run {
parameters.appendAll(StringValues.build {
append("client_id", credentialWallet.TEST_DID)
append("credential_offer_endpoint", "openid-credential-offer://")
})
build()
}
val credentialOfferRequestUri = runBlocking { ktorClient.get(initIssuanceWithPresentationExchangeUrl).bodyAsText() }
val credentialOfferRequest = CredentialOfferRequest.fromHttpQueryString(Url(credentialOfferRequestUri).encodedQuery)
val credentialOffer = credentialWallet.resolveCredentialOffer(credentialOfferRequest)
val credentialResponses = credentialWallet.executeFullAuthIssuance(credentialOffer, credentialWallet.TEST_DID, ebsiClientConfig)
credentialResponses.size shouldBe 1
credentialResponses[0].isDeferred shouldBe false
credentialResponses[0].credential shouldNotBe null
}
}

0 comments on commit 692fd60

Please sign in to comment.