OpenID4VCI-credentialin myöntäminen selitettynä: tarjouksesta hyväksyttyyn credentialiin
OpenID4VCI, OpenID for Verifiable Credential Issuance, määrittelee, miten wallet pyytää ja vastaanottaa credentialin myöntäjältä. Yksittäinen myöntäminen kulkee useiden erillisten vaiheiden läpi, ennen kuin walletilla on todella käyttökelpoinen credential, ja jokaisella vaiheella on oma epäonnistumistapansa. Tämä sivu käy läpi koko tämän elinkaaren, alkuperäisten esimerkkien avulla.
Kaksi tapaa aloittaa: pre-authorized code ja authorization code
Myöntäminen alkaa usein myöntäjän lähettämästä Credential Offer -tarjouksesta, ja sen nimeämä grant ratkaisee, miten wallet valtuutetaan. Wallet voi myös aloittaa myöntämisen itse, ilman mitään tarjousta, authorization code -kulun kautta. Molemmat kulut päätyvät samaan pisteeseen: walletilla on käyttöoikeustoken, jota se voi käyttää credentialin pyytämiseen.
Pre-authorized code -kulku
1. Myöntäjä
Tuntee haltijan jo ja antaa Credential Offer -tarjouksen, jossa on pre-authorized_code
2. Wallet
Lunastaa koodin token-päätepisteessä, valinnaisesti transaktiokoodilla
3. Wallet
Pyytää credentialia todistaen hallitsevansa avainta
Authorization code -kulku
1. Wallet
Skannaa Credential Offer -tarjouksen, jossa mainitaan authorization_code-grant, tai aloittaa kulun itse ilman tarjousta
2. Valtuutuspalvelin
Vie haltijan kirjautumisen ja suostumuksen läpi ja myöntää sitten koodin
3. Wallet
Vaihtaa koodin tokeniin ja pyytää sitten credentialia
Credential-tarjouksen koko elinkaari
Spesifikaatio ei määrittele nimettyjä tiloja, mutta myöntäjän käynnistämä kulku, jossa credential myönnetään heti, on helpoin seurata alla olevan sekvenssin tapaan. Jokainen vaihe voi epäonnistua omalla tavallaan, ja walletin toteutuksen on käsiteltävä nämä polut, ei vain onnistunutta reittiä.
Esimerkki: katsastustodistus kuljetuskalustolle
Ajoneuvojen katsastuslaitos myöntää katsastustodistuksen kuljetusyrityksen yrityswalletiin rutiinikatsastuksen jälkeen. Katsastaja on jo todentanut kalustopäällikön katsastuspisteessä, joten myöntäjä käyttää pre-authorized code -kulkua. Alla olevat vaiheet seuraavat tätä yksittäistä myöntämistä tarjouksesta hyväksyttyyn credentialiin.
Esimerkki näyttää peruspiirteisen OpenID4VCI:n. Korkean varmuuden käyttöönotot, kuten EUDI Wallet, noudattavat tämän lisäksi HAIP-profiilia, joka lisää DPoP-sidottuja käyttöoikeustokeneita, wallet attestationin token-päätepisteessä ja key attestationin credential-avaimille. Ne on jätetty tästä pois, jotta jokainen vaihe pysyy luettavana.
1. Credential offer
Katsastuslaitoksen päätelaite näyttää QR-koodin. Se sisältää URI:n, joka alkaa openid-credential-offer:// ja kantaa alla olevaa tarjousta, URL-koodattuna credential_offer-parametrissa, tai credential_offer_uri-arvon, josta wallet hakee sen. Wallet skannaa sen ja lukee, mikä credential on tarjolla ja miten se hankitaan.
Myöntäjä
Näyttää QR-koodin, jossa on Credential Offer
Nimeää credential-konfiguraation ja pre-authorized_code-grantin
{
"credential_issuer": "https://issuer.fleetinspect.example",
"credential_configuration_ids": ["roadworthiness_certificate"],
"grants": {
"urn:ietf:params:oauth:grant-type:pre-authorized_code": {
"pre-authorized_code": "fi-8f2c0b3a",
"tx_code": {
"length": 6,
"input_mode": "numeric",
"description": "Enter the code sent to your phone by text message"
}
}
}
}2. Myöntäjän metatietojen haku
Ennen kuin wallet pyytää mitään, se hakee myöntäjän metatiedot selvittääkseen, mitä roadworthiness_certificate sisältää ja mitä päätepisteitä sen tulee kutsua. Metatiedot eivät listaa erillisiä valtuutuspalvelimia, joten myöntäjä on oma valtuutuspalvelimensa, ja wallet lukee token-päätepisteen kyseisen palvelimen metatiedoista.
Wallet
GET /.well-known/openid-credential-issuer
Selvittää credential-muodon, väitteet ja hyväksytyt proof-tyypit sekä nonce-, credential-, deferred- ja notification-päätepisteet
Credentialin myöntäjän metatiedot (ote)
{
"credential_issuer": "https://issuer.fleetinspect.example",
"nonce_endpoint": "https://issuer.fleetinspect.example/nonce",
"credential_endpoint": "https://issuer.fleetinspect.example/credential",
"deferred_credential_endpoint": "https://issuer.fleetinspect.example/deferred",
"notification_endpoint": "https://issuer.fleetinspect.example/notify",
"credential_configurations_supported": {
"roadworthiness_certificate": {
"format": "dc+sd-jwt",
"vct": "https://fleetinspect.example/vct/roadworthiness",
"cryptographic_binding_methods_supported": ["jwk"],
"credential_signing_alg_values_supported": ["ES256"],
"proof_types_supported": {
"jwt": { "proof_signing_alg_values_supported": ["ES256"] }
},
"credential_metadata": {
"claims": [
{ "path": ["vehicle_registration"] },
{ "path": ["inspection_result"] },
{ "path": ["valid_until"] }
]
}
}
}
}Valtuutuspalvelimen metatiedot (ote), osoitteesta /.well-known/oauth-authorization-server
{
"issuer": "https://issuer.fleetinspect.example",
"token_endpoint": "https://issuer.fleetinspect.example/token",
"pre-authorized_grant_anonymous_access_supported": true
}3. Token-pyyntö
Wallet lunastaa pre-authorized coden token-päätepisteessä yhdessä transaktiokoodin kanssa, jonka katsastuslaitos lähetti kalustopäällikön puhelimeen. Koodin lähettäminen toista kanavaa pitkin tarkoittaa, että joku, joka kuvaa QR-koodin olan yli, ei silti pysty lunastamaan sitä.
Wallet
POST /token
Lähettää pre-authorized_code- ja tx_code-arvot, saa käyttöoikeustokenin, joka rajautuu tähän tarjoukseen
POST /token HTTP/1.1 Host: issuer.fleetinspect.example Content-Type: application/x-www-form-urlencoded grant_type=urn:ietf:params:oauth:grant-type:pre-authorized_code &pre-authorized_code=fi-8f2c0b3a &tx_code=482913
Vastaus
{
"access_token": "fi-at-3d91e0",
"token_type": "Bearer",
"expires_in": 86400
}4. Hallinnan todistus
Koska metatiedot listaavat nonce_endpoint-päätepisteen, wallet hakee sieltä ensin tuoreen c_nonce-arvon. Sitten se todistaa hallitsevansa yksityistä avainta, johon credential sidotaan, allekirjoittamalla proof JWT:n myöntäjän tunnisteen ja tämän c_nonce-arvon yli.
Wallet
POST /nonce, allekirjoittaa sitten proof JWT:n avaimella, johon credential sidotaan
Sitoo credentialin tähän avaimeen, ei pelkästään käyttöoikeustokenin haltijaan
POST /nonce HTTP/1.1 Host: issuer.fleetinspect.example
Vastaus
{
"c_nonce": "fi-nonce-77aa"
}Wallet rakentaa nyt proof JWT:n kahdesta JSON-objektista, headerista ja payloadista, ja allekirjoittaa ne yksityisellä avaimella, johon credential sidotaan.
Header: mikä tämä JWT on ja mikä avain sen allekirjoitti
{
"typ": "openid4vci-proof+jwt",
"alg": "ES256",
"jwk": { "kty": "EC", "crv": "P-256", "x": "...", "y": "..." }
}typ: merkitsee tämän OpenID4VCI key proofiksi, jotta sitä ei sekoiteta muunlaiseen JWT:henalg: allekirjoitusalgoritmi, jonka myöntäjä listasi proof_signing_alg_values_supported-arvossajwk: julkinen avain, johon credential sidotaan; myöntäjä tarkistaa allekirjoituksen sitä vasten
Payload: kenelle proof on tarkoitettu ja milloin se tehtiin
{
"aud": "https://issuer.fleetinspect.example",
"iat": 1789376400,
"nonce": "fi-nonce-77aa"
}aud: myöntäjän tunniste, jotta proofia ei voi toistaa toisessa myöntäjässäiat: hetki, jolloin proof luotiin, sekunteina vuodesta 1970nonce: nonce-päätepisteestä saatu c_nonce, joka osoittaa proofin olevan tuore
Allekirjoitettu tulos
Header ja payload koodataan kumpikin base64url-muotoon ja yhdistetään pisteellä. Wallet allekirjoittaa tämän merkkijonon yksityisellä avaimellaan ja liittää base64url-koodatun allekirjoituksen toisen pisteen jälkeen. Syntyvä merkkijono on proof JWT, jonka wallet lähettää credential-pyynnössä vaiheessa 5.
base64url(header) . base64url(payload) . base64url(signature) eyJ0eXAiOiJvcGVuaWQ0dmNpLXByb29mK2p3dCIs... .eyJhdWQiOiJodHRwczovL2lzc3Vlci5mbGVldGluc3BlY3QuZXhhbXBsZSIs... .<ES256 signature>
5. Credential-pyyntö
Wallet kutsuu credential-päätepistettä käyttöoikeustokenilla ja proofilla, ja myöntäjä luo ja palauttaa allekirjoitetun credentialin.
Wallet
POST /credential
Lähettää käyttöoikeustokenin, konfiguraatio-id:n ja proof JWT:n, saa allekirjoitetun credentialin ja notification_id:n
POST /credential HTTP/1.1
Host: issuer.fleetinspect.example
Content-Type: application/json
Authorization: Bearer fi-at-3d91e0
{
"credential_configuration_id": "roadworthiness_certificate",
"proofs": {
"jwt": ["<proof JWT from step 4>"]
}
}Vastaus
{
"credentials": [
{ "credential": "<issuer-signed SD-JWT VC>" }
],
"notification_id": "fi-notif-9012"
}Koko kulku yhdellä silmäyksellä
Tämä sekvenssikaavio kokoaa yhteen esimerkin viisi vaihetta, tarjouksesta ilmoitukseen. Yhtenäiset nuolet ovat pyyntöjä, katkoviivanuolet vastauksia, ja pisteviivanuoli kuvaa transaktiokoodia, joka kulkee protokollan ulkopuolella tekstiviestillä.
Wallet
Kuljetusyrityksen yrityswallet
Valtuutuspalvelin
Tässä esimerkissä myöntäjä ajaa sitä itse
Credentialin myöntäjä
Ajoneuvojen katsastuslaitos
- Credentialin myöntäjä kohteeseen Wallet: Credential Offer, esitetty QR-koodina
- Credentialin myöntäjä kohteeseen Wallet: tx_code, lähetetty tekstiviestillä kalustopäällikön puhelimeen
- Wallet kohteeseen Credentialin myöntäjä: GET /.well-known/openid-credential-issuer
- Credentialin myöntäjä kohteeseen Wallet: credentialin myöntäjän metatiedot
- Wallet kohteeseen Valtuutuspalvelin: GET /.well-known/oauth-authorization-server
- Valtuutuspalvelin kohteeseen Wallet: valtuutuspalvelimen metatiedot
- Wallet kohteeseen Valtuutuspalvelin: POST /token: pre-authorized_code, tx_code
- Valtuutuspalvelin kohteeseen Wallet: access_token
- Wallet kohteeseen Credentialin myöntäjä: POST /nonce
- Credentialin myöntäjä kohteeseen Wallet: c_nonce
- Wallet: allekirjoittaa proof JWT:n
- Wallet kohteeseen Credentialin myöntäjä: POST /credential: käyttöoikeustoken, proofit
- Credentialin myöntäjä kohteeseen Wallet: credentials, notification_id
- Wallet: validoi ja tallentaa
- Wallet kohteeseen Credentialin myöntäjä: POST /notify: credential_accepted
- Credentialin myöntäjä kohteeseen Wallet: 204 No Content
Kun credential ei ole vielä valmis: viivästetty myöntäminen
Yllä oleva esimerkki olettaa, että katsastustulos on jo lopullinen. Jos katsastuslaitoksen sen sijaan täytyy eskaloida rajatapaus vanhemmalle katsastajalle, credential-päätepiste ei voi palauttaa credentialia heti, joten se viivästää myöntämistä.
Välitön myöntäminen
Credential-päätepiste palauttaa allekirjoitetun credentialin samassa vastauksessa kuin pyyntö.
Viivästetty myöntäminen
Credential-päätepiste vastaa koodilla HTTP 202 sekä transaction_id- ja interval-arvolla. Wallet kysyy deferred credential -päätepisteeltä kyseisellä id:llä, odottaen vähintään interval sekuntia pyyntöjen välillä, kunnes credential on valmis.
Viivästetty vastaus osoitteesta /credential
HTTP/1.1 202 Accepted
Content-Type: application/json
{
"transaction_id": "fi-tx-55c2",
"interval": 900
}/deferred-osoitteen kysely, kunnes se on valmis
POST /deferred HTTP/1.1
Host: issuer.fleetinspect.example
Content-Type: application/json
Authorization: Bearer fi-at-3d91e0
{ "transaction_id": "fi-tx-55c2" }
// While the review is open: 202 with the same transaction_id and interval.
// Once approved: 200 with the credentials, optionally with a notification_id.
// If the review rejects the result: a credential_request_denied error.Kehän sulkeminen: notification-päätepiste
Myöntämisen jälkeen wallet voi kertoa myöntäjälle, mitä credentialille tapahtui, käyttäen credential-vastauksesta saatua notification_id-arvoa. Walleteilla ei ole pakko lähettää näitä ilmoituksia, eikä toimitusta taata, joten myöntäjä ei voi tulkita puuttuvasta ilmoituksesta mitään.
Wallet
Lähettää tapahtuman myöntäjän notification_endpoint-päätepisteeseen vastaanotetulle notification_id:lle, joka kattaa jokaisen kyseisen vastauksen credentialin
Tallennettu walletiin
Myöntäminen epäonnistui jostain muusta syystä, esimerkiksi koska credential ei validoitunut
Myöntäminen epäonnistui haltijan toiminnan vuoksi, esimerkiksi koska hän kieltäytyi tallentamasta sitä
POST /notify HTTP/1.1
Host: issuer.fleetinspect.example
Content-Type: application/json
Authorization: Bearer fi-at-3d91e0
{
"notification_id": "fi-notif-9012",
"event": "credential_accepted"
}Aiheeseen liittyvät termit
Usein kysytyt kysymykset
Mistä wallet tietää, mitä grant-tyyppiä käyttää?
Credential Offer nimeää grantin grants-objektissaan. authorization_code on läsnä, kun myöntäjä haluaa haltijan kirjautuvan osana kulkua. pre-authorized_code on läsnä, kun haltija oli jo todennettu kanavalla, jolla tarjous luotiin, esimerkiksi katsastajan toimesta katsastuspisteessä alla olevassa esimerkissä. Tarjous voi listata molemmat, jolloin wallet valitsee toisen. Jos tarjouksessa ei ole lainkaan grants-objektia, wallet tarkistaa valtuutuspalvelimen metatiedoista, mitä grant-tyyppejä tämä tukee.
Miksi wallet hakee myöntäjän metatiedot ennen kuin pyytää mitään?
Credential Offer nimeää vain credential_configuration_ids-arvot, myöntäjän URL:n ja grantit. Myöntäjän metatiedot, jotka tarjotaan well-known-polusta, kuvaavat kunkin konfiguraation: sen muodon, sen väitteet (claims) ja hyväksytyt proof-tyypit, sekä nonce-, credential-, deferred- ja notification-päätepisteet. Ne kertovat myös, mitä valtuutuspalvelinta käyttää, ja kyseisen palvelimen omat metatiedot antavat token-päätepisteen. Ilman molempia wallet ei tietäisi, miten rakentaa kelvollisia pyyntöjä tai mitä näyttää haltijalle ennen suostumusta.
Mitä hallinnan todistus oikeastaan todistaa?
Se todistaa, että credentialia pyytävä wallet hallitsee yksityistä avainta, johon credential sidotaan, eikä pelkästään että sillä on voimassa oleva käyttöoikeustoken. Wallet allekirjoittaa proof JWT:n myöntäjän tunnisteen ja myöntäjän nonce-päätepisteestä saadun tuoreen c_nonce-arvon yli käyttäen tätä avainta. Myöntäjä sisällyttää vastaavan julkisen avaimen credentialiin. Verifioija, joka vaatii avainsidontaa, pyytää haltijaa allekirjoittamaan uudelleen samalla avaimella esittäessään credentialin, jolloin kopioitu credential ilman avainta ei läpäise tätä tarkistusta.
Miksi myöntäjä viivästäisi myöntämistä sen sijaan, että palauttaisi credentialin heti?
Osaa myöntäjän ennen credentialin luomista tekemistä tarkistuksista ei voida suorittaa loppuun yhden HTTP-pyynnön sisällä, esimerkiksi manuaalista tarkastusta tai kutsua hitaaseen ulkoiseen rekisteriin. Viivästetty myöntäminen mahdollistaa sen, että credential-päätepiste vastaa heti transaction_id-arvolla yhteyden estämisen sijaan, ja wallet kysyy deferred-päätepisteeltä tällä id:llä, kunnes tarkistus valmistuu ja credential on valmis noudettavaksi.
Onko notification-päätepiste pakollinen myöntäjälle?
Ei. Se on myöntäjille valinnainen, eikä walleteillakaan ole pakko käyttää sitä. Kun molemmat tukevat sitä, myöntäjä saa tietää, mitä myöntämisen jälkeen tapahtui: credentialit tallennettiin (credential_accepted), haltija pysäytti myöntämisen, esimerkiksi kieltäytymällä tallentamasta niitä (credential_deleted), tai se epäonnistui jostain muusta syystä (credential_failure). Toimitusta ei taata, joten myöntäjän tulisi pitää ilmoitusta hyödyllisenä tietona, ei koskaan luotettavana tallenteena, eikä se voi päätellä mitään puuttuvasta ilmoituksesta.
Lähteet
Tämä sivu on informatiivinen eikä muodosta oikeudellista neuvontaa. Luotettavaa ohjeistusta varten ota yhteyttä suoraan OpenID Foundationiin ja Euroopan komissioon.