Η έκδοση διαπιστευτηρίων OpenID4VCI εξηγημένη: από την προσφορά έως το αποδεκτό διαπιστευτήριο
Το OpenID4VCI, δηλαδή OpenID for Verifiable Credential Issuance, ορίζει πώς ένα πορτοφόλι ζητά και λαμβάνει ένα διαπιστευτήριο από έναν εκδότη. Μια μεμονωμένη έκδοση διατρέχει πολλά ξεχωριστά βήματα πριν το πορτοφόλι κατέχει πράγματι ένα χρησιμοποιήσιμο διαπιστευτήριο, και καθένα έχει τον δικό του τρόπο αποτυχίας. Αυτή η σελίδα διατρέχει πλήρως αυτόν τον κύκλο ζωής, με πρωτότυπα λυμένα παραδείγματα.
Δύο τρόποι εκκίνησης: προεξουσιοδοτημένος κωδικός και κωδικός εξουσιοδότησης
Η έκδοση συχνά ξεκινά από μια Credential Offer που στέλνει ο εκδότης, και η χορήγηση που ονομάζει καθορίζει πώς εξουσιοδοτείται το πορτοφόλι. Ένα πορτοφόλι μπορεί επίσης να ξεκινήσει την έκδοση μόνο του, χωρίς καμία προσφορά, χρησιμοποιώντας τη ροή κωδικού εξουσιοδότησης. Και οι δύο ροές καταλήγουν στο ίδιο σημείο: το πορτοφόλι κατέχει ένα token πρόσβασης που μπορεί να χρησιμοποιήσει για να ζητήσει το διαπιστευτήριο.
Ροή προεξουσιοδοτημένου κωδικού
1. Εκδότης
Γνωρίζει ήδη τον κάτοχο, παραδίδει μια Credential Offer με έναν κωδικό pre-authorized_code
2. Πορτοφόλι
Εξαργυρώνει τον κωδικό στο token endpoint, προαιρετικά με κωδικό συναλλαγής
3. Πορτοφόλι
Ζητά το διαπιστευτήριο με απόδειξη κατοχής του κλειδιού του
Ροή κωδικού εξουσιοδότησης
1. Πορτοφόλι
Σαρώνει μια Credential Offer που ορίζει χορήγηση authorization_code, ή ξεκινά μόνο του τη διαδικασία χωρίς προσφορά
2. Διακομιστής εξουσιοδότησης
Οδηγεί τον κάτοχο μέσα από σύνδεση και συγκατάθεση, και μετά εκδίδει έναν κωδικό
3. Πορτοφόλι
Ανταλλάσσει τον κωδικό για ένα token και μετά ζητά το διαπιστευτήριο
Ο πλήρης κύκλος ζωής μιας προσφοράς διαπιστευτηρίου
Η προδιαγραφή δεν ορίζει ονομασμένες καταστάσεις, αλλά μια ροή που ξεκινά από τον εκδότη, όπου το διαπιστευτήριο εκδίδεται αμέσως, είναι ευκολότερο να ακολουθηθεί όπως στην παρακάτω σειρά. Κάθε βήμα μπορεί να αποτύχει με τον δικό του τρόπο, και μια υλοποίηση πορτοφολιού πρέπει να χειρίζεται αυτές τις διαδρομές, όχι μόνο την επιτυχημένη.
Λυμένο παράδειγμα: πιστοποιητικό καταλληλότητας κυκλοφορίας για στόλο μεταφορών
Ένας φορέας τεχνικού ελέγχου οχημάτων εκδίδει ένα πιστοποιητικό καταλληλότητας κυκλοφορίας στο επιχειρηματικό πορτοφόλι μιας εταιρείας μεταφορών μετά από έναν συνήθη έλεγχο. Ο επιθεωρητής έχει ήδη πιστοποιήσει τον διαχειριστή στόλου στο σημείο ελέγχου, οπότε ο εκδότης χρησιμοποιεί τη ροή προεξουσιοδοτημένου κωδικού. Τα παρακάτω βήματα ακολουθούν αυτή τη μεμονωμένη έκδοση από την προσφορά έως το αποδεκτό διαπιστευτήριο.
Το παράδειγμα δείχνει το βασικό OpenID4VCI. Οι υλοποιήσεις υψηλής διασφάλισης, όπως το EUDI Wallet, ακολουθούν πάνω σε αυτό το προφίλ HAIP, το οποίο προσθέτει tokens πρόσβασης δεσμευμένα με DPoP, βεβαίωση πορτοφολιού στο token endpoint και βεβαίωση κλειδιού για τα κλειδιά του διαπιστευτηρίου. Αυτά παραλείπονται εδώ ώστε κάθε βήμα να παραμένει ευανάγνωστο.
1. Προσφορά διαπιστευτηρίου
Το τερματικό του φορέα ελέγχου εμφανίζει έναν κωδικό QR. Περιέχει ένα URI που ξεκινά με openid-credential-offer:// και μεταφέρει την παρακάτω προσφορά, κωδικοποιημένη σε URL μέσα σε παράμετρο credential_offer, ή ένα credential_offer_uri από το οποίο το πορτοφόλι το ανακτά. Το πορτοφόλι το σαρώνει και διαβάζει ποιο διαπιστευτήριο προσφέρεται και πώς να το παραλάβει.
Εκδότης
Εμφανίζει κωδικό QR με μια Credential Offer
Ονομάζει τη διαμόρφωση διαπιστευτηρίου και μια χορήγηση 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. Ανακάλυψη μεταδεδομένων εκδότη
Πριν ζητήσει οτιδήποτε, το πορτοφόλι ανακτά τα μεταδεδομένα του εκδότη για να μάθει τι περιέχει το roadworthiness_certificate και ποια endpoints να καλέσει. Τα μεταδεδομένα δεν αναφέρουν ξεχωριστούς διακομιστές εξουσιοδότησης, οπότε ο εκδότης είναι ο ίδιος ο διακομιστής εξουσιοδότησής του, και το πορτοφόλι διαβάζει το token endpoint από τα μεταδεδομένα εκείνου του διακομιστή.
Πορτοφόλι
GET /.well-known/openid-credential-issuer
Μαθαίνει τη μορφή διαπιστευτηρίου, τους ισχυρισμούς και τους αποδεκτούς τύπους απόδειξης, καθώς και τα endpoints για nonce, διαπιστευτήριο, αναβολή και ειδοποίηση
Μεταδεδομένα εκδότη διαπιστευτηρίων (απόσπασμα)
{
"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"] }
]
}
}
}
}Μεταδεδομένα διακομιστή εξουσιοδότησης (απόσπασμα), από το /.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
Το πορτοφόλι εξαργυρώνει τον προεξουσιοδοτημένο κωδικό στο token endpoint, μαζί με τον κωδικό συναλλαγής που έστειλε ο φορέας ελέγχου στο κινητό του διαχειριστή στόλου. Η αποστολή αυτού του κωδικού μέσω δεύτερου καναλιού σημαίνει ότι κάποιος που φωτογραφίζει τον κωδικό QR πάνω από τον ώμο του κατόχου εξακολουθεί να μην μπορεί να τον εξαργυρώσει.
Πορτοφόλι
POST /token
Στέλνει το pre-authorized_code και το tx_code, λαμβάνει ένα token πρόσβασης περιορισμένο σε αυτή την προσφορά
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
Απόκριση
{
"access_token": "fi-at-3d91e0",
"token_type": "Bearer",
"expires_in": 86400
}4. Απόδειξη κατοχής
Επειδή τα μεταδεδομένα αναφέρουν ένα nonce_endpoint, το πορτοφόλι πρώτα ανακτά ένα φρέσκο c_nonce από εκεί. Στη συνέχεια αποδεικνύει ότι κατέχει το ιδιωτικό κλειδί στο οποίο θα δεσμευτεί το διαπιστευτήριο, υπογράφοντας ένα proof JWT πάνω στο αναγνωριστικό του εκδότη και αυτό το c_nonce.
Πορτοφόλι
POST /nonce, και μετά υπογράφει ένα proof JWT με το κλειδί στο οποίο θα δεσμευτεί το διαπιστευτήριο
Δεσμεύει το διαπιστευτήριο σε αυτό το κλειδί, όχι απλώς σε όποιον κατέχει το token πρόσβασης
POST /nonce HTTP/1.1 Host: issuer.fleetinspect.example
Απόκριση
{
"c_nonce": "fi-nonce-77aa"
}Το πορτοφόλι τώρα δημιουργεί το proof JWT από δύο αντικείμενα JSON, μια κεφαλίδα και ένα payload, και τα υπογράφει με το ιδιωτικό κλειδί στο οποίο θα δεσμευτεί το διαπιστευτήριο.
Κεφαλίδα: τι είναι αυτό το JWT και ποιο κλειδί το υπέγραψε
{
"typ": "openid4vci-proof+jwt",
"alg": "ES256",
"jwk": { "kty": "EC", "crv": "P-256", "x": "...", "y": "..." }
}typ: σημειώνει ότι αυτό είναι μια απόδειξη κλειδιού OpenID4VCI, ώστε να μην μπορεί να εκληφθεί ως κάποιο άλλο είδος JWTalg: ο αλγόριθμος υπογραφής, ένας από αυτούς που ανέφερε ο εκδότης στο proof_signing_alg_values_supportedjwk: το δημόσιο κλειδί στο οποίο θα δεσμευτεί το διαπιστευτήριο· ο εκδότης ελέγχει την υπογραφή σε σχέση με αυτό
Payload: για ποιον προορίζεται η απόδειξη και πότε δημιουργήθηκε
{
"aud": "https://issuer.fleetinspect.example",
"iat": 1789376400,
"nonce": "fi-nonce-77aa"
}aud: το αναγνωριστικό του εκδότη, ώστε η απόδειξη να μην μπορεί να επαναχρησιμοποιηθεί σε άλλον εκδότηiat: η στιγμή που δημιουργήθηκε η απόδειξη, σε δευτερόλεπτα από το 1970nonce: το c_nonce από το nonce endpoint, που δείχνει ότι η απόδειξη είναι φρέσκια
Το υπογεγραμμένο αποτέλεσμα
Η κεφαλίδα και το payload κωδικοποιούνται καθένα ξεχωριστά σε base64url και ενώνονται με μια τελεία. Το πορτοφόλι υπογράφει αυτή τη συμβολοσειρά με το ιδιωτικό του κλειδί και προσθέτει την κωδικοποιημένη σε base64url υπογραφή μετά από μια δεύτερη τελεία. Η προκύπτουσα συμβολοσειρά είναι το proof JWT που στέλνει το πορτοφόλι στο αίτημα διαπιστευτηρίου στο βήμα 5.
base64url(header) . base64url(payload) . base64url(signature) eyJ0eXAiOiJvcGVuaWQ0dmNpLXByb29mK2p3dCIs... .eyJhdWQiOiJodHRwczovL2lzc3Vlci5mbGVldGluc3BlY3QuZXhhbXBsZSIs... .<ES256 signature>
5. Αίτημα διαπιστευτηρίου
Το πορτοφόλι καλεί το endpoint διαπιστευτηρίων με το token πρόσβασης και την απόδειξη, και ο εκδότης εκδίδει και επιστρέφει το υπογεγραμμένο διαπιστευτήριο.
Πορτοφόλι
POST /credential
Στέλνει το token πρόσβασης, το αναγνωριστικό διαμόρφωσης και το proof JWT, λαμβάνει το υπογεγραμμένο διαπιστευτήριο και ένα 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>"]
}
}Απόκριση
{
"credentials": [
{ "credential": "<issuer-signed SD-JWT VC>" }
],
"notification_id": "fi-notif-9012"
}Ολόκληρη η ροή με μια ματιά
Αυτό το διάγραμμα ακολουθίας συγκεντρώνει τα πέντε βήματα του παραδείγματος, από την προσφορά έως την ειδοποίηση. Τα συνεχή βέλη είναι αιτήματα, τα διακεκομμένα βέλη είναι αποκρίσεις, και το διάστικτο βέλος είναι ο κωδικός συναλλαγής που ταξιδεύει εκτός πρωτοκόλλου με μήνυμα κειμένου.
Πορτοφόλι
Επιχειρηματικό πορτοφόλι εταιρείας μεταφορών
Διακομιστής εξουσιοδότησης
Λειτουργεί από τον ίδιο τον εκδότη σε αυτό το παράδειγμα
Εκδότης διαπιστευτηρίων
Φορέας τεχνικού ελέγχου οχημάτων
- Εκδότης διαπιστευτηρίων προς Πορτοφόλι: Credential Offer, εμφανιζόμενη ως κωδικός QR
- Εκδότης διαπιστευτηρίων προς Πορτοφόλι: tx_code, που στέλνεται στο κινητό του διαχειριστή στόλου με μήνυμα κειμένου
- Πορτοφόλι προς Εκδότης διαπιστευτηρίων: GET /.well-known/openid-credential-issuer
- Εκδότης διαπιστευτηρίων προς Πορτοφόλι: μεταδεδομένα εκδότη διαπιστευτηρίων
- Πορτοφόλι προς Διακομιστής εξουσιοδότησης: GET /.well-known/oauth-authorization-server
- Διακομιστής εξουσιοδότησης προς Πορτοφόλι: μεταδεδομένα διακομιστή εξουσιοδότησης
- Πορτοφόλι προς Διακομιστής εξουσιοδότησης: POST /token: pre-authorized_code, tx_code
- Διακομιστής εξουσιοδότησης προς Πορτοφόλι: access_token
- Πορτοφόλι προς Εκδότης διαπιστευτηρίων: POST /nonce
- Εκδότης διαπιστευτηρίων προς Πορτοφόλι: c_nonce
- Πορτοφόλι: υπογράφει το proof JWT
- Πορτοφόλι προς Εκδότης διαπιστευτηρίων: POST /credential: token πρόσβασης, αποδείξεις
- Εκδότης διαπιστευτηρίων προς Πορτοφόλι: credentials, notification_id
- Πορτοφόλι: επικυρώνει και αποθηκεύει
- Πορτοφόλι προς Εκδότης διαπιστευτηρίων: POST /notify: credential_accepted
- Εκδότης διαπιστευτηρίων προς Πορτοφόλι: 204 No Content
Όταν το διαπιστευτήριο δεν είναι ακόμα έτοιμο: αναβαλλόμενη έκδοση
Το παραπάνω παράδειγμα υποθέτει ότι το αποτέλεσμα του ελέγχου είναι ήδη οριστικό. Αν αντίθετα ο φορέας ελέγχου χρειάζεται να παραπέμψει ένα οριακό αποτέλεσμα σε ανώτερο επιθεωρητή, το endpoint διαπιστευτηρίων δεν μπορεί να επιστρέψει αμέσως το διαπιστευτήριο, οπότε αναβάλλει την έκδοση.
Άμεση έκδοση
Το endpoint διαπιστευτηρίων επιστρέφει το υπογεγραμμένο διαπιστευτήριο στην ίδια απόκριση με το αίτημα.
Αναβαλλόμενη έκδοση
Το endpoint διαπιστευτηρίων απαντά με HTTP 202, ένα transaction_id και ένα διάστημα. Το πορτοφόλι κάνει polling στο deferred credential endpoint με αυτό το id, περιμένοντας τουλάχιστον interval δευτερόλεπτα μεταξύ αιτημάτων, μέχρι το διαπιστευτήριο να είναι έτοιμο.
Αναβαλλόμενη απόκριση από το /credential
HTTP/1.1 202 Accepted
Content-Type: application/json
{
"transaction_id": "fi-tx-55c2",
"interval": 900
}Polling στο /deferred μέχρι να είναι έτοιμο
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.Κλείνοντας τον κύκλο: το endpoint ειδοποιήσεων
Μετά την έκδοση, το πορτοφόλι μπορεί να ενημερώσει τον εκδότη τι συνέβη με το διαπιστευτήριο, χρησιμοποιώντας το notification_id από την απόκριση διαπιστευτηρίου. Τα πορτοφόλια δεν υποχρεούνται να στέλνουν αυτές τις ειδοποιήσεις και η παράδοση δεν είναι εγγυημένη, οπότε ένας εκδότης δεν μπορεί να αποδώσει κανένα νόημα σε μια ειδοποίηση που λείπει.
Πορτοφόλι
Στέλνει ένα συμβάν στο notification_endpoint του εκδότη για το notification_id που έλαβε, το οποίο καλύπτει κάθε διαπιστευτήριο σε αυτή την απόκριση
Αποθηκεύτηκε στο πορτοφόλι
Η έκδοση απέτυχε για οποιονδήποτε άλλο λόγο, για παράδειγμα το διαπιστευτήριο δεν πέρασε την επικύρωση
Η έκδοση απέτυχε εξαιτίας του κατόχου, για παράδειγμα αρνήθηκε να το αποθηκεύσει
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"
}Σχετικοί όροι
Συχνές ερωτήσεις
Πώς ξέρει το πορτοφόλι ποιον τύπο χορήγησης να χρησιμοποιήσει;
Η Credential Offer ονομάζει τη χορήγηση στο αντικείμενο grants της. Το authorization_code υπάρχει όταν ο εκδότης θέλει ο κάτοχος να συνδεθεί ως μέρος της διαδικασίας. Το pre-authorized_code υπάρχει όταν ο κάτοχος έχει ήδη πιστοποιηθεί στο κανάλι όπου δημιουργήθηκε η προσφορά, για παράδειγμα από τον επιθεωρητή στο σημείο ελέγχου στο παρακάτω παράδειγμα. Μια προσφορά μπορεί να αναφέρει και τα δύο, και τότε το πορτοφόλι επιλέγει ένα. Αν η προσφορά δεν έχει καθόλου αντικείμενο grants, το πορτοφόλι εξετάζει ποιους τύπους χορήγησης υποστηρίζει ο διακομιστής εξουσιοδότησης στα μεταδεδομένα του.
Γιατί το πορτοφόλι ανακτά τα μεταδεδομένα του εκδότη πριν ζητήσει οτιδήποτε;
Η Credential Offer ονομάζει μόνο τα credential_configuration_ids, το URL του εκδότη και τα grants. Τα μεταδεδομένα του εκδότη, που εξυπηρετούνται από μια γνωστή διαδρομή, περιγράφουν κάθε διαμόρφωση: τη μορφή της, τους ισχυρισμούς της και τους τύπους απόδειξης που δέχεται, καθώς και τα endpoints για nonce, διαπιστευτήριο, αναβολή και ειδοποίηση. Αναφέρει επίσης ποιον διακομιστή εξουσιοδότησης να χρησιμοποιήσει, και τα μεταδεδομένα εκείνου του διακομιστή δίνουν το token endpoint. Χωρίς αυτά τα δύο, το πορτοφόλι δεν θα ήξερε πώς να δημιουργήσει έγκυρα αιτήματα ή τι να δείξει στον κάτοχο πριν συναινέσει.
Τι αποδεικνύει πραγματικά η απόδειξη κατοχής;
Αποδεικνύει ότι το πορτοφόλι που ζητά το διαπιστευτήριο κατέχει το ιδιωτικό κλειδί στο οποίο θα δεσμευτεί το διαπιστευτήριο, όχι απλώς ότι έχει έγκυρο token πρόσβασης. Το πορτοφόλι υπογράφει ένα proof JWT πάνω στο αναγνωριστικό του εκδότη και σε ένα φρέσκο c_nonce από το nonce endpoint του εκδότη, χρησιμοποιώντας αυτό το κλειδί. Ο εκδότης ενσωματώνει το αντίστοιχο δημόσιο κλειδί στο διαπιστευτήριο. Ένας επαληθευτής που απαιτεί δέσμευση κλειδιού ζητά από τον κάτοχο να υπογράψει ξανά με το ίδιο κλειδί κατά την παρουσίαση, οπότε ένα αντιγραμμένο διαπιστευτήριο χωρίς το κλειδί αποτυγχάνει σε αυτόν τον έλεγχο.
Γιατί ένας εκδότης θα ανέβαλλε την έκδοση αντί να επιστρέψει το διαπιστευτήριο αμέσως;
Ορισμένοι έλεγχοι που εκτελεί ο εκδότης πριν εκδώσει ένα διαπιστευτήριο δεν μπορούν να ολοκληρωθούν μέσα σε ένα μόνο αίτημα HTTP, για παράδειγμα μια χειροκίνητη επιθεώρηση ή μια κλήση σε ένα αργό εξωτερικό μητρώο. Η αναβαλλόμενη έκδοση επιτρέπει στο endpoint διαπιστευτηρίων να απαντήσει αμέσως με ένα transaction_id αντί να μπλοκάρει τη σύνδεση, και το πορτοφόλι κάνει polling στο αναβαλλόμενο endpoint με αυτό το id μέχρι να ολοκληρωθεί ο έλεγχος και το διαπιστευτήριο να είναι έτοιμο για παραλαβή.
Είναι υποχρεωτικό το endpoint ειδοποιήσεων για έναν εκδότη;
Όχι. Είναι προαιρετικό για τους εκδότες, και τα πορτοφόλια δεν υποχρεούνται να το χρησιμοποιούν επίσης. Όταν και οι δύο το υποστηρίζουν, ο εκδότης μαθαίνει τι συνέβη μετά την έκδοση: τα διαπιστευτήρια αποθηκεύτηκαν (credential_accepted), ο κάτοχος διέκοψε την έκδοση, για παράδειγμα αρνούμενος να τα αποθηκεύσει (credential_deleted), ή απέτυχε για άλλο λόγο (credential_failure). Η παράδοση δεν είναι εγγυημένη, οπότε ένας εκδότης πρέπει να αντιμετωπίζει μια ειδοποίηση ως χρήσιμη πληροφορία, ποτέ ως αξιόπιστο αρχείο, και δεν μπορεί να συμπεράνει τίποτα από την απουσία της.
Πηγές
Αυτή η σελίδα είναι ενημερωτική και δεν αποτελεί νομική συμβουλή. Για έγκυρη καθοδήγηση συμβουλευτείτε απευθείας το OpenID Foundation και την Ευρωπαϊκή Επιτροπή.