Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(jans-auth-server): introspection endpoint must return 401 when ORM throws "Failed to find entry" exception #7772 #7810

Merged
merged 2 commits into from
Feb 22, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import io.jans.as.model.authzdetails.AuthzDetails;
import io.jans.as.common.service.AttributeService;
import io.jans.as.model.authorize.AuthorizeErrorResponseType;
import io.jans.as.model.authzdetails.AuthzDetails;
import io.jans.as.model.common.IntrospectionResponse;
import io.jans.as.model.config.Constants;
import io.jans.as.model.configuration.AppConfiguration;
Expand All @@ -29,6 +29,7 @@
import io.jans.as.server.service.external.context.ExternalIntrospectionContext;
import io.jans.as.server.service.token.TokenService;
import io.jans.as.server.util.ServerUtil;
import io.jans.orm.exception.EntryPersistenceException;
import io.jans.util.Pair;
import jakarta.inject.Inject;
import jakarta.servlet.http.HttpServletRequest;
Expand Down Expand Up @@ -110,39 +111,48 @@ public Response introspectPost(@HeaderParam("Authorization") String authorizatio
}

private AuthorizationGrant validateAuthorization(String authorization, String token) throws UnsupportedEncodingException {
final boolean skipAuthorization = isTrue(appConfiguration.getIntrospectionSkipAuthorization());
log.trace("skipAuthorization: {}", skipAuthorization);
if (skipAuthorization) {
return null;
}
try {
final boolean skipAuthorization = isTrue(appConfiguration.getIntrospectionSkipAuthorization());
log.trace("skipAuthorization: {}", skipAuthorization);
if (skipAuthorization) {
return null;
}

if (StringUtils.isBlank(authorization)) {
log.trace("Bad request: Authorization header or token is blank.");
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(errorResponseFactory.errorAsJson(AuthorizeErrorResponseType.INVALID_REQUEST, "")).build());
}
if (StringUtils.isBlank(authorization)) {
log.trace("Bad request: Authorization header or token is blank.");
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(errorResponseFactory.errorAsJson(AuthorizeErrorResponseType.INVALID_REQUEST, "")).build());
}

final Pair<AuthorizationGrant, Boolean> pair = getAuthorizationGrant(authorization, token);
final AuthorizationGrant authorizationGrant = pair.getFirst();
if (authorizationGrant == null) {
log.error("Authorization grant is null.");
throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED).type(MediaType.APPLICATION_JSON_TYPE).entity(errorResponseFactory.errorAsJson(AuthorizeErrorResponseType.ACCESS_DENIED, "Authorization grant is null.")).build());
}
final Pair<AuthorizationGrant, Boolean> pair = getAuthorizationGrant(authorization, token);
final AuthorizationGrant authorizationGrant = pair.getFirst();
if (authorizationGrant == null) {
log.error("Authorization grant is null.");
throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED).type(MediaType.APPLICATION_JSON_TYPE).entity(errorResponseFactory.errorAsJson(AuthorizeErrorResponseType.ACCESS_DENIED, "Authorization grant is null.")).build());
}

final AbstractToken authorizationAccessToken = authorizationGrant.getAccessToken(tokenService.getToken(authorization));
final AbstractToken authorizationAccessToken = authorizationGrant.getAccessToken(tokenService.getToken(authorization));

if ((authorizationAccessToken == null || !authorizationAccessToken.isValid()) && BooleanUtils.isFalse(pair.getSecond())) {
log.error("Access token is not valid. Valid: {}, basicClientAuthentication: {}", (authorizationAccessToken != null && authorizationAccessToken.isValid()), pair.getSecond());
throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED).type(MediaType.APPLICATION_JSON_TYPE).entity(errorResponseFactory.errorAsJson(AuthorizeErrorResponseType.ACCESS_DENIED, "Access token is not valid")).build());
}
if ((authorizationAccessToken == null || !authorizationAccessToken.isValid()) && BooleanUtils.isFalse(pair.getSecond())) {
log.error("Access token is not valid. Valid: {}, basicClientAuthentication: {}", (authorizationAccessToken != null && authorizationAccessToken.isValid()), pair.getSecond());
throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED).type(MediaType.APPLICATION_JSON_TYPE).entity(errorResponseFactory.errorAsJson(AuthorizeErrorResponseType.ACCESS_DENIED, "Access token is not valid")).build());
}

if (isTrue(appConfiguration.getIntrospectionAccessTokenMustHaveUmaProtectionScope()) &&
!authorizationGrant.getScopesAsString().contains(UmaScopeType.PROTECTION.getValue())) { // #562 - make uma_protection optional
final String reason = "access_token used to access introspection endpoint does not have uma_protection scope, however in AS configuration `checkUmaProtectionScopePresenceDuringIntrospection` is true";
log.trace(reason);
throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED).entity(errorResponseFactory.errorAsJson(AuthorizeErrorResponseType.ACCESS_DENIED, reason)).type(MediaType.APPLICATION_JSON_TYPE).build());
if (isTrue(appConfiguration.getIntrospectionAccessTokenMustHaveUmaProtectionScope()) &&
!authorizationGrant.getScopesAsString().contains(UmaScopeType.PROTECTION.getValue())) { // #562 - make uma_protection optional
final String reason = "access_token used to access introspection endpoint does not have uma_protection scope, however in AS configuration `checkUmaProtectionScopePresenceDuringIntrospection` is true";
log.trace(reason);
throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED).entity(errorResponseFactory.errorAsJson(AuthorizeErrorResponseType.ACCESS_DENIED, reason)).type(MediaType.APPLICATION_JSON_TYPE).build());
}
introspectionService.validateIntrospectionScopePresence(authorizationGrant);
return authorizationGrant;
} catch (EntryPersistenceException e) {
log.trace("Failed to find entry.", e);
throw new WebApplicationException(Response
.status(Response.Status.UNAUTHORIZED)
.type(MediaType.APPLICATION_JSON_TYPE)
.entity(errorResponseFactory.errorAsJson(AuthorizeErrorResponseType.ACCESS_DENIED, "Authorization is not valid"))
.build());
}
introspectionService.validateIntrospectionScopePresence(authorizationGrant);
return authorizationGrant;
}

private Response introspect(String authorization, String accept, String token, String tokenTypeHint, String responseAsJwt, HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
Expand Down