Credential offer
Overview
Once all the required workflow components are configured, you can initiate an OID4VCI workflow by creating a Credential offer.
This is achieved by making an API request to a specific MATTR VII endpoint. The request defines the credential configurations that will be used as well as additional request parameters to support the issuance workflow.
MATTR VII responds with an offer URI, which can be shared with intended holders as a QR code, deep-link or wallet notification. This enables the digital wallet to present the offer to the holder and request for consent to initiate the issuance workflow.
MATTR VII exposes two different endpoints to create a credential offer, depending on the authentication flow you are using:
- Authorization Code flow: The returned offer URI will be used by the wallet to redirect the holder to the configured Authentication provider for authentication. Once the holder is authenticated, they are redirected back to the issuance workflow.
- Pre-authorized Code flow: The returned offer URI already includes the pre-authorized code, which is used to authenticate the holder. This code is passed to the wallet and used to request an access token from the issuer’s token endpoint. The access token is then used to request the credential from the issuance endpoint.
The OID4VCI specification supports issuing multiple credentials in a single workflow, so you can reference multiple credential configurations in the same offer. When a multi-format credential offer is created, the generated URI offer is used to issue all the credential formats in a single workflow.
Claiming credential offers
When generating a credential offer, issuers can influence which wallet applications are able to claim the offer and how the user experience flows. This involves both user experience considerations and security, privacy, or commercial requirements where you want a specific app to claim the credential.
The mechanism for controlling this is through URI schemes. When a credential offer is generated (for either Authorization Code or Pre-authorized Code flows), the issuer applies a URI scheme that determines which apps can handle the offer and what that experience will be like.
Selecting a URI scheme for claiming the credential offer
There are several URI scheme options available, each with different trade-offs for user experience, security, and control:
Standard OpenID4VCI custom scheme
The OpenID4VCI specification proposes the use of a generic openid-credential-offer:// scheme as a
baseline, which means any app registered to handle this scheme could respond to the offer.
User experience:
- If you are interacting with the offer from an app that already recognizes this type of scheme, it can handle the offer immediately.
- If you are interacting with the offer outside of the holder app (such as tapping a link in a browser or scanning a QR code with the native camera), this will typically prompt the OS to present options of any app that is registered to handle that scheme (on Android), or sometimes it will automatically pick an app without enabling user selection (on iOS).
Considerations:
- This approach may not always open the app you want, or the OS may present other apps as options that you don't want users to see.
- Provides the most interoperability but the least control over which specific app handles the offer.
Private-use URI scheme (unique custom scheme)
The OAuth 2.0 for Native Apps specification
proposes using more unique custom schemes to make it clearer that the offer is intended for a
particular app. This uses reverse-domain schemes, such as com.example.app://.
User experience:
- Works in the same way as the standard OpenID4VCI custom scheme, but makes it less likely that another app would be registered to handle the same scheme due to the unique nature of reverse-domain schemes.
Considerations:
- This does not prevent another app from registering to also handle that same scheme.
- Not ideal if it is important to ensure only your app can handle the offer.
- Provides better targeting than the generic scheme but still allows potential conflicts.
Claimed HTTPS scheme (App Links / Universal Links)
Also called out in the OAuth 2.0 for Native Apps specification, the most secure way to ensure only your app can handle a request is to register a domain path to open your app via App Links on Android and Universal Links on iOS.
User experience:
- The offer URI uses an HTTPS URL pointing to your domain, which the operating system verifies is registered to only open your particular app.
- Provides the smoothest user experience as the OS can reliably open the correct app without presenting choices.
Considerations:
- Requires domain ownership and proper configuration of verification files on your web server.
- Provides the highest level of security and control over which app handles the offer.
- Recommended for production deployments where you need to ensure offers are only handled by your specific application.
More information can be found in the following resources:
Ensuring apps can handle the chosen URI scheme
Regardless of which URI scheme approach you choose, holder apps must be properly registered with the operating system to handle these schemes. See the following resources for platform-specific implementation guides:
- Apple Docs - Defining a Custom URL Scheme for Your App
- Android Docs - Create Deep Links to App Content
How to adjust the offer URI to use specific schemes
To use a custom URI scheme or App Link/Universal Link, you need to transform the generated offer URI returned by MATTR VII as a JSON object:
You will need to extract the uri element from this object and construct a new URI that is prefixed with your desired scheme, and embeds the information from the credential_offer parameter in a format that can be handled by your application.
Example: From the generated offer URI above, construct a new URI for your chosen scheme that passes the complete credential offer to an /accept route:
com.example.wallet://accept/{base64Url(openid-credential-offer://credential_offer=%7B%22credential_issuer...)}
Where:
com.example.wallet://is your app's custom URI scheme.acceptis a path defined by your app to handle the offer.{base64Url(...)}is the base64 URL-encoded version of the original credential offer (this encoding ensures that the entire offer URI can be safely included in the new URI without issues related to special characters).
For MATTR GO wallets using the app bundle ID, this might look like:
global.mattr.wallet://accept/b3BlbmlkLWNyZWRlbnRpYWwtb2ZmZXI6Ly8_Y3JlZGVudGlhbF9vZmZlcj0lN0IlMjJjcmVkZW50aWFsX2lzc3VlciUyMiUzQSUyMmh0dHBzJTNBJTJGJTJGdGVuYW50LnZpaS5tYXR0ci5nbG9iYWwlMjIlMkMlMjJjcmVkZW50aWFscyUyMiUzQSU1QiUyMjIwZDZiYmU2LWE5NzgtNDQ3Yy1iNWJkLWYzM2I2ZGNhMTllMiUyMiU1RCU3RA
The same transformation applies for a domain-verified HTTPS scheme:
https://example.com/wallet/accept?offer={base64Url(openid-credential-offer://...)}
Understanding the security implications
It's important to understand that using a specific URI scheme does not prevent other applications from claiming the offer entirely. A technically sophisticated user or malicious app could still extract the offer URI from the link embedded in a button or QR code and claim it with a different wallet application.
The URI scheme approach is primarily a user experience mechanism to:
- Make it easier to scan a QR code or follow a deep link and have the OS offer to open the link with the desired application.
- Reduce confusion by limiting which apps are presented as options to the user.
- For App Links/Universal Links, provide verified domain ownership to ensure your app is the default handler.
The only way to fully restrict which app can claim a credential offer is through the OID4VCI Authorization Code flow. This involves defining an allowed redirect URI that the user is redirected to after authentication. By specifying a redirect URI that only your app can handle, you can ensure that only your app can complete the issuance process. This configuration is done on the MATTR VII side when setting up your tenant. Please contact us if you need help with this setup.
Credential offer interaction options
After an issuer generates an offer (regardless of the scheme type), there are two common ways to present the offer to users. Sometimes UX and UI considerations mean offering both options, with a way to switch between each as a fallback.
Displayed as a hyperlink or button (same-device)
For situations where you expect the offer to be presented on the user's mobile device (where they would likely have the holder app installed), you can treat the offer as a hyperlink or button that will invoke your app to handle the offer.
Best practices:
- Make the button or link visually prominent and clearly labeled (e.g., "Add to Wallet", "Claim Credential").
- Consider providing a fallback QR code option for users who encounter issues with the direct link.
Displayed as a QR code (cross-device)
For situations where you expect the offer to be presented on a screen other than the user's mobile device (such as a desktop computer or even a printed leaflet), you can display a QR code that can be scanned by the user's device to pick up the offer.
Best practices:
- Ensure the QR code is large enough to be easily scanned (200px square is generally sufficient).
- Consider providing instructions or visual cues to guide users on how to scan the code with their wallet app.
- For users already on a mobile device, consider also displaying a button or link as an alternative to scanning.
How would you rate this page?