Issuer configuration
Updated the 11st of November 2024.
The wallets support most of the VC options of the OIDC4VCI standard for issuer configuration.
OIDC4VCI Specifications Drafts
OIDC4VCI has evolved rapidly between 2022 (Draft 10/11) and 2024 (Draft >= 13). The issuer metadata has changed multiple times. Right now wallets support Draft 10/11 and Draft 13 of the specifications. The selection of one Draft or another can be done manually in the wallet with the custom profile and the OIDCVC settings screen or through the wallet provider backend.
EBSI V3.x is based on OIDC4VCI Draft 10, DIIP V2.1, DIIP V3.0 and ARF use Draft 13.
Specifications of the different Drafts are available here:
- Draft 10 supported
- Draft 11 supported
- Draft 12 not supported
- Draft 13 supported
- Draft 14 soon supported
OIDC4VCI flow and features
Wallets support:
- VC format ldp_vc, jwt_vc, jwt_vc_json, jwt_vc_json-ld, vc+sd-jwt,
- VCDM 1.1,
- credential offer by value and by reference,
- pre authorized code (by default), authorized code flow, push authorization request, PKCE,
- Attestation based client authentication,
tx_code
withinput_mode
text
ornumeric
,lenght
anddescription
,authorization_details
andscope
. Tune with OIDCVC settings or wallet provider backend to usescope
.,- authorization server as a standalone server associated to one VC type,
- dynamic credential request,
- client secret post, client secret basic and public client authentication,
- bearer credential (no crypto binding),
- proof types as
jwt
orldp_vc
, - proof of possession header with
kid
orjwk
, - deferred endpoint,
- key identifiers as jwk thumbprint of DID,
- keys as EdDSA, P-256, seckp256k1,
Wallets do not support:
- notification endpoint,
- batch endpoint of Draft 13,
- DPoP for code and token,
- encrypted credentials,
- VCDM 2.0.
Limitations due to VC formats
JSON-LD VC
Wallets do not support remonte @context loading. Use embedded definition of json-ld attributes in the @contex
t array.
Example:
{
"@context": ["https://www.w3.org/2018/credentials/v1",
{
"EmailPass" : {
"@id": "https://github.com/TalaoDAO/context#emailpass",
"@context": {
"@version": 1.1,
"@protected": true,
"schema" : "https://schema.org/",
"id": "@id",
"type": "@type",
"email": "schema:email"
}
}
}
],
"id": "urn:uuid:123",
"type": [
"VerifiableCredential",
"EmailPass"
],
"issuer": "did:web:talao.co",
"issuanceDate": "2024-03-27T15:42:10Z",
"credentialSubject" : {
"id": "did:key:zDnaeY6i6uVda46Vm8whCFQJPzTYBeZnkHvPCaBLfZoVYwqEP",
"type" : "EmailPass",
"email" : "john.doe@gmail.com"
},
"proof": {
"type": "Ed25519Signature2018",
"proofPurpose": "assertionMethod",
"verificationMethod": "did:key:z6MkftN6LL5DRTG8u5LjhQuwUconSp3wremHoMjcH1LP7Hxd#z6MkftN6LL5DRTG8u5LjhQuwUconSp3wremHoMjcH1LP7Hxd",
"created": "2024-03-27T14:42:10.447Z",
"jws": "eyJhbGciOiJFZERTQSIsImNyaXQiOlsiYjY0Il0sImI2NCI6ZmFsc2V9..uEc2nusfEihJKUY6Owulwrm0tQccazRt3mDI_5RKXWSFc9ZYOoTJ5hAUI7BZE1vH9S62J8NBIXEkIkz4kcMdCw"
},
}
Invocation schemes for issuance
Wallet support different invocation schemes:
- openid-credential-offer://,
- haip://,
- https://app.altme.io/app/download/oidc4vc,
- https://app.talao.co/app/download/oidc4vc
Those schemes can be displayed as QR code for wallet app scanner, smartphone camera or as a deeplink / universal link (a button in a html page for the smartphone browser).
Support of Universal Links and App Links
For security reasons Talao wallets use Universal Links and App Links to redirect to wallet authorization endpoints and callback endpoints. However those links are not supported by default by all browsers. We suggest to use Safari for IOS phones and Chrome for Android. You may need to setup browser options manually to allow Universal links or App Links with Firefox, Brave, Samsung explorer or even Chrome on IOS.
Dynamic Credential Request
Dynamic Credential Request is an option to operate a VP presentation for user authentication inside an authorization code flow.
The main difference between this process and the use of a VP authentication step (OIDC4VP) followed by the issuance of a VC by pre authorized code flow (OIDC4VCI) is that the VP(s) requested by the verifier for user authentication maybe adapted dynamically to the user identity and the VC requested,
In order to manage that combination wallet must provide its own authorization endpoint to the issuer. Our wallets support the client_metadata
attribute when OIDC4VCI Draft is below or equal to 11 and the wallet_issuer
attribute for more recent Draft, both added to the authorization request and push authorization request.
Example of client_metadata:
{
"authorization_endpoint":"https://app.altme.io/app/download/authorize",
"scopes_supported":[
"openid"
],
"response_types_supported":[
"vp_token","id_token"
],
"client_id_schemes_supported":[
"redirect_uri","did"
],
"grant_types_supported":......
}
Here is a script of the issuance of a VC in using another VC as a mean of authentication:
- Wallet makes an authorization request to the AS of the issuer through a QRcode or a deeplink. The
client_metadata
attribute (or wallet_issuer attribute) is added to the request aside the standardredirect_uri
endpoint of the wallet. For this step the wallet opens a browser session and redirects the user agent to the AS authorization endpoint. - To process the authentication step, the issuer fetches the wallet authorization endpoint from the
client_metadata
and prepares a VP request with its ownreponse_uri
endpoint like a verifier. The VP request is sent as a redirect to the wallet authorization endpoint. For implementation issuer can add thestate
attribute to the VP request to link the request to the original wallet request. - Wallet selects the VP requested and transfers is through a POST to the
response_uri
endpoint provided in the VP request. The state is added to thevp_token
andpresentation_submission
. - Issuer acting as a verifier validates the VP data needed to prepare the VC and redirects the user agent to the
redirect_uri
endpoint of the wallet with thecode
. For implementation thestate
can be associated to thecode
. - Wallet requests an
access_token
in exchange of thecode
. For implementation thecode
can be associated to theaccess_token
. - Wallet requests the credential with the access token.
In case of the use of the wallet_issuer
attribute, issuer must discover the wallet authorization endpoint through the standard /.well-known/openid-configuration
endpoint:
- Talao: https://app.talao.co/wallet-issuer/.well-known/openid-configuration
- Altme: https://app.altme.io/wallet-issuer/.well-known/openid-configuration
Learn more about Dynamic Credential Request.
Wallet rendering - display credentials
Attributes of a VC
Wallet support all the attributes of the display.
"credential_configurations_supported": {
"IBANLegalPerson": {
"scope": "IBANLegalPerson_scope",
"display": [
{
"name": "Company IBAN",
"description": "IBAN",
"text_color": "#FBFBFB",
"text_color": "#FFFFFF",
"logo": {
"uri": "https://i.ibb.co/ZdVm5Bg/abn-logo.png",
"alt_text": "ABN Amro logo"
},
"background_image": {
"uri": "https://i.ibb.co/kcb9XQ4/abncard-iban-lp.png",
"alt_text": "ABN Amro Card"
}
}
],
......
}
}
The uri
can be either a link or a data uri scheme. text_color
and background_color
are fallbacks options if links are not provided.
name
is used as the VC name if there is no background image.
If display
is not provided wallets use a fallback blue card with white text color.
Attributes of a claim
Wallets show only but all claims that are in the issuer metadata, rules are:
- if there is a
display
attribute in the claim, wallet displays the label in bold with the claim value on the same line. Otherwise wallet displays the claim value alone, - if the claim is a json object (nested claims) without
display
-> it goes to the line and indent, - if the claim is a json object with a
display
-> it displays the label in bold and goes to the line and indent.
With this issuer metadata:
"claims": {
"given_name": {
"display": [
{
"name": "Given Name",
"locale": "en-US"
}
]
},
"family_name": {
"display": [
{
"name": "Surname",
"locale": "en-US"
}
]
},
"email": {},
"phone_number": {},
"address": {
"street_address": {},
"locality": {},
"region": {},
"country": {}
},
"birthdate": {},
"is_over_18": {},
"is_over_21": {},
"is_over_65": {}
}
wallets rendering will be:
Given name: John
Surname: DOE
john.doe@gmail.com
+33678876876
13 rue de Paris
Paris
Paris
France
12/09/1990
True
True
False
Wallets support all attributes of the display :
"claims": {
"given_name": {
"value_type": "string",
"display": [
{
"name": "First Name",
"locale": "en-US"
},
value_type
supported are:
string
,integer
,bool
,email
,uri
,image/jpeg
,image/png
email
and uri
are active as you can launch the browser or open the smartphone email manager with a clic.
order
is supported
mandatory
in not supported.
Locale
Locale language is chosen depending on the smartphone language. If the smartphone language translation is not provided with the claim, wallet will use locale. If locale is not provided in the issuer metadata, wallet will use english.
"issuing_country": {
"mandatory": true,
"value_type": "string",
"display": [
{
"name": "Issuing country",
},
{
"name": "Issuing country",
"locale": "en-US"
},
{
"name": "Pays d'emission",
"locale": "fr-FR"
}
]
}
Images
Use the value_type image/jpeg
or image/png
Image can be provided as value (data:uri) or reference https://...
"picture": {
"mandatory": True,
"value_type": "image/jpeg",
"display": [
{
"name": "Picture",
"locale": "en-US"
},
{
"name": "Portrait",
"locale": "fr-FR"}],
},
Type metadata of SD-JWT VC
Wallet does not support the type metadata of the sd-jwt VC IETF standard.
VC Status list support
Wallets support the following specifications depending on the VC format:
- ldp_vc, jwt_vc, jwt_vc_json, jwt_vc_json-l : Bitstring Status List V1.0
- sd-jwt-vc : Token Status List
When the VC is received from the issuer or displayed, the wallet verifies the signature of the VC, the signature of the status list and the status of the VC. If any of these checked fails teh wallet display a red card status. These verification steps can by passed with an option in the wallet provider backed through a security low profile.
Waltid issuer integration
All issuer.{..}
, expirationDate
, issuanceDate
and credentialSubject.id
claims must be removed from the credential data as they are already provided in the json_jwt_vc as iss
, sub
, iat
. Here is a correct configuration needed to make the waltid example running :
{
"issuerKey": {
"type": "jwk",
"jwk": {
"kty": "EC",
"d": "uTIT47GfSlRa0Da4CsyoIZpjjwQLFxmL2qmBuzZpEy0",
"crv": "P-256",
"kid": "FsHUZY4_tDJDvxdp5B6moS1kwpP7PBekw4KfK7m0LCU",
"x": "keR9l4u1SaZKMZ7wHvj_3z44vP0sa3nlzrnc8UjpQV0",
"y": "pmcaedg5dtc2R6ZPZfWCBY56_M_5fUZgsz4LWD0mG8U"
}
},
"credentialConfigurationId": "UniversityDegree_jwt_vc_json",
"credentialData":{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"type": [
"VerifiableCredential",
"UniversityDegreeCredential"
],
"credentialSubject": {
"degree":{
"type": "BachelorDegree",
"name": "Bachelor of Science and Arts"
}
}
},
"authenticationMethod": "PRE_AUTHORIZED",
"issuerDid": "did:jwk:eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiRnNIVVpZNF90REpEdnhkcDVCNm1vUzFrd3BQN1BCZWt3NEtmSzdtMExDVSIsIngiOiJrZVI5bDR1MVNhWktNWjd3SHZqXzN6NDR2UDBzYTNubHpybmM4VWpwUVYwIiwieSI6InBtY2FlZGc1ZHRjMlI2WlBaZldDQlk1Nl9NXzVmVVpnc3o0TFdEMG1HOFUifQ"
}
Authlete issuer integration
This is the configuration needed to run the Authlete OIDC4VCI Demo in pre authorized code flow with a sd-jwt VC.
The specific topics here are the client_id value to get the access token and the general use of jwk/cnf.
You will need to have an access to the wallet provider backend to setup a custom profile and update the OIDC4VC options as follow:
- Go to the
SSI Data
page - SSI profile (4.1) choose
custom profile
- Key Identifier (4.5) choose
jwk thumbprint with P-256
- Client type (4.6) choose
confidential or other
- Client Authentication Method (4.9) choose
client id
and enter the example value218232426
- OIDC4VCI Draft (4.10) select
Draft 13
- VC Format (4.13) choose
vc+sd-jwt
- Proof Type (4.14) select
jwt
- Proof of Possession Header (4.15) select
jwk
- Do not forget to save the configuration (bottom setup button)
- Download the configuration to the wallet by scan or update it from the wallet if you already use it.
Go to the issuer URL, select the Pre Authorised Code Grant in the form, if needed you can add transaction code data. Submit the issuer form, scan the QR code, choose the IndentityCredential proposed in the wallet, follow the process and consent.
Use the developer mode to display the VC decoded inside the wallet or download it and use this tool to decode it with all disclosures.
{
"kid": "J1FwJP87C6-QN_WSIOmJAQc6n5CQ_bZdaFJ5GDnW1Rk",
"typ": "vc+sd-jwt",
"alg": "ES256"
}
{
"_sd": [
"04le4bFu5-mavLr_ZiPP6cLyet2AoAEKN5SzbukwWi0",
"1VmLs3WfKoHcQb-MlrRWx0kKkC8lmpL164jeRV9aGOA",
"Mg5UREMN3elGQbOvcG9Mh6CaSTHyDgcMnzMLF21EEJw",
"Wx9xvfgee4AQ4a0fbWCwGyxr3LB7g1mQQx0Oq4hy8A4",
"eDlVzAalQrQavjMbSvGcppFhuFCuvZSy1RHliRy1xKs",
"jt0qxHtMYfLXYYm7rySaKXpBP1SMJk3vX0-FgFE-Oqk",
"k_r1tAt6TsnoqsNyrGOtyykCAFFD5pQCSNTuqFG9Xeg",
"lqre2R2Xrj8FEyTX_yauPS4KRUb5a4BZt9cIXwVmzqs",
"wrsr2ZuNmcy3-3l4-8pjQHMx7sq-sxbL0sVOiBT1tvY",
"xDRY5VC6STHnuAuHHc2j1pgX4pBKfX69yJEh1WpItl8"
],
"vct": "https://credentials.example.com/identity_credential",
"_sd_alg": "sha-256",
"iss": "https://trial.authlete.net",
"cnf": {
"jwk": {
"kty": "EC",
"use": "sig",
"crv": "P-256",
"kid": "okKqec7q60xoZwwePMiEGaAXwvLCt-WqMaX2V3L1Lr4",
"x": "ptUUeO8I9lazDDBWKPTV-WZGedtQTt2gln2t0wKDjV8",
"y": "YklhBu0YC2p7OUKy2ZYSqzCcDvXVtH_qBMwGBf6NmTY",
"alg": "ES256"
}
},
"iat": 1730468137
}
Full issuance flow example
This example is based on the flow of this issuer.
Below the URL encoded credential offer which is read as a QR code by the wallet:
openid-credential-offer://?credential_offer_uri=https://talao.co/issuer/credential_offer_uri/ca0f1c7e-9426-11ef-b6e7-0a1628958560
First the wallet calls the credential_offer_uri endpoint:
GET /issuer/credential_offer_uri/ca0f1c7e-9426-11ef-b6e7-0a1628958560
Host: talao.co
The issuer responds with the credential offer which looks like this:
{
"credential_offer": {
"credential_issuer": "https://talao.co/issuer/sobosgdtgd",
"credential_configuration_ids": [
"InsuranceNaturalPerson"
],
"grants": {
"urn:ietf:params:oauth:grant-type:pre-authorized_code": {
"pre-authorized_code": "dfc8ee59-9430-11ef-9e55-0a1628958560"
}
}
}
}
Then the wallet calls the issuer metadata endpoint:
GET /issuer/sobosgdtgd/.well-known/openid-credential-issuer
Host: talao.co
The issuer responds with the issuer matadata which looks like this:
{
"credential_issuer": "https://talao.co/issuer/sobosgdtgd",
"pre-authorized_grant_anonymous_access_supported": true,
"display": [
{
"name": "Talao issuer",
"locale": "en-US",
"logo": {
"uri": "https://talao.co/static/img/talao.png",
"alt_text": "Talao logo"
}
},
{
"name": "Talao issuer",
"locale": "fr-FR",
"logo": {
"uri": "https://talao.co/static/img/talao.png",
"alt_text": "Talao logo"
}
}
],
"credential_endpoint": "https://talao.co/issuer/sobosgdtgd/credential",
"deferred_credential_endpoint": "https://talao.co/issuer/sobosgdtgd/deferred",
"scopes_supported": [
"openid"
],
"response_types_supported": [
"vp_token",
"id_token"
],
"response_modes_supported": [
"query"
],
"grant_types_supported": [
"authorization_code",
"urn:ietf:params:oauth:grant-type:pre-authorized_code"
],
"subject_types_supported": [
"public",
"pairwise"
],
"id_token_signing_alg_values_supported": [
"ES256",
"ES256K",
"EdDSA",
"RS256"
],
"request_object_signing_alg_values_supported": [
"ES256",
"ES256K",
"EdDSA",
"RS256"
],
"request_parameter_supported": true,
"request_uri_parameter_supported": true,
"token_endpoint_auth_methods_supported": [
"client_secret_basic",
"client_secret_post",
"client_secret_jwt",
"none"
],
"request_authentication_methods_supported": {
"authorization_endpoint": [
"request_object"
]
},
"subject_syntax_types_supported": [
"urn:ietf:params:oauth:jwk-thumbprint",
"did:key",
"did:ebsi",
"did:pkh",
"did:ethr",
"did:web",
"did:jwk"
],
"subject_syntax_types_discriminations": [
"did:key:jwk_jcs-pub",
"did:ebsi:v1"
],
"subject_trust_frameworks_supported": [
"ebsi"
],
"id_token_types_supported": [
"subject_signed_id_token"
],
"authorization_endpoint": "https://talao.co/issuer/sobosgdtgd/authorize",
"token_endpoint": "https://talao.co/issuer/sobosgdtgd/token",
"jwks_uri": "https://talao.co/issuer/sobosgdtgd/jwks",
"pushed_authorization_request_endpoint": "https://talao.co/issuer/sobosgdtgd/authorize/par",
"credential_configurations_supported": {
"InsuranceNaturalPerson": {
"scope": "InsuranceNaturalPerson_scope",
"display": [
{
"locale": "en-US",
"name": "Issurance attestation",
"description": "Insurance for liability risks",
"background_color": "#3B6F6D",
"text_color": "#FFFFFF",
"logo": {
"uri": "https://dutchblockchaincoalition.org/assets/images/icons/Logo-DBC.png",
"alt_text": "AXA International."
},
"background_image": {
"uri": "https://i.ibb.co/CHqjxrJ/dbc-card-hig-res.png",
"alt_text": "AXA International"
}
}
],
"id": "InsuranceNaturalPerson",
"credential_definition": {
"type": [
"VerifiableCredential",
"InsuranceNaturalPerson"
],
"credentialSubject": {
"insurerName": {
"display": [
{
"name": "Insurer name",
"locale": "en-US"
}
]
},
"leiCodeInsurer": {
"display": [
{
"name": "LEI code",
"locale": "en-US"
}
]
},
"contractId": {
"display": [
{
"name": "Contract Identifier",
"locale": "en-US"
}
]
},
"insuredPerson": {}
}
},
"format": "jwt_vc_json",
"cryptographic_binding_methods_supported": [
"did:jwk",
"did:key"
],
"proof_types_supported": {
"jwt": {
"proof_signing_alg_values_supported": [
"ES256"
]
}
},
"credential_signing_alg_values_supported": [
"ES256"
]
}
}
}
Then wallet calls the token endpoint with the pre authorized code and a client_id (optional):
POST /issuer/sobosgdtgd/token HTTP/1.0
Host: talao.co
Content-Type: application/x-www-form-urlencoded
Content-Length: 321
grant_type=urn:ietf:params:oauth:grant-type:pre-authorized_code
&pre-authorized_code=dfc8ee59-9430-11ef-9e55-0a1628958560
&client_id=did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6IkthY0xyeG1OMXhNNGlrZWY2bHJRM1F5d25PVEdrR05xV3hhM2Rsc1pReDgiLCJ5IjoiYXZWZWgzY3Z5SVl1Q0NUVDF5YnZKeFoyeXNvQ2FuaDFOOE9nTzFBT1M3WSJ9
The issuer responds with an access token and a c_nonce (optional):
{
"access_token": "4fed3ac3-9431-11ef-b492-0a1628958560",
"c_nonce": "4fed3cc1-9431-11ef-beed-0a1628958560",
"token_type": "bearer",
"expires_in": 10000,
"c_nonce_expires_in": 1704466725,
"refresh_token": "4fed3c24-9431-11ef-b9f1-0a1628958560"
}
Then the wallet calls the credential endpoint with the format and type of the credential and a proof of key ownership as a jwt:
POST /issuer/sobosgdtgd/credential HTTP/1.0
Host: talao.co
Authorization: Bearer 4fed3ac3-9431-11ef-b492-0a1628958560
Content-Type: application/json
Content-Length: 932
{
"format": "jwt_vc_json",
"credential_definition": {
"type": [
"VerifiableCredential",
"InsuranceNaturalPerson"
]
},
"proof": {
"proof_type": "jwt",
"jwt": "eyJhbGciOiJFUzI1NiIsInR5cCI6Im9wZW5pZDR2Y2ktcHJvb2Yrand0Iiwia2lkIjoiZGlkOmp3azpleUpqY25ZaU9pSlFMVEkxTmlJc0ltdDBlU0k2SWtWRElpd2llQ0k2SWt0aFkweHllRzFPTVhoTk5HbHJaV1kyYkhKUk0xRjVkMjVQVkVkclIwNXhWM2hoTTJSc2MxcFJlRGdpTENKNUlqb2lZWFpXWldnelkzWjVTVmwxUTBOVVZERjVZblpLZUZveWVYTnZRMkZ1YURGT09FOW5UekZCVDFNM1dTSjkjMCJ9.eyJpc3MiOiJkaWQ6andrOmV5SmpjbllpT2lKUUxUSTFOaUlzSW10MGVTSTZJa1ZESWl3aWVDSTZJa3RoWTB4eWVHMU9NWGhOTkdsclpXWTJiSEpSTTFGNWQyNVBWRWRyUjA1eFYzaGhNMlJzYzFwUmVEZ2lMQ0o1SWpvaVlYWldaV2d6WTNaNVNWbDFRME5VVkRGNVluWktlRm95ZVhOdlEyRnVhREZPT0U5blR6RkJUMU0zV1NKOSIsImlhdCI6MTczMDAxMjQ3MCwiYXVkIjoiaHR0cHM6Ly90YWxhby5jby9pc3N1ZXIvc29ib3NnZHRnZCIsIm5vbmNlIjoiNGZlZDNjYzEtOTQzMS0xMWVmLWJlZWQtMGExNjI4OTU4NTYwIn0.2rQCQ8PJy5bu8wVUJ76C_qVXcdrj5ajyUFNwk3agvMbPMH40B8fu0Oq5dMiz7h2YGPgjI87wQBjFHToEhaN-5w"
}
}
The issuer responds with the credential:
{
"credential": "eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDp3ZWI6YXBwLmFsdG1lLmlvOmlzc3VlciNrZXktMSIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NjE1NDg1MDAsImlhdCI6MTczMDAxMjUwMCwiaXNzIjoiZGlkOndlYjphcHAuYWx0bWUuaW86aXNzdWVyIiwianRpIjoidXJuOnV1aWQ6NTBjZmJmMzEtOTQzMS0xMWVmLTg1ZDUtMGExNjI4OTU4NTYwIiwibmJmIjoxNzMwMDEyNTAwLCJub25jZSI6IjRmZWQzY2MxLTk0MzEtMTFlZi1iZWVkLTBhMTYyODk1ODU2MCIsInN1YiI6ImRpZDpqd2s6ZXlKamNuWWlPaUpRTFRJMU5pSXNJbXQwZVNJNklrVkRJaXdpZUNJNklrdGhZMHh5ZUcxT01YaE5OR2xyWldZMmJISlJNMUY1ZDI1UFZFZHJSMDV4VjNoaE0yUnNjMXBSZURnaUxDSjVJam9pWVhaV1pXZ3pZM1o1U1ZsMVEwTlVWREY1WW5aS2VGb3llWE52UTJGdWFERk9PRTluVHpGQlQxTTNXU0o5IiwidmMiOnsiY3JlZGVudGlhbFN0YXR1cyI6W3siaWQiOiJodHRwczovL3RhbGFvLmNvL3NhbmRib3gvaXNzdWVyL2JpdHN0cmluZ3N0YXR1c2xpc3QvMSM2NTU1MiIsInN0YXR1c0xpc3RDcmVkZW50aWFsIjoiaHR0cHM6Ly90YWxhby5jby9zYW5kYm94L2lzc3Vlci9iaXRzdHJpbmdzdGF0dXNsaXN0LzEiLCJzdGF0dXNMaXN0SW5kZXgiOiI2NTU1MiIsInN0YXR1c1B1cnBvc2UiOiJyZXZvY2F0aW9uIiwidHlwZSI6IkJpdHN0cmluZ1N0YXR1c0xpc3RFbnRyeSJ9XSwiY3JlZGVudGlhbFN1YmplY3QiOnsiY29udHJhY3QiOnsiY29udHJhY3RBbW91bnQiOjEwMDAwMDAwLCJjb250cmFjdFR5cGUiOiJMaWFiaWxpdHkgcmlza3MiLCJjdXJyZW5jeSI6IkVVUiJ9LCJjb250cmFjdElkIjoiODk3ODk3NjUgOTc2OTY1IiwiaWQiOiIiLCJpbnN1cmVkUGVyc29uIjp7ImJpcnRoZGF0ZSI6IjIwMDAtMTItMDEiLCJmYW1pbHlfbmFtZSI6IkRvZSIsImdpdmVuX25hbWUiOiJKb2huIn0sImluc3VyZXJOYW1lIjoiQVhBIEludGVybmF0aW9uYWwiLCJsZWlDb2RlSW5zdXJlciI6IjAyMDk5ODc2RlI3NSJ9LCJleHBpcmF0aW9uRGF0ZSI6IjIwMjUtMTAtMjdUMDY6NTg6MzBaIiwiaWQiOiJ1cm46dXVpZDo0ZDQ3YTZiYS01MWNkLTQxZWYtOWJhYi1mYzQ5NjNiNWFmZjMiLCJpc3N1YW5jZURhdGUiOiIyMDI0LTEwLTI3VDA2OjU4OjMwWiIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJJbnN1cmFuY2VOYXR1cmFsUGVyc29uIl19fQ.1DI8Fwe-uWXF3FyxksgNVb453XylOBL8CeQuf-sPI0_Soo_MXHYmwGsKiS6m-rOVCNu4DihclrtIG4NElWbnAg"
}
The wallet stores the credential with the issuer metadata for correct rendering.