Search in sources :

Example 11 with OAuth20AccessToken

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;
}
Also used : lombok.val(lombok.val) OAuth20AccessTokenAtHashGenerator(org.apereo.cas.support.oauth.web.response.accesstoken.OAuth20AccessTokenAtHashGenerator) DigestUtils(org.apereo.cas.util.DigestUtils) ArrayUtils(org.apache.commons.lang3.ArrayUtils) BooleanUtils(org.apache.commons.lang3.BooleanUtils) Beans(org.apereo.cas.configuration.support.Beans) StringUtils(org.apache.commons.lang3.StringUtils) ArrayList(java.util.ArrayList) FunctionUtils(org.apereo.cas.util.function.FunctionUtils) ObjectProvider(org.springframework.beans.factory.ObjectProvider) AuthenticationHandler(org.apereo.cas.authentication.AuthenticationHandler) Map(java.util.Map) CollectionUtils(org.apereo.cas.util.CollectionUtils) TicketGrantingTicket(org.apereo.cas.ticket.TicketGrantingTicket) OAuth20JwtAccessTokenEncoder(org.apereo.cas.support.oauth.web.response.accesstoken.response.OAuth20JwtAccessTokenEncoder) OAuth20Constants(org.apereo.cas.support.oauth.OAuth20Constants) OAuth20ResponseTypes(org.apereo.cas.support.oauth.OAuth20ResponseTypes) BaseIdTokenGeneratorService(org.apereo.cas.ticket.BaseIdTokenGeneratorService) OAuth20GrantTypes(org.apereo.cas.support.oauth.OAuth20GrantTypes) OidcConstants(org.apereo.cas.oidc.OidcConstants) lombok.val(lombok.val) OAuthRegisteredService(org.apereo.cas.support.oauth.services.OAuthRegisteredService) Collectors(java.util.stream.Collectors) OAuth20AccessToken(org.apereo.cas.ticket.accesstoken.OAuth20AccessToken) OidcConfigurationContext(org.apereo.cas.oidc.OidcConfigurationContext) Objects(java.util.Objects) Slf4j(lombok.extern.slf4j.Slf4j) NumericDate(org.jose4j.jwt.NumericDate) OidcRegisteredService(org.apereo.cas.services.OidcRegisteredService) Stream(java.util.stream.Stream) JwtClaims(org.jose4j.jwt.JwtClaims) Optional(java.util.Optional) Principal(org.apereo.cas.authentication.principal.Principal) UserProfile(org.pac4j.core.profile.UserProfile) Assert(org.springframework.util.Assert) JwtClaims(org.jose4j.jwt.JwtClaims)

Example 12 with OAuth20AccessToken

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;
}
Also used : lombok.val(lombok.val) OAuth20AccessToken(org.apereo.cas.ticket.accesstoken.OAuth20AccessToken) OAuth20AccessTokenFactory(org.apereo.cas.ticket.accesstoken.OAuth20AccessTokenFactory)

Example 13 with OAuth20AccessToken

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);
}
Also used : lombok.val(lombok.val) OAuth20AccessToken(org.apereo.cas.ticket.accesstoken.OAuth20AccessToken) LinkedHashSet(java.util.LinkedHashSet) UmaPermissionTicket(org.apereo.cas.uma.ticket.permission.UmaPermissionTicket) ResponseEntity(org.springframework.http.ResponseEntity) JEEContext(org.pac4j.core.context.JEEContext) ResourceSet(org.apereo.cas.uma.ticket.resource.ResourceSet)

Aggregations

lombok.val (lombok.val)13 OAuth20AccessToken (org.apereo.cas.ticket.accesstoken.OAuth20AccessToken)13 JEEContext (org.pac4j.core.context.JEEContext)6 Slf4j (lombok.extern.slf4j.Slf4j)4 HashMap (java.util.HashMap)3 Map (java.util.Map)3 MockTicketGrantingTicket (org.apereo.cas.mock.MockTicketGrantingTicket)3 OidcConstants (org.apereo.cas.oidc.OidcConstants)3 OAuth20Utils (org.apereo.cas.support.oauth.util.OAuth20Utils)3 ResponseEntity (org.springframework.http.ResponseEntity)3 LinkedHashMap (java.util.LinkedHashMap)2 LinkedHashSet (java.util.LinkedHashSet)2 Optional (java.util.Optional)2 HttpServletResponse (javax.servlet.http.HttpServletResponse)2 StringUtils (org.apache.commons.lang3.StringUtils)2 Principal (org.apereo.cas.authentication.principal.Principal)2 OidcConfigurationContext (org.apereo.cas.oidc.OidcConfigurationContext)2 OidcRegisteredService (org.apereo.cas.services.OidcRegisteredService)2 OAuth20Constants (org.apereo.cas.support.oauth.OAuth20Constants)2 OAuth20GrantTypes (org.apereo.cas.support.oauth.OAuth20GrantTypes)2