272         String code = 
formParams.getFirst(OAuth2Constants.CODE);
   274             event.error(Errors.INVALID_CODE);
   275             throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_REQUEST, 
"Missing parameter: " + OAuth2Constants.CODE, Response.Status.BAD_REQUEST);
   278         ClientSessionCode.ParseResult<AuthenticatedClientSessionModel> parseResult = ClientSessionCode.parseResult(code, null, 
session, 
realm, 
client, 
event, AuthenticatedClientSessionModel.class);
   279         if (parseResult.isAuthSessionNotFound() || parseResult.isIllegalHash()) {
   280             AuthenticatedClientSessionModel clientSession = parseResult.getClientSession();
   283             if (clientSession != null) {
   284                 clientSession.detachFromUserSession();
   287             event.error(Errors.INVALID_CODE);
   289             throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_GRANT, 
"Code not valid", Response.Status.BAD_REQUEST);
   292         AuthenticatedClientSessionModel clientSession = parseResult.getClientSession();
   294         if (parseResult.isExpiredToken()) {
   295             event.error(Errors.EXPIRED_CODE);
   296             throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_GRANT, 
"Code is expired", Response.Status.BAD_REQUEST);
   299         UserSessionModel userSession = clientSession.getUserSession();
   301         if (userSession == null) {
   302             event.error(Errors.USER_SESSION_NOT_FOUND);
   303             throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_GRANT, 
"User session not found", Response.Status.BAD_REQUEST);
   307         UserModel user = userSession.getUser();
   309             event.error(Errors.USER_NOT_FOUND);
   310             throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_GRANT, 
"User not found", Response.Status.BAD_REQUEST);
   313         event.user(userSession.getUser());
   315         if (!user.isEnabled()) {
   316             event.error(Errors.USER_DISABLED);
   317             throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_GRANT, 
"User disabled", Response.Status.BAD_REQUEST);
   320         String redirectUri = clientSession.getNote(OIDCLoginProtocol.REDIRECT_URI_PARAM);
   321         String redirectUriParam = 
formParams.getFirst(OAuth2Constants.REDIRECT_URI);
   324         if (redirectUriParam != null && redirectUriParam.contains(
"session_state=") && !redirectUri.contains(
"session_state=")) {
   325             redirectUriParam = KeycloakUriBuilder.fromUri(redirectUriParam)
   326                     .replaceQueryParam(OAuth2Constants.SESSION_STATE, null)
   330         if (redirectUri != null && !redirectUri.equals(redirectUriParam)) {
   331             event.error(Errors.INVALID_CODE);
   332             throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_GRANT, 
"Incorrect redirect_uri", Response.Status.BAD_REQUEST);
   336             event.error(Errors.INVALID_CODE);
   337             throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_GRANT, 
"Auth error", Response.Status.BAD_REQUEST);
   341             event.error(Errors.NOT_ALLOWED);
   342             throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_GRANT, 
"Client not allowed to exchange code", Response.Status.BAD_REQUEST);
   345         if (!AuthenticationManager.isSessionValid(
realm, userSession)) {
   346             event.error(Errors.USER_SESSION_NOT_FOUND);
   347             throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_GRANT, 
"Session not active", Response.Status.BAD_REQUEST);
   351         String codeVerifier = 
formParams.getFirst(OAuth2Constants.CODE_VERIFIER);
   352         String codeChallenge = clientSession.getNote(OIDCLoginProtocol.CODE_CHALLENGE_PARAM);
   353         String codeChallengeMethod = clientSession.getNote(OIDCLoginProtocol.CODE_CHALLENGE_METHOD_PARAM);
   354         String authUserId = user.getId();
   355         String authUsername = user.getUsername();
   356         if (authUserId == null) {
   357             authUserId = 
"unknown";
   359         if (authUsername == null) {
   360             authUsername = 
"unknown";
   362         if (codeChallenge != null && codeVerifier == null) {
   363             logger.warnf(
"PKCE code verifier not specified, authUserId = %s, authUsername = %s", authUserId, authUsername);
   364             event.error(Errors.CODE_VERIFIER_MISSING);
   365             throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_GRANT, 
"PKCE code verifier not specified", Response.Status.BAD_REQUEST);
   368         if (codeChallenge != null) {
   372                 logger.infof(
"PKCE invalid code verifier");
   373                 event.error(Errors.INVALID_CODE_VERIFIER);
   374                 throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_GRANT, 
"PKCE invalid code verifier", Response.Status.BAD_REQUEST);
   377             logger.debugf(
"PKCE supporting Client, codeVerifier = %s", codeVerifier);
   378             String codeVerifierEncoded = codeVerifier;
   382                 if (codeChallengeMethod != null && codeChallengeMethod.equals(OAuth2Constants.PKCE_METHOD_S256)) {
   383                     logger.debugf(
"PKCE codeChallengeMethod = %s", codeChallengeMethod);
   386                     logger.debug(
"PKCE codeChallengeMethod is plain");
   387                     codeVerifierEncoded = codeVerifier;
   389             } 
catch (Exception nae) {
   390                 logger.infof(
"PKCE code verification failed, not supported algorithm specified");
   391                 event.error(Errors.PKCE_VERIFICATION_FAILED);
   392                 throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_GRANT, 
"PKCE code verification failed, not supported algorithm specified", Response.Status.BAD_REQUEST);
   394             if (!codeChallenge.equals(codeVerifierEncoded)) {
   395                 logger.warnf(
"PKCE verification failed. authUserId = %s, authUsername = %s", authUserId, authUsername);
   396                 event.error(Errors.PKCE_VERIFICATION_FAILED);
   397                 throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_GRANT, 
"PKCE verification failed", Response.Status.BAD_REQUEST);
   399                 logger.debugf(
"PKCE verification success. codeVerifierEncoded = %s, codeChallenge = %s", codeVerifierEncoded, codeChallenge);
   409         String scopeParam = clientSession.getNote(OAuth2Constants.SCOPE);
   410         Set<ClientScopeModel> clientScopes = TokenManager.getRequestedClientScopes(scopeParam, 
client);
   411         if (!TokenManager.verifyConsentStillAvailable(
session, user, 
client, clientScopes)) {
   412             event.error(Errors.NOT_ALLOWED);
   413             throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_SCOPE, 
"Client no longer has requested consent from user", Response.Status.BAD_REQUEST);
   416         ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionAndClientScopes(clientSession, clientScopes);
   422                 .generateRefreshToken();
   426         if (OIDCAdvancedConfigWrapper.fromClientModel(
client).isUseMtlsHokToken()) {
   427             AccessToken.CertConf certConf = MtlsHoKTokenUtil.bindTokenWithClientCertificate(
request, 
session);
   428             if (certConf != null) {
   429                 responseBuilder.getAccessToken().setCertConf(certConf);
   430                 responseBuilder.getRefreshToken().setCertConf(certConf);
   432                 event.error(Errors.INVALID_REQUEST);
   433                 throw new CorsErrorResponseException(
cors, OAuthErrorException.INVALID_REQUEST, 
"Client Certification missing for MTLS HoK Token Binding", Response.Status.BAD_REQUEST);
   437         if (TokenUtil.isOIDCRequest(scopeParam)) {
   438             responseBuilder.generateIDToken();
   441         AccessTokenResponse res = responseBuilder.build();
   445         return cors.
builder(Response.ok(res).type(MediaType.APPLICATION_JSON_TYPE)).build();
 final EventBuilder event
Definition: TokenEndpoint.java:144
 
boolean isStandardFlowEnabled()
 
boolean isValidPkceCodeVerifier(String codeVerifier)
Definition: TokenEndpoint.java:1144
 
void updateClientSession(AuthenticatedClientSessionModel clientSession)
Definition: TokenEndpoint.java:484
 
MultivaluedMap< String, String > formParams
Definition: TokenEndpoint.java:116
 
HttpRequest request
Definition: TokenEndpoint.java:131
 
Cors cors
Definition: TokenEndpoint.java:150
 
ClientModel client
Definition: TokenEndpoint.java:117
 
final TokenManager tokenManager
Definition: TokenEndpoint.java:142
 
final RealmModel realm
Definition: TokenEndpoint.java:143
 
static final Logger logger
Definition: TokenEndpoint.java:115
 
ResponseBuilder builder
Definition: Cors.java:61
 
KeycloakSession session
Definition: TokenEndpoint.java:128
 
String generateS256CodeChallenge(String codeVerifier)
Definition: TokenEndpoint.java:1158
 
void updateUserSessionFromClientAuth(UserSessionModel userSession)
Definition: TokenEndpoint.java:510