Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/src/main/java/org/keycloak/OAuth2Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -176,5 +176,6 @@ public interface OAuth2Constants {

// OID4VCI - https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html
String OPENID_CREDENTIAL = "openid_credential";
String CREDENTIAL_CONFIGURATION_ID = "credential_configuration_id";
String CREDENTIAL_IDENTIFIERS = "credential_identifiers";
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@

import org.jboss.logging.Logger;

import static org.keycloak.OAuth2Constants.CREDENTIAL_CONFIGURATION_ID;
import static org.keycloak.OAuth2Constants.CREDENTIAL_IDENTIFIERS;
import static org.keycloak.OAuth2Constants.OPENID_CREDENTIAL;
import static org.keycloak.models.Constants.AUTHORIZATION_DETAILS_RESPONSE;
import static org.keycloak.protocol.oid4vc.issuance.OID4VCAuthorizationDetailResponse.CLAIMS;
import static org.keycloak.protocol.oid4vc.issuance.OID4VCAuthorizationDetailResponse.CREDENTIAL_CONFIGURATION_ID;
import static org.keycloak.protocol.oid4vc.issuance.OID4VCAuthorizationDetailResponse.CREDENTIAL_IDENTIFIERS;
import static org.keycloak.protocol.oid4vc.model.ClaimsDescription.MANDATORY;
import static org.keycloak.protocol.oid4vc.model.ClaimsDescription.PATH;
import static org.keycloak.protocol.oid4vc.model.OID4VCAuthorizationDetail.CLAIMS;

public class OID4VCAuthorizationDetailsProcessor implements AuthorizationDetailsProcessor<OID4VCAuthorizationDetailResponse> {
public class OID4VCAuthorizationDetailsProcessor implements AuthorizationDetailsProcessor<OID4VCAuthorizationDetail> {
private static final Logger logger = Logger.getLogger(OID4VCAuthorizationDetailsProcessor.class);
private final KeycloakSession session;

Expand All @@ -75,12 +75,12 @@ public String getSupportedType() {
}

@Override
public Class<OID4VCAuthorizationDetailResponse> getSupportedResponseJavaType() {
return OID4VCAuthorizationDetailResponse.class;
public Class<OID4VCAuthorizationDetail> getSupportedResponseJavaType() {
return OID4VCAuthorizationDetail.class;
}

@Override
public OID4VCAuthorizationDetailResponse process(UserSessionModel userSession, ClientSessionContext clientSessionCtx, AuthorizationDetailsJSONRepresentation authzDetail) {
public OID4VCAuthorizationDetail process(UserSessionModel userSession, ClientSessionContext clientSessionCtx, AuthorizationDetailsJSONRepresentation authzDetail) {
OID4VCAuthorizationDetail detail = authzDetail.asSubtype(OID4VCAuthorizationDetail.class);
Map<String, SupportedCredentialConfiguration> supportedCredentials = OID4VCIssuerWellKnownProvider.getSupportedCredentials(session);

Expand All @@ -89,7 +89,7 @@ public OID4VCAuthorizationDetailResponse process(UserSessionModel userSession, C
String issuerIdentifier = OID4VCIssuerWellKnownProvider.getIssuer(session.getContext());

validateAuthorizationDetail(detail, supportedCredentials, authorizationServers, issuerIdentifier);
OID4VCAuthorizationDetailResponse responseDetail = buildAuthorizationDetailResponse(detail, userSession, clientSessionCtx);
OID4VCAuthorizationDetail responseDetail = buildAuthorizationDetail(detail, userSession, clientSessionCtx);

// For authorization code flow, create CredentialOfferState if credential identifiers are present
// This allows credential requests with credential_identifier to find the associated offer state
Expand All @@ -104,7 +104,7 @@ public OID4VCAuthorizationDetailResponse process(UserSessionModel userSession, C
* Processes all OID4VC authorization details to support multiple credential requests.
*/
private void createOfferStateForAuthorizationCodeFlow(UserSessionModel userSession, ClientSessionContext clientSessionCtx,
OID4VCAuthorizationDetailResponse oid4vcDetail) {
OID4VCAuthorizationDetail oid4vcDetail) {
AuthenticatedClientSessionModel clientSession = clientSessionCtx.getClientSession();
ClientModel client = clientSession != null ? clientSession.getClient() : null;
UserModel user = userSession != null ? userSession.getUser() : null;
Expand Down Expand Up @@ -260,12 +260,12 @@ private void validateClaims(List<ClaimsDescription> claims, SupportedCredentialC
}
}

private OID4VCAuthorizationDetailResponse buildAuthorizationDetailResponse(OID4VCAuthorizationDetail detail, UserSessionModel userSession, ClientSessionContext clientSessionCtx) {
private OID4VCAuthorizationDetail buildAuthorizationDetail(OID4VCAuthorizationDetail detail, UserSessionModel userSession, ClientSessionContext clientSessionCtx) {
String credentialConfigurationId = detail.getCredentialConfigurationId();

// Try to reuse identifier from authorizationDetailsResponse in client session context
List<AuthorizationDetailsJSONRepresentation> previousResponses = clientSessionCtx.getAttribute(AUTHORIZATION_DETAILS_RESPONSE, List.class);
List<OID4VCAuthorizationDetailResponse> oid4vcPreviousResponses = getSupportedAuthorizationDetails(previousResponses);
List<OID4VCAuthorizationDetail> oid4vcPreviousResponses = getSupportedAuthorizationDetails(previousResponses);
List<String> credentialIdentifiers = oid4vcPreviousResponses != null && !oid4vcPreviousResponses.isEmpty()
? oid4vcPreviousResponses.get(0).getCredentialIdentifiers()
: null;
Expand All @@ -275,7 +275,7 @@ private OID4VCAuthorizationDetailResponse buildAuthorizationDetailResponse(OID4V
credentialIdentifiers.add(UUID.randomUUID().toString());
}

OID4VCAuthorizationDetailResponse responseDetail = new OID4VCAuthorizationDetailResponse();
OID4VCAuthorizationDetail responseDetail = new OID4VCAuthorizationDetail();
responseDetail.setType(OPENID_CREDENTIAL);
responseDetail.setCredentialConfigurationId(credentialConfigurationId);
responseDetail.setCredentialIdentifiers(credentialIdentifiers);
Expand All @@ -292,7 +292,7 @@ private OID4VCAuthorizationDetailResponse buildAuthorizationDetailResponse(OID4V
* @param clientSession the client session that contains the credential offer information
* @return the authorization details response if generation was successful, null otherwise
*/
private List<OID4VCAuthorizationDetailResponse> generateAuthorizationDetailsFromCredentialOffer(AuthenticatedClientSessionModel clientSession) {
private List<OID4VCAuthorizationDetail> generateAuthorizationDetailsFromCredentialOffer(AuthenticatedClientSessionModel clientSession) {
logger.debug("Processing authorization_details from credential offer");

// Get supported credentials
Expand All @@ -311,7 +311,7 @@ private List<OID4VCAuthorizationDetailResponse> generateAuthorizationDetailsFrom
}

// Generate authorization_details for each credential configuration
List<OID4VCAuthorizationDetailResponse> authorizationDetailsList = new ArrayList<>();
List<OID4VCAuthorizationDetail> authorizationDetailsList = new ArrayList<>();

for (String credentialConfigurationId : credentialConfigurationIds) {
SupportedCredentialConfiguration config = supportedCredentials.get(credentialConfigurationId);
Expand All @@ -324,7 +324,7 @@ private List<OID4VCAuthorizationDetailResponse> generateAuthorizationDetailsFrom
logger.debugf("Generated credential identifier '%s' for configuration '%s'",
credentialIdentifier, credentialConfigurationId);

OID4VCAuthorizationDetailResponse authDetail = new OID4VCAuthorizationDetailResponse();
OID4VCAuthorizationDetail authDetail = new OID4VCAuthorizationDetail();
authDetail.setType(OPENID_CREDENTIAL);
authDetail.setCredentialConfigurationId(credentialConfigurationId);
authDetail.setCredentialIdentifiers(List.of(credentialIdentifier));
Expand Down Expand Up @@ -363,7 +363,7 @@ private List<String> extractCredentialConfigurationIds(AuthenticatedClientSessio
}

@Override
public List<OID4VCAuthorizationDetailResponse> handleMissingAuthorizationDetails(UserSessionModel userSession, ClientSessionContext clientSessionCtx) {
public List<OID4VCAuthorizationDetail> handleMissingAuthorizationDetails(UserSessionModel userSession, ClientSessionContext clientSessionCtx) {
// Only generate authorization_details from credential offer if:
// 1. No authorization_details were processed yet, AND
// 2. There's a credential offer note in the client session (indicating this is a credential offer flow)
Expand All @@ -377,7 +377,7 @@ public List<OID4VCAuthorizationDetailResponse> handleMissingAuthorizationDetails
}

@Override
public OID4VCAuthorizationDetailResponse processStoredAuthorizationDetails(UserSessionModel userSession, ClientSessionContext clientSessionCtx, AuthorizationDetailsJSONRepresentation storedAuthDetails)
public OID4VCAuthorizationDetail processStoredAuthorizationDetails(UserSessionModel userSession, ClientSessionContext clientSessionCtx, AuthorizationDetailsJSONRepresentation storedAuthDetails)
throws InvalidAuthorizationDetailsException {
if (storedAuthDetails == null) {
return null;
Expand Down Expand Up @@ -412,15 +412,6 @@ public <T extends AuthorizationDetailsJSONRepresentation> T asSubtype(Authorizat
fillFields(authzDetail, detail);
return clazz.cast(detail);
}
} else if (OID4VCAuthorizationDetailResponse.class.equals(clazz)) {
if (authzDetail instanceof OID4VCAuthorizationDetailResponse) {
return clazz.cast(authzDetail);
} else {
OID4VCAuthorizationDetailResponse detail = new OID4VCAuthorizationDetailResponse();
fillFields(authzDetail, detail);
detail.setCredentialIdentifiers((List<String>) authzDetail.getCustomData().get(CREDENTIAL_IDENTIFIERS));
return clazz.cast(detail);
}
} else {
throw new IllegalArgumentException("Authorization details '" + authzDetail + "' is unsupported to be parsed to '" + clazz + "'.");
}
Expand All @@ -430,6 +421,7 @@ private void fillFields(AuthorizationDetailsJSONRepresentation inDetail, OID4VCA
outDetail.setType(inDetail.getType());
outDetail.setLocations(inDetail.getLocations());
outDetail.setCredentialConfigurationId((String) inDetail.getCustomData().get(CREDENTIAL_CONFIGURATION_ID));
outDetail.setCredentialIdentifiers((List<String>) inDetail.getCustomData().get(CREDENTIAL_IDENTIFIERS));
outDetail.setClaims(parseClaims((List<Map>) inDetail.getCustomData().get(CLAIMS)));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
import org.keycloak.protocol.oid4vc.model.Format;
import org.keycloak.protocol.oid4vc.model.JwtProof;
import org.keycloak.protocol.oid4vc.model.NonceResponse;
import org.keycloak.protocol.oid4vc.model.OID4VCAuthorizationDetail;
import org.keycloak.protocol.oid4vc.model.OfferUriType;
import org.keycloak.protocol.oid4vc.model.PreAuthorizedCode;
import org.keycloak.protocol.oid4vc.model.PreAuthorizedGrant;
Expand Down Expand Up @@ -784,7 +785,7 @@ public Response requestCredential(String requestPayload) {
}

CredentialScopeModel requestedCredential;
OID4VCAuthorizationDetailResponse authDetails;
OID4VCAuthorizationDetail authDetails;

// When the CredentialRequest contains a credential identifier the caller must have gone through the
// CredentialOffer process or otherwise have set up a valid CredentialOfferState
Expand Down Expand Up @@ -933,10 +934,10 @@ public Response requestCredential(String requestPayload) {
return response;
}

private OID4VCAuthorizationDetailResponse getAuthorizationDetailFromToken(AccessToken accessToken) {
private OID4VCAuthorizationDetail getAuthorizationDetailFromToken(AccessToken accessToken) {
List<AuthorizationDetailsJSONRepresentation> tokenAuthDetails = accessToken.getAuthorizationDetails();
AuthorizationDetailsProcessor<OID4VCAuthorizationDetailResponse> oid4vcProcessor = session.getProvider(AuthorizationDetailsProcessor.class, OPENID_CREDENTIAL);
List<OID4VCAuthorizationDetailResponse> oid4vcResponses = oid4vcProcessor.getSupportedAuthorizationDetails(tokenAuthDetails);
AuthorizationDetailsProcessor<OID4VCAuthorizationDetail> oid4vcProcessor = session.getProvider(AuthorizationDetailsProcessor.class, OPENID_CREDENTIAL);
List<OID4VCAuthorizationDetail> oid4vcResponses = oid4vcProcessor.getSupportedAuthorizationDetails(tokenAuthDetails);
return oid4vcResponses == null || oid4vcResponses.isEmpty() ? null : oid4vcResponses.get(0);
}

Expand Down Expand Up @@ -1421,7 +1422,7 @@ private AuthenticationManager.AuthResult getAuthResult() {
*/
private Object getCredential(AuthenticationManager.AuthResult authResult,
SupportedCredentialConfiguration credentialConfig,
OID4VCAuthorizationDetailResponse authDetail,
OID4VCAuthorizationDetail authDetail,
CredentialRequest credentialRequestVO,
EventBuilder eventBuilder
) {
Expand Down Expand Up @@ -1512,7 +1513,7 @@ private Response getErrorResponse(ErrorType errorType, String errorDescription)

// builds the unsigned credential by applying all protocol mappers.
private VCIssuanceContext getVCToSign(List<OID4VCMapper> protocolMappers, SupportedCredentialConfiguration credentialConfig,
AuthenticationManager.AuthResult authResult, OID4VCAuthorizationDetailResponse authDetail, CredentialRequest credentialRequestVO,
AuthenticationManager.AuthResult authResult, OID4VCAuthorizationDetail authDetail, CredentialRequest credentialRequestVO,
CredentialScopeModel credentialScopeModel, EventBuilder eventBuilder) {

// Compute issuance date and apply correlation-mitigation according to realm configuration
Expand Down Expand Up @@ -1626,7 +1627,7 @@ private CredentialBuilder findCredentialBuilder(SupportedCredentialConfiguration
* @throws BadRequestException if mandatory requested claims are missing
*/
private void validateRequestedClaimsArePresent(Map<String, Object> allClaims, SupportedCredentialConfiguration credentialConfig,
UserModel user, OID4VCAuthorizationDetailResponse authzDetail, String scope, EventBuilder eventBuilder) {
UserModel user, OID4VCAuthorizationDetail authzDetail, String scope, EventBuilder eventBuilder) {
// Protocol mappers from configuration
Map<List<Object>, ClaimsDescription> claimsConfig = credentialConfig.getCredentialMetadata().getClaims()
.stream()
Expand Down Expand Up @@ -1672,7 +1673,7 @@ private void validateRequestedClaimsArePresent(Map<String, Object> allClaims, Su
}


private List<ClaimsDescription> getClaimsFromAuthzDetails(String scope, UserModel user, OID4VCAuthorizationDetailResponse authzDetail) {
private List<ClaimsDescription> getClaimsFromAuthzDetails(String scope, UserModel user, OID4VCAuthorizationDetail authzDetail) {
List<ClaimsDescription> storedClaims = authzDetail == null ? null : authzDetail.getClaims();
if (storedClaims == null || storedClaims.isEmpty()) {
String username = user.getUsername();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
import org.keycloak.common.util.Base64Url;
import org.keycloak.common.util.Time;
import org.keycloak.models.KeycloakSession;
import org.keycloak.protocol.oid4vc.issuance.OID4VCAuthorizationDetailResponse;
import org.keycloak.protocol.oid4vc.model.CredentialsOffer;
import org.keycloak.protocol.oid4vc.model.OID4VCAuthorizationDetail;
import org.keycloak.protocol.oid4vc.model.PreAuthorizedCode;
import org.keycloak.protocol.oid4vc.model.PreAuthorizedGrant;
import org.keycloak.provider.Provider;
Expand All @@ -41,7 +41,7 @@ class CredentialOfferState {
private String userId;
private String nonce;
private int expiration;
private OID4VCAuthorizationDetailResponse authorizationDetails;
private OID4VCAuthorizationDetail authorizationDetails;

public CredentialOfferState(CredentialsOffer credOffer, String clientId, String userId, int expiration) {
this.credentialsOffer = credOffer;
Expand Down Expand Up @@ -88,11 +88,11 @@ public int getExpiration() {
return expiration;
}

public OID4VCAuthorizationDetailResponse getAuthorizationDetails() {
public OID4VCAuthorizationDetail getAuthorizationDetails() {
return authorizationDetails;
}

public void setAuthorizationDetails(OID4VCAuthorizationDetailResponse authorizationDetails) {
public void setAuthorizationDetails(OID4VCAuthorizationDetail authorizationDetails) {
this.authorizationDetails = authorizationDetails;
}

Expand Down
Loading
Loading