Skip to content

Commit

Permalink
Add error details to events to be able to track down root causes
Browse files Browse the repository at this point in the history
Closes keycloak#28429

Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
  • Loading branch information
ahus1 authored and mposolda committed Apr 4, 2024
1 parent 8fb6d43 commit 647bce4
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,8 @@ final protected BrokeredIdentityContext validateJwt(EventBuilder event, String s
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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ private void logEvent(Event event) {
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());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1144,8 +1144,9 @@ private void generateRefreshToken(boolean offlineTokenRequested) {
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()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ private Response doBrowserLogout(AuthenticationSessionModel logoutSession) {
}
} 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);
}
Expand Down Expand Up @@ -529,9 +530,11 @@ private Response logoutToken() {
} 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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ private void checkToken() {
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);
Expand All @@ -184,6 +185,7 @@ private void checkToken() {
}

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);
Expand All @@ -193,11 +195,13 @@ private void checkToken() {
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
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;
Expand Down Expand Up @@ -65,6 +65,7 @@ public Response process(Context context) {
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());
}
Expand All @@ -91,13 +92,16 @@ public Response process(Context context) {
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());
}
Expand Down

0 comments on commit 647bce4

Please sign in to comment.