Přejít na hlavní obsah

Vydávání pověření OpenID4VCI vysvětleno: od nabídky k přijatému pověření

OpenID4VCI, OpenID for Verifiable Credential Issuance, definuje, jak peněženka žádá o pověření od vydavatele a jak jej získává. Jedno vydání prochází několika odlišnými kroky, než peněženka skutečně získá použitelné pověření, a každý z nich má svůj vlastní způsob selhání. Tato stránka prochází celý tento životní cyklus, s původními názornými příklady.

Dva způsoby zahájení: předautorizovaný kód a autorizační kód

Vydávání často začíná od Credential Offer zaslané vydavatelem, a grant, který uvádí, rozhoduje o tom, jak bude peněženka autorizována. Peněženka může vydávání zahájit i sama, bez jakékoli nabídky, pomocí toku s autorizačním kódem. Oba toky končí na stejném místě: peněženka má přístupový token, který může použít k vyžádání pověření.

Tok s předautorizovaným kódem

1. Vydavatel

Již zná držitele, vydá Credential Offer s pre-authorized_code

2. Peněženka

Uplatní kód na tokenovém endpointu, volitelně s transakčním kódem

3. Peněženka

Požádá o pověření s důkazem držení svého klíče

Tok s autorizačním kódem

1. Peněženka

Naskenuje Credential Offer, která uvádí grant authorization_code, nebo zahájí tok sama bez nabídky

2. Autorizační server

Provede držitele přihlášením a souhlasem, poté vydá kód

3. Peněženka

Vymění kód za token a poté požádá o pověření

Celý životní cyklus nabídky pověření

Specifikace nedefinuje pojmenované stavy, ale tok zahájený vydavatelem, ve kterém je pověření vydáno rovnou, se nejsnáze sleduje jako sekvence níže. Každý krok může selhat svým vlastním způsobem a implementace peněženky musí zvládnout i tyto cesty, nejen tu úspěšnou.

Nabídka vytvořena
QR kód nebo odkaz otevře peněženku
Nabídka přijata
grant uplatněn
Token získán
nonce a důkaz držení
Pověření vyžádáno
pověření vytvořeno
Pověření vydáno
peněženka ověří a uloží
Pověření přijato
Kde může dojít k selhání, v pořadí kroků:
Platnost kódu vypršela před uplatněním
Žádost o token zamítnuta
Žádost o pověření zamítnuta
Pověření nebylo uloženo

Názorný příklad: osvědčení o technické způsobilosti pro dopravní flotilu

Stanice technické kontroly vozidel vydá osvědčení o technické způsobilosti do firemní peněženky dopravní společnosti po rutinní kontrole. Inspektor už vedoucího vozového parku ověřil na místě kontroly, takže vydavatel použije tok s předautorizovaným kódem. Následující kroky sledují toto jediné vydání od nabídky až po přijaté pověření.

Příklad ukazuje základní OpenID4VCI. Nasazení s vysokou úrovní záruky, jako je EUDI Wallet, na něm staví profil HAIP, který přidává přístupové tokeny vázané na DPoP, atestaci peněženky na tokenovém endpointu a atestaci klíčů pro klíče pověření. Ty jsou zde kvůli srozumitelnosti každého kroku vynechány.

1. Nabídka pověření

Terminál stanice technické kontroly zobrazí QR kód. Obsahuje URI začínající openid-credential-offer://, který nese níže uvedenou nabídku zakódovanou v URL v parametru credential_offer, nebo credential_offer_uri, ze kterého si ji peněženka stáhne. Peněženka kód naskenuje a přečte, jaké pověření je nabízeno a jak jej získat.

Vydavatel

Zobrazí QR kód s Credential Offer

Uvádí konfiguraci pověření a grant pre-authorized_code

{
  "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. Zjišťování metadat vydavatele

Než o cokoli požádá, peněženka si stáhne metadata vydavatele, aby zjistila, co obsahuje roadworthiness_certificate a jaké endpointy volat. Metadata neuvádí žádné samostatné autorizační servery, takže vydavatel je svým vlastním autorizačním serverem, a peněženka si tokenový endpoint přečte z metadat tohoto serveru.

Peněženka

GET /.well-known/openid-credential-issuer

Zjistí formát pověření, tvrzení a přijímané typy důkazů, a také endpointy pro nonce, pověření, odložení a notifikace

Metadata vydavatele pověření (výňatek)

{
  "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"] }
        ]
      }
    }
  }
}

Metadata autorizačního serveru (výňatek), z /.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. Žádost o token

Peněženka uplatní předautorizovaný kód na tokenovém endpointu spolu s transakčním kódem, který stanice technické kontroly zaslala na telefon vedoucího vozového parku. Odeslání tohoto kódu druhým kanálem znamená, že ten, kdo vyfotí QR kód přes rameno, jej stále nemůže uplatnit.

Peněženka

POST /token

Odešle pre-authorized_code a tx_code, obdrží přístupový token omezený na tuto nabídku

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

Odpověď

{
  "access_token": "fi-at-3d91e0",
  "token_type": "Bearer",
  "expires_in": 86400
}

4. Důkaz držení

Protože metadata uvádějí nonce_endpoint, peněženka si odtud nejprve stáhne čerstvý c_nonce. Poté dokáže, že vlastní soukromý klíč, ke kterému bude pověření vázáno, tím, že podepíše proof JWT nad identifikátorem vydavatele a tímto c_nonce.

Peněženka

POST /nonce, poté podepíše proof JWT klíčem, ke kterému bude pověření vázáno

Váže pověření k tomuto klíči, nikoli pouze k tomu, kdo drží přístupový token

POST /nonce HTTP/1.1
Host: issuer.fleetinspect.example

Odpověď

{
  "c_nonce": "fi-nonce-77aa"
}

Peněženka nyní sestaví proof JWT ze dvou JSON objektů, hlavičky a payloadu, a podepíše je soukromým klíčem, ke kterému bude pověření vázáno.

Hlavička: co tento JWT je a jaký klíč jej podepsal

{
  "typ": "openid4vci-proof+jwt",
  "alg": "ES256",
  "jwk": { "kty": "EC", "crv": "P-256", "x": "...", "y": "..." }
}
  • typ: označuje toto jako důkaz klíče OpenID4VCI, takže jej nelze zaměnit s jiným typem JWT
  • alg: podpisový algoritmus, jeden z těch, které vydavatel uvedl v proof_signing_alg_values_supported
  • jwk: veřejný klíč, ke kterému bude pověření vázáno; vydavatel proti němu ověřuje podpis

Payload: pro koho je důkaz určen a kdy vznikl

{
  "aud": "https://issuer.fleetinspect.example",
  "iat": 1789376400,
  "nonce": "fi-nonce-77aa"
}
  • aud: identifikátor vydavatele, díky kterému nelze důkaz přehrát u jiného vydavatele
  • iat: čas vytvoření důkazu, v sekundách od roku 1970
  • nonce: c_nonce z nonce endpointu, který ukazuje, že důkaz je čerstvý

Podepsaný výsledek

Hlavička a payload jsou každý zakódovány v base64url a spojeny tečkou. Peněženka tento řetězec podepíše svým soukromým klíčem a připojí za druhou tečku podpis zakódovaný v base64url. Výsledný řetězec je proof JWT, který peněženka odesílá v žádosti o pověření v kroku 5.

base64url(header) . base64url(payload) . base64url(signature)

eyJ0eXAiOiJvcGVuaWQ0dmNpLXByb29mK2p3dCIs...
  .eyJhdWQiOiJodHRwczovL2lzc3Vlci5mbGVldGluc3BlY3QuZXhhbXBsZSIs...
  .<ES256 signature>

5. Žádost o pověření

Peněženka volá endpoint pověření s přístupovým tokenem a důkazem, a vydavatel vytvoří a vrátí podepsané pověření.

Peněženka

POST /credential

Odešle přístupový token, identifikátor konfigurace a proof JWT, obdrží podepsané pověření a notification_id

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>"]
  }
}

Odpověď

{
  "credentials": [
    { "credential": "<issuer-signed SD-JWT VC>" }
  ],
  "notification_id": "fi-notif-9012"
}

Celý tok na jeden pohled

Tento sekvenční diagram spojuje pět kroků názorného příkladu dohromady, od nabídky až po notifikaci. Plné šipky jsou požadavky, přerušované šipky jsou odpovědi a tečkovaná šipka je transakční kód putující mimo protokol formou textové zprávy.

Peněženka

Firemní peněženka dopravní společnosti

Autorizační server

V tomto příkladu provozovaný samotným vydavatelem

Vydavatel pověření

Stanice technické kontroly vozidel

  1. Vydavatel pověření komu Peněženka: Credential Offer, zobrazená jako QR kód
  2. Vydavatel pověření komu Peněženka: tx_code, zaslaný SMS zprávou na telefon vedoucího vozového parku
  3. Peněženka komu Vydavatel pověření: GET /.well-known/openid-credential-issuer
  4. Vydavatel pověření komu Peněženka: metadata vydavatele pověření
  5. Peněženka komu Autorizační server: GET /.well-known/oauth-authorization-server
  6. Autorizační server komu Peněženka: metadata autorizačního serveru
  7. Peněženka komu Autorizační server: POST /token: pre-authorized_code, tx_code
  8. Autorizační server komu Peněženka: access_token
  9. Peněženka komu Vydavatel pověření: POST /nonce
  10. Vydavatel pověření komu Peněženka: c_nonce
  11. Peněženka: podepisuje proof JWT
  12. Peněženka komu Vydavatel pověření: POST /credential: přístupový token, důkazy
  13. Vydavatel pověření komu Peněženka: credentials, notification_id
  14. Peněženka: ověří a uloží
  15. Peněženka komu Vydavatel pověření: POST /notify: credential_accepted
  16. Vydavatel pověření komu Peněženka: 204 No Content

Když pověření ještě není připraveno: odložené vydání

Výše uvedený příklad předpokládá, že výsledek kontroly je již konečný. Pokud musí stanice technické kontroly místo toho eskalovat hraniční výsledek na staršího inspektora, endpoint pověření nemůže pověření vrátit hned, takže vydání odloží.

Okamžité vydání

Endpoint pověření vrátí podepsané pověření ve stejné odpovědi jako požadavek.

Odložené vydání

Endpoint pověření odpoví kódem HTTP 202, hodnotou transaction_id a intervalem místo pověření. Peněženka dotazuje deferred_credential_endpoint s tímto ID a čeká mezi požadavky alespoň tolik sekund, kolik udává interval, dokud pověření není připraveno.

transaction_iddotazování deferred_credential_endpoint

Odložená odpověď z /credential

HTTP/1.1 202 Accepted
Content-Type: application/json

{
  "transaction_id": "fi-tx-55c2",
  "interval": 900
}

Dotazování /deferred, dokud není připraveno

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.

Uzavření smyčky: notifikační endpoint

Po vydání může peněženka vydavateli sdělit, co se s pověřením stalo, pomocí notification_id z odpovědi na pověření. Peněženky nejsou povinny tyto notifikace odesílat a doručení není zaručeno, takže vydavatel nesmí chybějící notifikaci nijak interpretovat.

Peněženka

Odešle událost na notification_endpoint vydavatele pro přijaté notification_id, které pokrývá každé pověření v dané odpovědi

credential_accepted

Uloženo v peněžence

credential_failure

Vydání selhalo z jiného důvodu, například pověření neprošlo validací

credential_deleted

Vydání selhalo kvůli držiteli, například odmítl pověření uložit

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"
}

Související pojmy

Často kladené otázky

Jak peněženka pozná, jaký typ grantu má použít?

Credential Offer uvádí grant ve svém objektu grants. authorization_code je přítomen, pokud vydavatel chce, aby se držitel v rámci toku přihlásil. pre-authorized_code je přítomen, pokud byl držitel již ověřen na kanálu, kde nabídka vznikla, například inspektorem na místě kontroly v následujícím příkladu. Nabídka může uvádět oba a peněženka si pak jeden vybere. Pokud nabídka nemá objekt grants vůbec, peněženka vyhledá v metadatech, jaké typy grantů autorizační server podporuje.

Proč si peněženka stahuje metadata vydavatele dřív, než o cokoli požádá?

Credential Offer uvádí pouze credential_configuration_ids, URL adresu vydavatele a grants. Metadata vydavatele, poskytovaná na dobře známé cestě, popisují každou konfiguraci: její formát, tvrzení a přijímané typy důkazů, a také endpointy pro nonce, pověření, odložení a notifikace. Uvádí také, který autorizační server použít, a metadata tohoto serveru poskytují tokenový endpoint. Bez obojího by peněženka nevěděla, jak sestavit platné požadavky ani co ukázat držiteli před udělením souhlasu.

Co důkaz držení vlastně dokazuje?

Dokazuje, že peněženka žádající o pověření vlastní soukromý klíč, ke kterému bude pověření vázáno, nikoli pouze to, že má platný přístupový token. Peněženka podepíše proof JWT nad identifikátorem vydavatele a čerstvým c_nonce z nonce endpointu vydavatele pomocí tohoto klíče. Vydavatel vloží odpovídající veřejný klíč do pověření. Ověřovatel, který vyžaduje vázání na klíč, požádá držitele, aby při předložení znovu podepsal stejným klíčem, takže zkopírované pověření bez klíče touto kontrolou neprojde.

Proč by vydavatel odkládal vydání místo toho, aby pověření vrátil hned?

Některé kontroly, které vydavatel provádí před vytvořením pověření, se nemohou dokončit v rámci jediného HTTP požadavku, například ruční přezkum nebo dotaz na pomalý externí registr. Odložené vydání umožňuje endpointu pověření odpovědět okamžitě hodnotou transaction_id místo blokování spojení, a peněženka dotazuje odložený endpoint s tímto ID, dokud kontrola neskončí a pověření není připraveno k vyzvednutí.

Je notifikační endpoint pro vydavatele povinný k implementaci?

Ne. Pro vydavatele je volitelný a peněženky jej rovněž nemusí používat. Pokud jej podporují obě strany, vydavatel se dozví, co se stalo po vydání: pověření byla uložena (credential_accepted), držitel vydání zastavil, například odmítnutím jejich uložení (credential_deleted), nebo selhalo z jiného důvodu (credential_failure). Doručení není zaručeno, takže by vydavatel měl notifikaci považovat za užitečnou informaci, nikdy za spolehlivý záznam, a z chybějící notifikace nesmí nic vyvozovat.

Zdroje

  1. OpenID for Verifiable Credential Issuance 1.0
  2. OpenID4VC High Assurance Interoperability Profile 1.0
  3. EUDI Wallet Architecture and Reference Framework

Tato stránka má informativní charakter a nepředstavuje právní poradenství. Pro závazné poučení se obraťte přímo na OpenID Foundation a Evropskou komisi.

Promluvte si s námi o integraci EUDI Wallet