Skip to content

Commit

Permalink
test: add AnonCreds API e2e tests
Browse files Browse the repository at this point in the history
Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
  • Loading branch information
yshyn-iohk committed Jan 20, 2025
1 parent 1766228 commit d54a18d
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 7 deletions.
2 changes: 1 addition & 1 deletion tests/integration-tests/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ dependencies {
testImplementation("io.ktor:ktor-server-netty:2.3.0")
testImplementation("io.ktor:ktor-client-apache:2.3.0")
// RestAPI client
testImplementation("org.hyperledger.identus:cloud-agent-client-kotlin:1.40.1-8363d1e")
testImplementation("org.hyperledger.identus:cloud-agent-client-kotlin:1.40.1-1766228")
// Test helpers library
testImplementation("io.iohk.atala:atala-automation:0.4.0")
// Hoplite for configuration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import java.util.UUID

enum class CreateCredentialOfferAPIVersion {
V0 {
override fun buildCredentialOfferRequest(
override fun buildJWTCredentialOfferRequest(
credentialType: CredentialType,
did: String,
assertionKey: String,
Expand All @@ -23,10 +23,46 @@ enum class CreateCredentialOfferAPIVersion {
credentialFormat = credentialType.format,
automaticIssuance = false,
)

override fun buildSDJWTCredentialOfferRequest(
credentialType: CredentialType,
did: String,
assertionKey: String,
schemaUrl: String?,
claims: Map<String, Any>,
connectionId: UUID,
validityPeriod: Double?,
): CreateIssueCredentialRecordRequest = CreateIssueCredentialRecordRequest(
schemaId = schemaUrl,
claims = claims,
issuingDID = did,
issuingKid = assertionKey,
connectionId = connectionId,
validityPeriod = validityPeriod ?: 3600.0,
credentialFormat = credentialType.format,
automaticIssuance = false,
)

override fun buildAnonCredsCredentialOfferRequest(
credentialType: CredentialType,
did: String,
credentialDefinitionId: UUID,
claims: Map<String, Any>,
connectionId: UUID,
validityPeriod: Double?,
) = CreateIssueCredentialRecordRequest(
credentialDefinitionId = credentialDefinitionId,
claims = claims,
issuingDID = did,
connectionId = connectionId,
validityPeriod = validityPeriod ?: 3600.0,
credentialFormat = credentialType.format,
automaticIssuance = false,
)
},

V1 {
override fun buildCredentialOfferRequest(
override fun buildJWTCredentialOfferRequest(
credentialType: CredentialType,
did: String,
assertionKey: String,
Expand All @@ -53,8 +89,25 @@ enum class CreateCredentialOfferAPIVersion {
validityPeriod = validityPeriod ?: 3600.0,
)
} else {
null
throw IllegalArgumentException("Unsupported credential type: $credentialType")
},
)

override fun buildSDJWTCredentialOfferRequest(
credentialType: CredentialType,
did: String,
assertionKey: String,
schemaUrl: String?,
claims: Map<String, Any>,
connectionId: UUID,
validityPeriod: Double?,
): CreateIssueCredentialRecordRequest = CreateIssueCredentialRecordRequest(
issuingKid = assertionKey,
connectionId = connectionId,
credentialFormat = credentialType.format,
automaticIssuance = false,
claims = null,
issuingDID = null,
sdJwtVcPropertiesV1 = if (credentialType == CredentialType.SD_JWT_VCDM_1_1) {
SDJWTVCPropertiesV1(
credentialSchema = CredentialSchemaRef(
Expand All @@ -67,13 +120,43 @@ enum class CreateCredentialOfferAPIVersion {
validityPeriod = validityPeriod ?: 3600.0,
)
} else {
null
throw IllegalArgumentException("Unsupported credential type: $credentialType")
},
)

override fun buildAnonCredsCredentialOfferRequest(
credentialType: CredentialType,
did: String,
credentialDefinitionId: UUID,
claims: Map<String, Any>,
connectionId: UUID,
validityPeriod: Double?
) = CreateIssueCredentialRecordRequest(
connectionId = connectionId,
credentialFormat = credentialType.format,
automaticIssuance = false,
anoncredsVcPropertiesV1 =
AnonCredsVCPropertiesV1(
issuingDID = did,
credentialDefinitionId = credentialDefinitionId,
claims = claims,
validityPeriod = validityPeriod ?: 3600.0,
)
)
},
;

abstract fun buildCredentialOfferRequest(
abstract fun buildJWTCredentialOfferRequest(
credentialType: CredentialType,
did: String,
assertionKey: String,
schemaUrl: String?,
claims: Map<String, Any>,
connectionId: UUID,
validityPeriod: Double? = null,
): CreateIssueCredentialRecordRequest

abstract fun buildSDJWTCredentialOfferRequest(
credentialType: CredentialType,
did: String,
assertionKey: String,
Expand All @@ -82,4 +165,13 @@ enum class CreateCredentialOfferAPIVersion {
connectionId: UUID,
validityPeriod: Double? = null,
): CreateIssueCredentialRecordRequest

abstract fun buildAnonCredsCredentialOfferRequest(
credentialType: CredentialType,
did: String,
credentialDefinitionId: UUID,
claims: Map<String, Any>,
connectionId: UUID,
validityPeriod: Double? = null,
): CreateIssueCredentialRecordRequest
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ enum class CredentialClaims {
"lastName" to "Doe",
)
},
ANONCREDS_STUDENT_CLAIMS {
override val claims: Map<String, Any> = linkedMapOf(
"name" to "Bob",
"age" to "21",
"sex" to "M",
)
}
;

abstract val claims: Map<String, Any>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package steps.credentials

import common.CreateCredentialOfferAPIVersion
import common.CredentialType
import interactions.Post
import interactions.body
import io.cucumber.java.en.When
Expand Down Expand Up @@ -47,4 +49,39 @@ class AnoncredSteps {
issuer.remember("thid", credentialRecord.thid)
holder.remember("thid", credentialRecord.thid)
}

@When("{actor} sends the prepared anoncreds credential offer to {actor}")
fun issuerSendsThePreparedAnonCredsOfferToHolder(issuer: Actor, holder: Actor) {
val api = issuer.recall<CreateCredentialOfferAPIVersion>("currentAPI")
val credentialType = issuer.recall<CredentialType>("currentCredentialType")
val did = issuer.recall<String>("currentDID")
val claims = issuer.recall<Map<String, Any>>("currentClaims")
val connectionId = issuer.recall<Connection>("connection-with-${holder.name}").connectionId
val credentialDefinitionId = issuer.recall<CredentialDefinitionResponse>("anoncredsCredentialDefinition").guid

val request = api.buildAnonCredsCredentialOfferRequest(credentialType, did, credentialDefinitionId, claims, connectionId)

val credentialOfferRequest = CreateIssueCredentialRecordRequest(
credentialDefinitionId = issuer.recall<CredentialDefinitionResponse>("anoncredsCredentialDefinition").guid,
claims = linkedMapOf(
"name" to "Bob",
"age" to "21",
"sex" to "M",
),
issuingDID = issuer.recall("shortFormDid"),
connectionId = issuer.recall<Connection>("connection-with-${holder.name}").connectionId,
validityPeriod = 3600.0,
credentialFormat = "AnonCreds",
automaticIssuance = false,
)

issuer.attemptsTo(
Post.to("/issue-credentials/credential-offers").body(credentialOfferRequest),
Ensure.thatTheLastResponse().statusCode().isEqualTo(SC_CREATED),
)

val credentialRecord = SerenityRest.lastResponse().get<IssueCredentialRecord>()
issuer.remember("thid", credentialRecord.thid)
holder.remember("thid", credentialRecord.thid)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class CredentialSteps {
val api = issuer.recall<CreateCredentialOfferAPIVersion>("currentAPI")
val credentialType = issuer.recall<CredentialType>("currentCredentialType")
val did = issuer.recall<String>("currentDID")

val assertionKey = issuer.recall<String>("currentAssertionKey")
val schema = issuer.recall<CredentialSchema>("currentSchema")
val schemaGuid = issuer.recall<String>(schema.name)
Expand All @@ -89,7 +90,11 @@ class CredentialSteps {
"${issuer.recall<String>("baseUrl")}/schema-registry/schemas/$it"
}

val credentialOfferRequest = api.buildCredentialOfferRequest(credentialType, did, assertionKey, schemaUrl!!, claims, connectionId)
val credentialOfferRequest = when (credentialType) {
CredentialType.JWT_VCDM_1_1 -> api.buildJWTCredentialOfferRequest(credentialType, did, assertionKey, schemaUrl!!, claims, connectionId)
CredentialType.SD_JWT_VCDM_1_1 -> api.buildSDJWTCredentialOfferRequest(credentialType, did, assertionKey, schemaUrl!!, claims, connectionId)
else -> throw IllegalArgumentException("Unsupported credential type: $credentialType")
}

issuer.attemptsTo(
Post.to("/issue-credentials/credential-offers").body(credentialOfferRequest),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@anoncred @issuance @refactoring
Feature: Issue Anoncreds credential using different REST API request versions

Background:
Given Issuer and Holder have an existing connection
And Issuer has a published DID for 'ANONCRED'
And Issuer has an anoncred schema definition
And Holder has an unpublished DID for 'ANONCRED'

Scenario Outline: Issuing jwt credential using different API version
When Issuer prepares the credential in 'ANONCREDS_V1' format using the '<createCredentialOfferApiVersion>' API
And Issuer prepares to use a 'short' form of DID with key id 'assertion-1'
And Issuer prepares the claims '<claims>' for the credential
And Issuer sends the prepared anoncreds credential offer to Holder
And Holder receives the credential offer
And Holder accepts anoncred credential offer
And Issuer issues the credential
Then Holder receives the issued credential
Examples:
| createCredentialOfferApiVersion | claims |
| V0 | ANONCREDS_STUDENT_CLAIMS |
| V1 | ANONCREDS_STUDENT_CLAIMS |

0 comments on commit d54a18d

Please sign in to comment.