You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Lets first quickly summarize what the spec says about Credential Offers.
The basic assumption is, that the Issuer creates a Credential Offer and then passes it to the Wallet. This can be done
by credential_offer_uri, by qr-code (for cross device flows), by a Wallet provided credential_offer_endpoint
or by some other means (e.g. email, messaging, etc.).
The spec does not detail how to request a Credential Offer from an Issuer. In Keycloak, we provide an /create-credential-offer endpoint that requires various access privileges depending on the offer that is to be created. Other means to create a Credential Offer may exist in the Admin Console.
Depending on Credential Offer Policies for a given credential_configuration_id and Issuing User, these required
privileges may be permissible enough to allow for a "self-issued" Credential Offer.
A Credential Offer contains a set of credential_configuration_ids, which the Wallet can use to request a Credential as defined in the Issuer metadata
Credential Offers come in two variants
authorization_code grant
pre-authorized_code grant
Authorization Code Grant
With the authorization_code grant, the Wallet can send an Authorization Request that references one of the credential_configuration_ids in authorization_details. Part of the authorization_code grant
is also some opaque issuer_state that the Wallet must include in the Authorization Request. This allows the
Issuer to correlate the Authorization Request with a previously made Credential Offer.
The Wallet may also send an Authorization Request with a scope parameter and no authorization_details
nor issuer_state. This by-passes the Credential Offer process completely - the Authorization Server may
still return an Authorization Code, which can then be used in an AccessToken request and ultimately grants access
to Credentials associated with that scope.
Whether the Authorization Server grants access or the Credential Endpoint actually returns the wanted Credential again
depends on the effective Credential Policies. These may require an existing Credential Offer for a given credential_configuration_id and hence prevent such a Credential Request on scope alone.
Pre-Authorized Code Grant
As the name suggests, this is a "pre-authorized" grant that the Wallet can use directly in an AccessToken Request. No
further authorization is required on part of the Wallet. It works for cases where the Wallet cannot be expected to use
an authorization_code grant. Since this is bearer grant that gives direct access to the Credentials referenced
by credential_configuration_ids, the party that creates such a Credential Offer must take upmost care about
how to communicate that "pre-authorized" grant. As a second authorization factor, the Issuer can create a tx_code
together with the Credential Offer. The tx_code is to be communicated via an alternative channel (i.e. not together with the pre-authorized code).
As noted above, we have a /create-credential-offer as the primary entry point to initiate Credential Offer creation. This endpoint now delegates to the new CredentialOfferProvider to the actual creation of the internal CredentialOfferState. This an immutable instance that represents the CredentialOffer. It also holds the authorization_details that become part of the AccessToken response and the AccessToken JWT.
Using CredentialOfferProvider as the single access point for CredentialOfferState is important. It can reason about whether an Issuing User actually has the required privileges to make the required offer.
Currently we enforce these general rules ...
The Issuing User must have an active login session
The referenced credential_configuration_id must exist
The potential targetUser must exist and be enabled
If the targetUser is given, the Issuing User must hold the credential_offer_create role
... these rules for authorization_code grant
If the targetUser is not given - it is an "Anonymous" offer not bound to a specific target user
... and these rules for pre-authorized_code grant
If the targetUser is not given - it is a self-issued credential offer
Additionally, we now support theses Credential Policies ...
Name
Expected
Default
Note
vc.policy.offer.required
true
false
Governs whether the given credential_configuration_id requires a Credential Offer
vc.policy.offer.pre-auth.allowed
true
true
Governs whether Credential Offers with pre-authorized_code grant are allowed
vc.policy.offer.tx-code.required
true
false
Governs Credential Offers with pre-authorized_code grant require a tx_code
These policies an be set as Client Scope Attribute values.
In future may want to integrate fine grained role access to also cover the joe can offer foo to alice case. For now however, these three Credential Policies should be sufficient to deliver a "minimal viable product" (i.e. for oid4vci preview).
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
In this discussion, I introduce a new CredentialOfferProvider and how it enforces CredentialPolicies
Issue: #46262
Related: #46396 #46200
Lets first quickly summarize what the spec says about Credential Offers.
The basic assumption is, that the Issuer creates a Credential Offer and then passes it to the Wallet. This can be done
by
credential_offer_uri, by qr-code (for cross device flows), by a Wallet providedcredential_offer_endpointor by some other means (e.g. email, messaging, etc.).
The spec does not detail how to request a Credential Offer from an Issuer. In Keycloak, we provide an
/create-credential-offerendpoint that requires various access privileges depending on the offer that is to be created. Other means to create a Credential Offer may exist in the Admin Console.Depending on Credential Offer Policies for a given
credential_configuration_idand Issuing User, these requiredprivileges may be permissible enough to allow for a "self-issued" Credential Offer.
A Credential Offer contains a set of
credential_configuration_ids, which the Wallet can use to request a Credential as defined in the Issuer metadataCredential Offers come in two variants
authorization_codegrantpre-authorized_codegrantAuthorization Code Grant
With the
authorization_codegrant, the Wallet can send an Authorization Request that references one of thecredential_configuration_idsinauthorization_details. Part of theauthorization_codegrantis also some opaque
issuer_statethat the Wallet must include in the Authorization Request. This allows theIssuer to correlate the Authorization Request with a previously made Credential Offer.
The Wallet may also send an Authorization Request with a
scopeparameter and noauthorization_detailsnor
issuer_state. This by-passes the Credential Offer process completely - the Authorization Server maystill return an Authorization Code, which can then be used in an AccessToken request and ultimately grants access
to Credentials associated with that
scope.Whether the Authorization Server grants access or the Credential Endpoint actually returns the wanted Credential again
depends on the effective Credential Policies. These may require an existing Credential Offer for a given
credential_configuration_idand hence prevent such a Credential Request on scope alone.Pre-Authorized Code Grant
As the name suggests, this is a "pre-authorized" grant that the Wallet can use directly in an AccessToken Request. No
further authorization is required on part of the Wallet. It works for cases where the Wallet cannot be expected to use
an
authorization_codegrant. Since this is bearer grant that gives direct access to the Credentials referencedby
credential_configuration_ids, the party that creates such a Credential Offer must take upmost care abouthow to communicate that "pre-authorized" grant. As a second authorization factor, the Issuer can create a
tx_codetogether with the Credential Offer. The
tx_codeis to be communicated via an alternative channel (i.e. not together with the pre-authorized code).As noted above, we have a
/create-credential-offeras the primary entry point to initiate Credential Offer creation. This endpoint now delegates to the new CredentialOfferProvider to the actual creation of the internal CredentialOfferState. This an immutable instance that represents the CredentialOffer. It also holds theauthorization_detailsthat become part of the AccessToken response and the AccessToken JWT.Using CredentialOfferProvider as the single access point for CredentialOfferState is important. It can reason about whether an Issuing User actually has the required privileges to make the required offer.
Currently we enforce these general rules ...
credential_configuration_idmust existtargetUsermust exist and be enabledtargetUseris given, the Issuing User must hold thecredential_offer_createrole... these rules for
authorization_codegranttargetUseris not given - it is an "Anonymous" offer not bound to a specific target user... and these rules for
pre-authorized_codegranttargetUseris not given - it is a self-issued credential offerAdditionally, we now support theses Credential Policies ...
vc.policy.offer.requiredcredential_configuration_idrequires a Credential Offervc.policy.offer.pre-auth.allowedpre-authorized_codegrant are allowedvc.policy.offer.tx-code.requiredpre-authorized_codegrant require atx_codeThese policies an be set as Client Scope Attribute values.
In future may want to integrate fine grained role access to also cover the
joecan offerfootoalicecase. For now however, these three Credential Policies should be sufficient to deliver a "minimal viable product" (i.e. for oid4vci preview).Secure-by-Default could mean ...
vc.policy.offer.required=truevc.policy.offer.pre-auth.allowed=falsevc.policy.offer.tx-code.required=trueBeta Was this translation helpful? Give feedback.
All reactions