@SuppressWarnings("LongFloatConversion")
    protected JwtClaims buildJwtClaims(final IdTokenGenerationContext context) throws Throwable {
        val accessToken = context.getAccessToken();
        LOGGER.trace("Attempting to produce claims for the ID token [{}]", accessToken);
        val authentication = accessToken.getAuthentication();
        val activePrincipal = buildPrincipalForAttributeFilter(accessToken, context.getRegisteredService());
        val principal = getConfigurationContext().getProfileScopeToAttributesFilter()
            .filter(accessToken.getService(), activePrincipal, context.getRegisteredService(), accessToken);
        LOGGER.debug("Principal to use to build the ID token is [{}]", principal);

        val oidc = getConfigurationContext().getCasProperties().getAuthn().getOidc();
        val claims = new JwtClaims();

        val jwtId = getJwtId(accessToken);
        LOGGER.debug("Calculated ID token jti claim to be [{}]", jwtId);
        claims.setJwtId(jwtId);

        claims.setClaim(OidcConstants.CLAIM_SESSION_ID, DigestUtils.sha(jwtId));
        val oidcRegisteredService = (OidcRegisteredService) context.getRegisteredService();
        claims.setIssuer(getConfigurationContext().getIssuerService().determineIssuer(Optional.of(oidcRegisteredService)));
        val audience = context.getRegisteredService().getAudience().isEmpty()
            ? List.of(accessToken.getClientId())
            : new ArrayList<>(context.getRegisteredService().getAudience());
        claims.setAudience(audience);
        LOGGER.debug("Calculated ID token aud claim to be [{}]", audience);

        buildExpirationClaim(claims, oidcRegisteredService);

        claims.setIssuedAtToNow();
        claims.setNotBeforeMinutesInThePast(Beans.newDuration(oidc.getCore().getSkew()).toMinutes());
        claims.setSubject(principal.getId());

        buildAuthenticationContextClassRef(claims, authentication);

        val amrValues = buildAuthenticationMethods(authentication);
        if (!amrValues.isEmpty()) {
            LOGGER.debug("ID token amr claim calculated as [{}]", amrValues);
            claims.setStringListClaim(OidcConstants.AMR, amrValues.toArray(ArrayUtils.EMPTY_STRING_ARRAY));
        }

        val attributes = authentication.getAttributes();
        claims.setStringClaim(OAuth20Constants.CLIENT_ID, context.getRegisteredService().getClientId());

        val authTime = accessToken.isStateless() || accessToken.getTicketGrantingTicket() == null
            ? authentication.getAuthenticationDate().toEpochSecond()
            : ((AuthenticationAwareTicket) accessToken.getTicketGrantingTicket()).getAuthentication().getAuthenticationDate().toEpochSecond();
        claims.setClaim(OidcConstants.CLAIM_AUTH_TIME, authTime);

        if (attributes.containsKey(OAuth20Constants.STATE)) {
            setClaim(claims, OAuth20Constants.STATE, attributes.get(OAuth20Constants.STATE).getFirst());
        }
        if (attributes.containsKey(OAuth20Constants.NONCE)) {
            setClaim(claims, OAuth20Constants.NONCE, attributes.get(OAuth20Constants.NONCE).getFirst());
        }
        generateAccessTokenHash(accessToken, oidcRegisteredService, claims);

        val includeClaims = context.getResponseType() != OAuth20ResponseTypes.CODE && context.getGrantType() != OAuth20GrantTypes.AUTHORIZATION_CODE;
        if (includeClaims || includeClaimsInIdTokenForcefully(context)) {
            FunctionUtils.doIf(includeClaimsInIdTokenForcefully(context),
                    __ -> 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, context.getRegisteredService(), 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.");
        }
        claims.setStringClaim(OidcConstants.TXN, UUID.randomUUID().toString());

        if (context.getGrantType() == OAuth20GrantTypes.CIBA) {
            generateCibaClaims(context, claims);
        }
        return claims;
    }
This is {@link OidcIdTokenGeneratorService}.

@author Misagh Moayyed
@since 5.0.0
support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/token/OidcIdTokenGeneratorService.java