use of org.apereo.cas.ticket.accesstoken.OAuth20AccessToken in project cas by apereo.
the class OidcIdTokenGeneratorService method buildJwtClaims.
/**
* Produce claims as jwt.
* As per OpenID Connect Core section 5.4, 'The Claims requested by the profile,
* email, address, and phone scope values are returned from the UserInfo Endpoint',
* except for response_type=id_token, where they are returned in the id_token
* (as there is no access token issued that could be used to access the userinfo endpoint).
*
* @param accessToken the access token
* @param timeoutInSeconds the timeoutInSeconds
* @param service the service
* @param responseType the response type
* @param grantType the grant type
* @return the jwt claims
*/
protected JwtClaims buildJwtClaims(final OAuth20AccessToken accessToken, final long timeoutInSeconds, final OidcRegisteredService service, final OAuth20ResponseTypes responseType, final OAuth20GrantTypes grantType) {
val authentication = accessToken.getAuthentication();
val principal = getConfigurationContext().getProfileScopeToAttributesFilter().filter(accessToken.getService(), authentication.getPrincipal(), service, accessToken);
LOGGER.debug("Principal to use to build th ID token is [{}]", principal);
val oidc = getConfigurationContext().getCasProperties().getAuthn().getOidc();
val claims = new JwtClaims();
val tgt = accessToken.getTicketGrantingTicket();
val jwtId = getJwtId(tgt);
claims.setJwtId(jwtId);
claims.setClaim(OidcConstants.CLAIM_SESSION_ID, DigestUtils.sha(jwtId));
claims.setIssuer(getConfigurationContext().getIssuerService().determineIssuer(Optional.empty()));
claims.setAudience(accessToken.getClientId());
val expirationDate = NumericDate.now();
expirationDate.addSeconds(timeoutInSeconds);
claims.setExpirationTime(expirationDate);
claims.setIssuedAtToNow();
claims.setNotBeforeMinutesInThePast((float) Beans.newDuration(oidc.getCore().getSkew()).toMinutes());
claims.setSubject(principal.getId());
val mfa = getConfigurationContext().getCasProperties().getAuthn().getMfa();
val attributes = authentication.getAttributes();
if (attributes.containsKey(mfa.getCore().getAuthenticationContextAttribute())) {
val acrValues = CollectionUtils.toCollection(attributes.get(mfa.getCore().getAuthenticationContextAttribute()));
val authnContexts = oidc.getCore().getAuthenticationContextReferenceMappings();
val mappings = CollectionUtils.convertDirectedListToMap(authnContexts);
val acrMapped = acrValues.stream().map(acrValue -> mappings.entrySet().stream().filter(entry -> entry.getValue().equalsIgnoreCase(acrValue.toString())).map(Map.Entry::getKey).findFirst().orElseGet(acrValue::toString)).collect(Collectors.joining(" "));
LOGGER.debug("ID token acr claim calculated as [{}]", acrMapped);
claims.setStringClaim(OidcConstants.ACR, acrMapped);
}
if (attributes.containsKey(AuthenticationHandler.SUCCESSFUL_AUTHENTICATION_HANDLERS)) {
val val = CollectionUtils.toCollection(attributes.get(AuthenticationHandler.SUCCESSFUL_AUTHENTICATION_HANDLERS));
claims.setStringListClaim(OidcConstants.AMR, val.toArray(ArrayUtils.EMPTY_STRING_ARRAY));
}
claims.setStringClaim(OAuth20Constants.CLIENT_ID, service.getClientId());
claims.setClaim(OidcConstants.CLAIM_AUTH_TIME, tgt.getAuthentication().getAuthenticationDate().toEpochSecond());
if (attributes.containsKey(OAuth20Constants.STATE)) {
setClaim(claims, OAuth20Constants.STATE, attributes.get(OAuth20Constants.STATE).get(0));
}
if (attributes.containsKey(OAuth20Constants.NONCE)) {
setClaim(claims, OAuth20Constants.NONCE, attributes.get(OAuth20Constants.NONCE).get(0));
}
generateAccessTokenHash(accessToken, service, claims);
val includeClaims = responseType != OAuth20ResponseTypes.CODE && grantType != OAuth20GrantTypes.AUTHORIZATION_CODE;
if (includeClaims || oidc.getCore().isIncludeIdTokenClaims()) {
FunctionUtils.doIf(oidc.getCore().isIncludeIdTokenClaims(), ignore -> LOGGER.warn("Individual claims requested by OpenID scopes are forced to be included in the ID token. " + "This is a violation of the OpenID Connect specification and a workaround via dedicated CAS configuration. " + "Claims should be requested from the userinfo/profile endpoints in exchange for an access token.")).accept(claims);
collectIdTokenClaims(principal, claims);
} else {
LOGGER.debug("Per OpenID Connect specification, individual claims requested by OpenID scopes " + "such as profile, email, address, etc. are only put " + "into the OpenID Connect ID token when the response type is set to id_token.");
}
return claims;
}
use of org.apereo.cas.ticket.accesstoken.OAuth20AccessToken in project cas by apereo.
the class OidcDynamicClientRegistrationEndpointController method generateRegistrationAccessToken.
/**
* Generate registration access token access token.
*
* @param request the request
* @param response the response
* @param registeredService the registered service
* @param registrationRequest the registration request
* @return the access token
* @throws Exception the exception
*/
protected OAuth20AccessToken generateRegistrationAccessToken(final HttpServletRequest request, final HttpServletResponse response, final OidcRegisteredService registeredService, final OidcClientRegistrationRequest registrationRequest) throws Exception {
val authn = DefaultAuthenticationBuilder.newInstance().setPrincipal(PrincipalFactoryUtils.newPrincipalFactory().createPrincipal(registeredService.getClientId())).build();
val clientConfigUri = OidcClientRegistrationUtils.getClientConfigurationUri(registeredService, getConfigurationContext().getCasProperties().getServer().getPrefix());
val service = getConfigurationContext().getWebApplicationServiceServiceFactory().createService(clientConfigUri);
val factory = (OAuth20AccessTokenFactory) getConfigurationContext().getTicketFactory().get(OAuth20AccessToken.class);
val accessToken = factory.create(service, authn, List.of(OidcConstants.CLIENT_REGISTRATION_SCOPE), registeredService.getClientId(), OAuth20ResponseTypes.NONE, OAuth20GrantTypes.NONE);
getConfigurationContext().getTicketRegistry().addTicket(accessToken);
return accessToken;
}
use of org.apereo.cas.ticket.accesstoken.OAuth20AccessToken in project cas by apereo.
the class UmaAuthorizationRequestEndpointController method generateRequestingPartyToken.
/**
* Generate requesting party token response entity.
*
* @param request the request
* @param response the response
* @param profileResult the profile result
* @param umaRequest the uma request
* @param permissionTicket the permission ticket
* @param resourceSet the resource set
* @return the response entity
* @throws Exception the exception
*/
protected ResponseEntity generateRequestingPartyToken(final HttpServletRequest request, final HttpServletResponse response, final UserProfile profileResult, final UmaAuthorizationRequest umaRequest, final UmaPermissionTicket permissionTicket, final ResourceSet resourceSet) throws Exception {
val currentAat = (OAuth20AccessToken) profileResult.getAttribute(OAuth20AccessToken.class.getName());
val registeredService = OAuth20Utils.getRegisteredOAuthServiceByClientId(getUmaConfigurationContext().getServicesManager(), OAuth20Utils.getClientIdFromAuthenticatedProfile(profileResult));
val scopes = new LinkedHashSet<>(permissionTicket.getScopes());
scopes.add(OAuth20Constants.UMA_AUTHORIZATION_SCOPE);
scopes.addAll(resourceSet.getScopes());
val holder = AccessTokenRequestContext.builder().authentication(currentAat.getAuthentication()).ticketGrantingTicket(currentAat.getTicketGrantingTicket()).grantType(OAuth20GrantTypes.UMA_TICKET).responseType(OAuth20ResponseTypes.NONE).registeredService(registeredService).generateRefreshToken(false).scopes(scopes).service(currentAat.getService()).build();
val result = getUmaConfigurationContext().getAccessTokenGenerator().generate(holder);
val accessToken = result.getAccessToken().get();
val encodedAccessToken = OAuth20JwtAccessTokenEncoder.builder().accessToken(accessToken).registeredService(holder.getRegisteredService()).service(holder.getService()).accessTokenJwtBuilder(getUmaConfigurationContext().getAccessTokenJwtBuilder()).casProperties(getUmaConfigurationContext().getCasProperties()).build().encode();
val timeout = Beans.newDuration(getUmaConfigurationContext().getCasProperties().getAuthn().getOauth().getUma().getRequestingPartyToken().getMaxTimeToLiveInSeconds()).getSeconds();
val userProfile = OAuth20Utils.getAuthenticatedUserProfile(new JEEContext(request, response), getUmaConfigurationContext().getSessionStore());
userProfile.addAttribute(UmaPermissionTicket.class.getName(), permissionTicket);
userProfile.addAttribute(ResourceSet.class.getName(), resourceSet);
val idToken = getUmaConfigurationContext().getRequestingPartyTokenGenerator().generate(accessToken, timeout, userProfile, OAuth20ResponseTypes.CODE, OAuth20GrantTypes.UMA_TICKET, registeredService);
accessToken.setIdToken(idToken);
getUmaConfigurationContext().getCentralAuthenticationService().updateTicket(accessToken);
if (StringUtils.isNotBlank(umaRequest.getRpt())) {
getUmaConfigurationContext().getCentralAuthenticationService().deleteTicket(umaRequest.getRpt());
}
val model = CollectionUtils.wrap("rpt", encodedAccessToken, "code", HttpStatus.CREATED);
return new ResponseEntity<>(model, HttpStatus.OK);
}
Aggregations