in services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpOIDCProtocolHandler.java [107:241]
public SecurityToken mapSignInResponse(RequestContext context, Idp idp, TrustedIdp trustedIdp) {
String code = (String) WebUtils.getAttributeFromFlowScope(context,
OAuthConstants.CODE_RESPONSE_TYPE);
if (code != null && !code.isEmpty()) {
String tokenEndpoint = getProperty(trustedIdp, TOKEN_ENDPOINT);
if (tokenEndpoint == null || tokenEndpoint.isEmpty()) {
LOG.warn("A TOKEN_ENDPOINT must be configured to use the OIDCProtocolHandler");
throw new IllegalStateException("No TOKEN_ENDPOINT specified");
}
String clientId = getProperty(trustedIdp, CLIENT_ID);
String clientSecret = getProperty(trustedIdp, CLIENT_SECRET);
if (clientSecret == null || clientSecret.isEmpty()) {
LOG.warn("A CLIENT_SECRET must be configured to use the OIDCProtocolHandler");
throw new IllegalStateException("No CLIENT_SECRET specified");
}
// Here we need to get the IdToken using the authorization code
List<Object> providers = new ArrayList<>();
providers.add(new OAuthJSONProvider());
WebClient client =
WebClient.create(tokenEndpoint, providers, clientId, clientSecret, "cxf-tls.xml");
if (LOG.isDebugEnabled()) {
ClientConfiguration config = WebClient.getConfig(client);
config.getOutInterceptors().add(new LoggingOutInterceptor());
config.getInInterceptors().add(new LoggingInInterceptor());
}
client.type("application/x-www-form-urlencoded").accept("application/json");
Form form = new Form();
form.param("grant_type", "authorization_code");
form.param("code", code);
form.param("client_id", clientId);
form.param("redirect_uri", idp.getIdpUrl().toString());
Response response = client.post(form);
ClientAccessToken accessToken = response.readEntity(ClientAccessToken.class);
String idToken = accessToken.getParameters().get("id_token");
if (idToken == null) {
LOG.warn("No IdToken received from the OIDC IdP");
return null;
}
client.close();
try {
String whr = (String) WebUtils.getAttributeFromFlowScope(context, IdpConstants.HOME_REALM);
if (whr == null) {
LOG.warn("Home realm is null");
throw new IllegalStateException("Home realm is null");
}
// Parse the received Token
JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(idToken);
JwtToken jwt = jwtConsumer.getJwtToken();
if (LOG.isDebugEnabled()) {
if (jwt.getClaims() != null) {
LOG.debug("Received Claims:");
for (Map.Entry<String, Object> claim : jwt.getClaims().asMap().entrySet()) {
LOG.debug(claim.getKey() + ": " + claim.getValue());
}
}
if (jwt.getJwsHeaders() != null) {
LOG.debug("Received JWS Headers:");
for (Map.Entry<String, Object> header : jwt.getJwsHeaders().asMap().entrySet()) {
LOG.debug(header.getKey() + ": " + header.getValue());
}
}
}
if (!validateSignature(trustedIdp, jwtConsumer)) {
LOG.warn("Signature does not validate");
return null;
}
// Make sure the received token is valid according to the spec
validateToken(jwt, clientId);
Instant created = Instant.ofEpochSecond((long)jwt.getClaim(JwtConstants.CLAIM_ISSUED_AT));
Instant notBefore = null;
if (jwt.getClaim(JwtConstants.CLAIM_NOT_BEFORE) != null) {
notBefore = Instant.ofEpochSecond((long)jwt.getClaim(JwtConstants.CLAIM_NOT_BEFORE));
}
Instant expires = Instant.ofEpochSecond((long)jwt.getClaim(JwtConstants.CLAIM_EXPIRY));
// Subject
String subjectName = getProperty(trustedIdp, SUBJECT_CLAIM);
LOG.debug("Trying to extract subject name using the claim name {}", subjectName);
if (subjectName == null || jwt.getClaim(subjectName) == null) {
LOG.debug("No claim available in the token for {}", subjectName);
subjectName = "preferred_username";
LOG.debug("Falling back to use subject claim name {}", subjectName);
if (jwt.getClaim(subjectName) == null) {
subjectName = JwtConstants.CLAIM_SUBJECT;
LOG.debug("No claim available in the token for preferred_username. "
+ "Falling back to use {}", subjectName);
}
}
// Convert into a SAML Token
SamlAssertionWrapper assertion =
createSamlAssertion(idp, trustedIdp, jwt.getClaims(), (String)jwt.getClaim(subjectName),
notBefore, expires);
Document doc = DOMUtils.createDocument();
Element token = assertion.toDOM(doc);
// Create new Security token with new id.
// Parameters for freshness computation are copied from original IDP_TOKEN
SecurityToken idpToken = new SecurityToken(assertion.getId(), created, expires);
idpToken.setToken(token);
LOG.info("[IDP_TOKEN={}] for user '{}' created from [RP_TOKEN={}] issued by home realm [{}/{}]",
assertion.getId(), assertion.getSaml2().getSubject().getNameID().getValue(),
jwt.getClaim(JwtConstants.CLAIM_JWT_ID), whr, jwt.getClaim(JwtConstants.CLAIM_ISSUER));
LOG.debug("Created date={}", created);
LOG.debug("Expired date={}", expires);
return idpToken;
} catch (IllegalStateException ex) {
throw ex;
} catch (Exception ex) {
LOG.warn("Unexpected exception occured", ex);
throw new IllegalStateException("Unexpected exception occured: " + ex.getMessage());
}
}
return null;
}