Skip to content

Commit

Permalink
[Android][iOS] Add Contexts for VC Playground VC 2.0 Issuance (#46)
Browse files Browse the repository at this point in the history
This adds some context files required for VC Playground VC 2.0 Issuance.
  • Loading branch information
Juliano1612 authored Nov 15, 2024
1 parent c1e09a1 commit 3631f95
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 127 deletions.
9 changes: 6 additions & 3 deletions example/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ android {
applicationId = "com.spruceid.mobilesdkexample"
minSdk = 26
targetSdk = 34
versionCode = 13
versionName = "1.0.0+13"
versionCode = 14
versionName = "1.1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
Expand All @@ -24,7 +24,10 @@ android {
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ import io.ktor.util.toMap

@Composable
fun HandleOID4VCIView(
navController: NavHostController,
url: String,
credentialPacksViewModel: CredentialPacksViewModel
navController: NavHostController,
url: String,
credentialPacksViewModel: CredentialPacksViewModel
) {
var loading by remember { mutableStateOf(false) }
var err by remember { mutableStateOf<String?>(null) }
Expand All @@ -47,38 +47,38 @@ fun HandleOID4VCIView(
loading = true
val client = HttpClient(CIO)
val oid4vciSession =
Oid4vci.newWithAsyncClient(
client =
object : AsyncHttpClient {
override suspend fun httpClient(
request: HttpRequest
): HttpResponse {
val res =
client.request(request.url) {
method = HttpMethod(request.method)
for ((k, v) in request.headers) {
headers[k] = v
}
setBody(request.body)
}

return HttpResponse(
statusCode = res.status.value.toUShort(),
headers =
res.headers.toMap().mapValues {
it.value.joinToString()
},
body = res.readBytes()
)
}
Oid4vci.newWithAsyncClient(
client =
object : AsyncHttpClient {
override suspend fun httpClient(
request: HttpRequest
): HttpResponse {
val res =
client.request(request.url) {
method = HttpMethod(request.method)
for ((k, v) in request.headers) {
headers[k] = v
}
)
setBody(request.body)
}

return HttpResponse(
statusCode = res.status.value.toUShort(),
headers =
res.headers.toMap().mapValues {
it.value.joinToString()
},
body = res.readBytes()
)
}
}
)

try {
oid4vciSession.initiateWithOffer(
credentialOffer = url,
clientId = "skit-demo-wallet",
redirectUrl = "https://spruceid.com"
credentialOffer = url,
clientId = "skit-demo-wallet",
redirectUrl = "https://spruceid.com"
)

val nonce = oid4vciSession.exchangeToken()
Expand All @@ -90,45 +90,45 @@ fun HandleOID4VCIView(
val jwk = keyManager.getJwk(id = "reference-app/default-signing")

val signingInput =
jwk?.let {
generatePopPrepare(
audience = metadata.issuer(),
nonce = nonce,
didMethod = DidMethod.JWK,
publicJwk = jwk,
durationInSecs = null
)
}
jwk?.let {
generatePopPrepare(
audience = metadata.issuer(),
nonce = nonce,
didMethod = DidMethod.JWK,
publicJwk = jwk,
durationInSecs = null
)
}

val signature =
signingInput?.let {
keyManager.signPayload(
id = "reference-app/default-signing",
payload = signingInput
)
}
signingInput?.let {
keyManager.signPayload(
id = "reference-app/default-signing",
payload = signingInput
)
}

val pop =
signingInput?.let {
signature?.let {
generatePopComplete(
signingInput = signingInput,
signature =
Base64.encodeToString(
signature,
Base64.URL_SAFE or
Base64.NO_PADDING or
Base64.NO_WRAP
)
.toByteArray()
signingInput?.let {
signature?.let {
generatePopComplete(
signingInput = signingInput,
signature =
Base64.encodeToString(
signature,
Base64.URL_SAFE or
Base64.NO_PADDING or
Base64.NO_WRAP
)
}
.toByteArray()
)
}
}

oid4vciSession.setContextMap(getVCPlaygroundOID4VCIContext(ctx = ctx))

val credentials =
pop?.let { oid4vciSession.exchangeCredential(proofsOfPossession = listOf(pop)) }
pop?.let { oid4vciSession.exchangeCredential(proofsOfPossession = listOf(pop)) }

credentials?.forEach { cred ->
cred.payload.toString(Charsets.UTF_8).let { credential = it }
Expand All @@ -144,15 +144,15 @@ fun HandleOID4VCIView(
LoadingView(loadingText = "Loading...")
} else if (err != null) {
ErrorView(
errorTitle = "Error Adding Credential",
errorDetails = err!!,
onClose = { navController.navigate(Screen.HomeScreen.route) { popUpTo(0) } }
errorTitle = "Error Adding Credential",
errorDetails = err!!,
onClose = { navController.navigate(Screen.HomeScreen.route) { popUpTo(0) } }
)
} else if (credential != null) {
AddToWalletView(
navController = navController,
rawCredential = credential!!,
credentialPacksViewModel = credentialPacksViewModel
navController = navController,
rawCredential = credential!!,
credentialPacksViewModel = credentialPacksViewModel
)
}
}
Expand All @@ -161,83 +161,90 @@ fun getVCPlaygroundOID4VCIContext(ctx: Context): Map<String, String> {
val context = mutableMapOf<String, String>()

context["https://contexts.vcplayground.org/examples/alumni/v1.json"] =
ctx.resources
.openRawResource(R.raw.contexts_vcplayground_org_examples_alumni_v1)
.bufferedReader()
.readLines()
.joinToString("")
ctx.resources
.openRawResource(R.raw.contexts_vcplayground_org_examples_alumni_v1)
.bufferedReader()
.readLines()
.joinToString("")

context["https://w3id.org/first-responder/v1"] =
ctx.resources
.openRawResource(R.raw.w3id_org_first_responder_v1)
.bufferedReader()
.readLines()
.joinToString("")
ctx.resources
.openRawResource(R.raw.w3id_org_first_responder_v1)
.bufferedReader()
.readLines()
.joinToString("")

context["https://w3id.org/vdl/aamva/v1"] =
ctx.resources
.openRawResource(R.raw.w3id_org_vdl_aamva_v1)
.bufferedReader()
.readLines()
.joinToString("")
ctx.resources
.openRawResource(R.raw.w3id_org_vdl_aamva_v1)
.bufferedReader()
.readLines()
.joinToString("")

context["https://w3id.org/citizenship/v3"] =
ctx.resources
.openRawResource(R.raw.w3id_org_citizenship_v3)
.bufferedReader()
.readLines()
.joinToString("")
ctx.resources
.openRawResource(R.raw.w3id_org_citizenship_v3)
.bufferedReader()
.readLines()
.joinToString("")

context["https://contexts.vcplayground.org/examples/movie-ticket/v1.json"] =
ctx.resources
.openRawResource(R.raw.contexts_vcplayground_org_examples_movie_ticket_v1)
.bufferedReader()
.readLines()
.joinToString("")
ctx.resources
.openRawResource(R.raw.contexts_vcplayground_org_examples_movie_ticket_v1)
.bufferedReader()
.readLines()
.joinToString("")

context["https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.2.json"] =
ctx.resources
.openRawResource(R.raw.purl_imsglobal_org_spec_ob_v3p0_context_3_0_2)
.bufferedReader()
.readLines()
.joinToString("")
ctx.resources
.openRawResource(R.raw.purl_imsglobal_org_spec_ob_v3p0_context_3_0_2)
.bufferedReader()
.readLines()
.joinToString("")

context["https://contexts.vcplayground.org/examples/food-safety-certification/v1.json"] =
ctx.resources
.openRawResource(
R.raw.contexts_vcplayground_org_examples_food_safety_certification_v1
)
.bufferedReader()
.readLines()
.joinToString("")
ctx.resources
.openRawResource(
R.raw.contexts_vcplayground_org_examples_food_safety_certification_v1
)
.bufferedReader()
.readLines()
.joinToString("")

context["https://contexts.vcplayground.org/examples/gs1-8110-coupon/v2.json"] =
ctx.resources
.openRawResource(R.raw.contexts_vcplayground_org_examples_gs1_8110_coupon_v2)
.bufferedReader()
.readLines()
.joinToString("")
ctx.resources
.openRawResource(R.raw.contexts_vcplayground_org_examples_gs1_8110_coupon_v2)
.bufferedReader()
.readLines()
.joinToString("")

context["https://contexts.vcplayground.org/examples/customer-loyalty/v1.json"] =
ctx.resources
.openRawResource(R.raw.contexts_vcplayground_org_examples_customer_loyalty_v1)
.bufferedReader()
.readLines()
.joinToString("")
ctx.resources
.openRawResource(R.raw.contexts_vcplayground_org_examples_customer_loyalty_v1)
.bufferedReader()
.readLines()
.joinToString("")

context["https://w3id.org/citizenship/v4rc1"] =
ctx.resources
.openRawResource(R.raw.w3id_org_citizenship_v4rc1)
.bufferedReader()
.readLines()
.joinToString("")
ctx.resources
.openRawResource(R.raw.w3id_org_citizenship_v4rc1)
.bufferedReader()
.readLines()
.joinToString("")

context["https://w3id.org/vc/render-method/v2rc1"] =
ctx.resources
.openRawResource(R.raw.w3id_org_vc_render_method_v2rc1)
.bufferedReader()
.readLines()
.joinToString("")
ctx.resources
.openRawResource(R.raw.w3id_org_vc_render_method_v2rc1)
.bufferedReader()
.readLines()
.joinToString("")

context["https://contexts.vcplayground.org/examples/movie-ticket-vcdm-v2/v1.json"] =
ctx.resources
.openRawResource(R.raw.contexts_vcplayground_org_examples_movie_ticket_vcdm_v2_v1)
.bufferedReader()
.readLines()
.joinToString("")

return context
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"@context": {
"@version": 1.1,
"@protected": true,
"MovieTicketCredential": "https://contexts.vcplayground.org/examples/movie-ticket/vocab#MovieTicketCredential",
"Ticket": "https://schema.org/Ticket",
"owns": {
"@id": "https://schema.org/owns",
"@type": "@id"
},
"name": "https://schema.org/name",
"description": "https://schema.org/description",
"identifier": "https://schema.org/identifier",
"image": {
"@id": "https://schema.org/image",
"@type": "@id"
},
"location": {
"@id": "https://schema.org/location",
"@type": "@id"
},
"startDate": {
"@id": "https://schema.org/startDate",
"@type": "http://www.w3.org/2001/XMLSchema#dateTime"
},
"ticketNumber": "https://schema.org/ticketNumber",
"ticketedSeat": "https://schema.org/ticketedSeat",
"ticketToken": "https://schema.org/ticketToken",
"seatNumber": "https://schema.org/seatNumber",
"seatRow": "https://schema.org/seatRow",
"seatSection": "https://schema.org/seatSection",
"address": "https://schema.org/address",
"addressLocality": "https://schema.org/addressLocality",
"addressRegion": "https://schema.org/addressRegion",
"postalCode": "https://schema.org/postalCode",
"streetAddress": "https://schema.org/streetAddress"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@
}
}
}
}
}

0 comments on commit 3631f95

Please sign in to comment.