Add error details to events to be able to track down root causes

Closes #28429

Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
Alexander Schwartz 2024-04-04 10:55:25 +02:00 committed by Marek Posolda
parent 8fb6d43e07
commit 647bce49c8
6 changed files with 20 additions and 2 deletions

View file

@ -880,6 +880,8 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
return context;
} catch (IOException e) {
logger.debug("Unable to extract identity from identity token", e);
event.detail(Details.REASON, "Unable to extract identity from identity token: " + e.getMessage());
event.error(Errors.INVALID_TOKEN);
throw new ErrorResponseException(OAuthErrorException.INVALID_TOKEN, "invalid token", Response.Status.BAD_REQUEST);
}

View file

@ -94,6 +94,10 @@ public class JBossLoggingEventListenerProvider implements EventListenerProvider
sanitize(sb, event.getClientId());
sb.append(", userId=");
sanitize(sb, event.getUserId());
if (event.getSessionId() != null) {
sb.append(", sessionId=");
sanitize(sb, event.getSessionId());
}
sb.append(", ipAddress=");
sanitize(sb, event.getIpAddress());

View file

@ -1144,8 +1144,9 @@ public class TokenManager {
if (offlineTokenRequested) {
UserSessionManager sessionManager = new UserSessionManager(session);
if (!sessionManager.isOfflineTokenAllowed(clientSessionCtx)) {
event.detail(Details.REASON, "Offline tokens not allowed for the user or client");
event.error(Errors.NOT_ALLOWED);
throw new ErrorResponseException("not_allowed", "Offline tokens not allowed for the user or client", Response.Status.BAD_REQUEST);
throw new ErrorResponseException(Errors.NOT_ALLOWED, "Offline tokens not allowed for the user or client", Response.Status.BAD_REQUEST);
}
refreshToken.type(TokenUtil.TOKEN_TYPE_OFFLINE);
if (realm.isOfflineSessionMaxLifespanEnabled()) {

View file

@ -433,6 +433,7 @@ public class LogoutEndpoint {
}
} catch (OAuthErrorException e) {
event.event(EventType.LOGOUT);
event.detail(Details.REASON, e.getDescription());
event.error(Errors.INVALID_TOKEN);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.SESSION_NOT_ACTIVE);
}
@ -529,9 +530,11 @@ public class LogoutEndpoint {
} catch (OAuthErrorException e) {
// KEYCLOAK-6771 Certificate Bound Token
if (MtlsHoKTokenUtil.CERT_VERIFY_ERROR_DESC.equals(e.getDescription())) {
event.detail(Details.REASON, e.getDescription());
event.error(Errors.NOT_ALLOWED);
throw new CorsErrorResponseException(cors, e.getError(), e.getDescription(), Response.Status.UNAUTHORIZED);
} else {
event.detail(Details.REASON, e.getDescription());
event.error(Errors.INVALID_TOKEN);
throw new CorsErrorResponseException(cors, e.getError(), e.getDescription(), Response.Status.BAD_REQUEST);
}

View file

@ -171,6 +171,7 @@ public class TokenRevocationEndpoint {
String encodedToken = formParams.getFirst(PARAM_TOKEN);
if (encodedToken == null) {
event.detail(Details.REASON, "Token not provided");
event.error(Errors.INVALID_REQUEST);
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "Token not provided",
Response.Status.BAD_REQUEST);
@ -184,6 +185,7 @@ public class TokenRevocationEndpoint {
}
if (!(TokenUtil.TOKEN_TYPE_REFRESH.equals(token.getType()) || TokenUtil.TOKEN_TYPE_OFFLINE.equals(token.getType()) || TokenUtil.TOKEN_TYPE_BEARER.equals(token.getType())|| TokenUtil.TOKEN_TYPE_DPOP.equals(token.getType()))) {
event.detail(Details.REASON, "Unsupported token type");
event.error(Errors.INVALID_TOKEN_TYPE);
throw new CorsErrorResponseException(cors, OAuthErrorException.UNSUPPORTED_TOKEN_TYPE, "Unsupported token type",
Response.Status.BAD_REQUEST);
@ -193,11 +195,13 @@ public class TokenRevocationEndpoint {
private void checkIssuedFor() {
String issuedFor = token.getIssuedFor();
if (issuedFor == null) {
event.detail(Details.REASON, "Issued for not set");
event.error(Errors.INVALID_TOKEN);
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_TOKEN, "Invalid token", Response.Status.OK);
}
if (!client.getClientId().equals(issuedFor)) {
event.detail(Details.REASON, "Unmatching clients");
event.error(Errors.INVALID_REQUEST);
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "Unmatching clients",
Response.Status.BAD_REQUEST);

View file

@ -25,10 +25,10 @@ import org.jboss.logging.Logger;
import org.keycloak.OAuth2Constants;
import org.keycloak.OAuthErrorException;
import org.keycloak.common.Profile;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventType;
import org.keycloak.models.AuthenticatedClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.representations.AccessTokenResponse;
@ -65,6 +65,7 @@ public class RefreshTokenGrantType extends OAuth2GrantTypeBase {
session.clientPolicy().triggerOnEvent(new TokenRefreshContext(formParams));
refreshToken = formParams.getFirst(OAuth2Constants.REFRESH_TOKEN);
} catch (ClientPolicyException cpe) {
event.detail(Details.REASON, cpe.getErrorDetail());
event.error(cpe.getError());
throw new CorsErrorResponseException(cors, cpe.getError(), cpe.getErrorDetail(), cpe.getErrorStatus());
}
@ -91,13 +92,16 @@ public class RefreshTokenGrantType extends OAuth2GrantTypeBase {
logger.trace(e.getMessage(), e);
// KEYCLOAK-6771 Certificate Bound Token
if (MtlsHoKTokenUtil.CERT_VERIFY_ERROR_DESC.equals(e.getDescription())) {
event.detail(Details.REASON, e.getDescription());
event.error(Errors.NOT_ALLOWED);
throw new CorsErrorResponseException(cors, e.getError(), e.getDescription(), Response.Status.UNAUTHORIZED);
} else {
event.detail(Details.REASON, e.getDescription());
event.error(Errors.INVALID_TOKEN);
throw new CorsErrorResponseException(cors, e.getError(), e.getDescription(), Response.Status.BAD_REQUEST);
}
} catch (ClientPolicyException cpe) {
event.detail(Details.REASON, cpe.getErrorDetail());
event.error(cpe.getError());
throw new CorsErrorResponseException(cors, cpe.getError(), cpe.getErrorDetail(), cpe.getErrorStatus());
}