Skip to content

Commit

Permalink
Merge pull request #1260 from JanssenProject/jans-auth-server-1208-3
Browse files Browse the repository at this point in the history
refactor(jans-auth-server): moved acr validation to validator
  • Loading branch information
yuriyz authored Apr 26, 2022
2 parents 59ecc4a + cd22f19 commit 2c79951
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import io.jans.as.model.token.JsonWebResponse;
import io.jans.as.model.util.JwtUtil;
import io.jans.as.model.util.Util;
import io.jans.as.persistence.model.Par;
import io.jans.as.server.audit.ApplicationAuditLogger;
import io.jans.as.server.ciba.CIBAPingCallbackService;
import io.jans.as.server.ciba.CIBAPushTokenDeliveryService;
Expand All @@ -52,7 +51,6 @@
import io.jans.as.server.model.exception.InvalidSessionStateException;
import io.jans.as.server.model.ldap.ClientAuthorization;
import io.jans.as.server.model.token.JwrService;
import io.jans.as.server.par.ws.rs.ParService;
import io.jans.as.server.security.Identity;
import io.jans.as.server.service.*;
import io.jans.as.server.service.ciba.CibaRequestService;
Expand Down Expand Up @@ -132,7 +130,7 @@ public class AuthorizeRestWebServiceImpl implements AuthorizeRestWebService {
private SessionIdService sessionIdService;

@Inject
CookieService cookieService;
private CookieService cookieService;

@Inject
private ScopeChecker scopeChecker;
Expand Down Expand Up @@ -303,12 +301,7 @@ private Response requestAuthorization(AuthzRequest authzRequest) {
RedirectUriResponse redirectUriResponse = new RedirectUriResponse(new RedirectUri(authzRequest.getRedirectUri(), responseTypes, authzRequest.getResponseModeEnum()), authzRequest.getState(), authzRequest.getHttpRequest(), errorResponseFactory);
redirectUriResponse.setFapiCompatible(appConfiguration.isFapi());

if (!client.getAttributes().getAuthorizedAcrValues().isEmpty() &&
!client.getAttributes().getAuthorizedAcrValues().containsAll(authzRequest.getAcrValuesList())) {
throw redirectUriResponse.createWebException(AuthorizeErrorResponseType.INVALID_REQUEST,
"Restricted acr value request, please review the list of authorized acr values for this client");
}
checkAcrChanged(authzRequest.getAcrValues(), prompts, sessionUser); // check after redirect uri is validated
authorizeRestWebServiceValidator.validateAcrs(authzRequest, client, redirectUriResponse);

Set<String> scopes = scopeChecker.checkScopesPolicy(client, authzRequest.getScope());

Expand Down Expand Up @@ -450,7 +443,7 @@ private Response requestAuthorization(AuthzRequest authzRequest) {
authorizeRestWebServiceValidator.validateRequestJwt(authzRequest.getRequest(), authzRequest.getRequestUri(), redirectUriResponse);
}

authorizeRestWebServiceValidator.validate(responseTypes, prompts, authzRequest.getNonce(), authzRequest.getState(), authzRequest.getRedirectUri(), authzRequest.getHttpRequest(), client, authzRequest.getResponseModeEnum());
authorizeRestWebServiceValidator.validate(authzRequest, responseTypes, client);
authorizeRestWebServiceValidator.validatePkce(authzRequest.getCodeChallenge(), redirectUriResponse);

if (StringUtils.isBlank(authzRequest.getAcrValues()) && !ArrayUtils.isEmpty(client.getDefaultAcrValues())) {
Expand Down Expand Up @@ -997,30 +990,6 @@ private void updateSessionForROPC(HttpServletRequest httpRequest, SessionId sess
}
}

private void checkAcrChanged(String acrValuesStr, List<Prompt> prompts, SessionId sessionUser) throws AcrChangedException {
try {
sessionIdService.assertAuthenticatedSessionCorrespondsToNewRequest(sessionUser, acrValuesStr);
} catch (AcrChangedException e) { // Acr changed
//See https://github.com/GluuFederation/oxTrust/issues/797
if (e.isForceReAuthentication()) {
if (!prompts.contains(Prompt.LOGIN)) {
log.info("ACR is changed, adding prompt=login to prompts");
prompts.add(Prompt.LOGIN);

sessionUser.setState(SessionIdState.UNAUTHENTICATED);
sessionUser.getSessionAttributes().put("prompt", implode(prompts, " "));
if (!sessionIdService.persistSessionId(sessionUser)) {
log.trace("Unable persist session_id, trying to update it.");
sessionIdService.updateSessionId(sessionUser);
}
sessionIdService.externalEvent(new SessionEvent(SessionEventType.UNAUTHENTICATED, sessionUser));
}
} else {
throw e;
}
}
}

private Map<String, String> getGenericRequestMap(HttpServletRequest httpRequest) {
Map<String, String> result = new HashMap<>();
for (Entry<String, String[]> entry : httpRequest.getParameterMap().entrySet()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,29 @@
package io.jans.as.server.authorize.ws.rs;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import io.jans.as.common.model.registration.Client;
import io.jans.as.common.util.RedirectUri;
import io.jans.as.model.authorize.AuthorizeErrorResponseType;
import io.jans.as.model.common.Prompt;
import io.jans.as.model.common.ResponseMode;
import io.jans.as.model.configuration.AppConfiguration;
import io.jans.as.model.crypto.signature.SignatureAlgorithm;
import io.jans.as.model.error.ErrorResponseFactory;
import io.jans.as.server.model.authorize.AuthorizeParamsValidator;
import io.jans.as.server.model.authorize.JwtAuthorizationRequest;
import io.jans.as.server.model.common.DeviceAuthorizationCacheControl;
import io.jans.as.server.model.common.SessionId;
import io.jans.as.server.model.common.SessionIdState;
import io.jans.as.server.model.exception.AcrChangedException;
import io.jans.as.server.security.Identity;
import io.jans.as.server.service.ClientService;
import io.jans.as.server.service.DeviceAuthorizationService;
import io.jans.as.server.service.RedirectUriResponse;
import io.jans.as.server.service.RedirectionUriService;
import io.jans.as.server.service.SessionIdService;
import io.jans.as.server.service.external.session.SessionEvent;
import io.jans.as.server.service.external.session.SessionEventType;
import io.jans.as.server.util.RedirectUtil;
import io.jans.as.server.util.ServerUtil;
import io.jans.orm.exception.EntryPersistenceException;
Expand All @@ -46,6 +54,7 @@
import static io.jans.as.model.ciba.BackchannelAuthenticationErrorResponseType.INVALID_REQUEST;
import static io.jans.as.model.crypto.signature.SignatureAlgorithm.NONE;
import static io.jans.as.model.crypto.signature.SignatureAlgorithm.RS256;
import static io.jans.as.model.util.StringUtils.implode;
import static org.apache.commons.lang.BooleanUtils.isTrue;

/**
Expand Down Expand Up @@ -74,6 +83,12 @@ public class AuthorizeRestWebServiceValidator {
@Inject
private AppConfiguration appConfiguration;

@Inject
private SessionIdService sessionIdService;

@Inject
private Identity identity;

public Client validateClient(String clientId, String state) {
return validateClient(clientId, state, false);
}
Expand Down Expand Up @@ -148,23 +163,27 @@ public void validateRequestJwt(String request, String requestUri, RedirectUriRes
}
}

public void validate(List<io.jans.as.model.common.ResponseType> responseTypes, List<Prompt> prompts, String nonce, String state, String redirectUri, HttpServletRequest httpRequest, Client client, io.jans.as.model.common.ResponseMode responseMode) {
if (!AuthorizeParamsValidator.validateParams(responseTypes, prompts, nonce, appConfiguration.isFapi(), responseMode)) {
public void validate(AuthzRequest authzRequest, List<io.jans.as.model.common.ResponseType> responseTypes, Client client) {
final ResponseMode responseMode = authzRequest.getResponseModeEnum();
final String redirectUri = authzRequest.getRedirectUri();
if (!AuthorizeParamsValidator.validateParams(responseTypes, authzRequest.getPromptList(), authzRequest.getNonce(), appConfiguration.isFapi(), responseMode)) {

if (redirectUri != null && redirectionUriService.validateRedirectionUri(client, redirectUri) != null) {
RedirectUri redirectUriResponse = new RedirectUri(redirectUri, responseTypes, responseMode);
redirectUriResponse.parseQueryString(errorResponseFactory.getErrorAsQueryString(
AuthorizeErrorResponseType.INVALID_REQUEST, state));
throw new WebApplicationException(RedirectUtil.getRedirectResponseBuilder(redirectUriResponse, httpRequest).build());
AuthorizeErrorResponseType.INVALID_REQUEST, authzRequest.getState()));
throw new WebApplicationException(RedirectUtil.getRedirectResponseBuilder(redirectUriResponse, authzRequest.getHttpRequest()).build());
} else {
throw new WebApplicationException(Response
.status(Response.Status.BAD_REQUEST.getStatusCode())
.type(MediaType.APPLICATION_JSON_TYPE)
.entity(errorResponseFactory.getErrorAsJson(AuthorizeErrorResponseType.INVALID_REQUEST, state, "Invalid redirect uri."))
.entity(errorResponseFactory.getErrorAsJson(AuthorizeErrorResponseType.INVALID_REQUEST, authzRequest.getState(), "Invalid redirect uri."))
.build());
}
}
}

@SuppressWarnings("java:S3776")
public void validateRequestObject(JwtAuthorizationRequest jwtRequest, RedirectUriResponse redirectUriResponse) {
if (!jwtRequest.getAud().isEmpty() && !jwtRequest.getAud().contains(appConfiguration.getIssuer())) {
log.error("Failed to match aud to AS, aud: {}", jwtRequest.getAud());
Expand Down Expand Up @@ -228,6 +247,7 @@ public void validateRequestObject(JwtAuthorizationRequest jwtRequest, RedirectUr
*
* @param jwtRequest Object to be validated.
*/
@SuppressWarnings("java:S3776")
public void validateCibaRequestObject(JwtAuthorizationRequest jwtRequest, String clientId) {
if (jwtRequest.getAud().isEmpty() || !jwtRequest.getAud().contains(appConfiguration.getIssuer())) {
log.error("Failed to match aud to AS, aud: {}", jwtRequest.getAud());
Expand Down Expand Up @@ -356,4 +376,40 @@ public void validatePkce(String codeChallenge, RedirectUriResponse redirectUriRe
throw redirectUriResponse.createWebException(AuthorizeErrorResponseType.INVALID_REQUEST);
}
}

public void validateAcrs(AuthzRequest authzRequest, Client client, RedirectUriResponse redirectUriResponse) throws AcrChangedException {
if (!client.getAttributes().getAuthorizedAcrValues().isEmpty() &&
!client.getAttributes().getAuthorizedAcrValues().containsAll(authzRequest.getAcrValuesList())) {
throw redirectUriResponse.createWebException(AuthorizeErrorResponseType.INVALID_REQUEST,
"Restricted acr value request, please review the list of authorized acr values for this client");
}
checkAcrChanged(authzRequest, identity.getSessionId()); // check after redirect uri is validated
}


private void checkAcrChanged(AuthzRequest authzRequest, SessionId sessionUser) throws AcrChangedException {
try {
sessionIdService.assertAuthenticatedSessionCorrespondsToNewRequest(sessionUser, authzRequest.getAcrValues());
} catch (AcrChangedException e) { // Acr changed
//See https://github.com/GluuFederation/oxTrust/issues/797
if (e.isForceReAuthentication()) {
final List<Prompt> promptList = Lists.newArrayList(authzRequest.getPromptList());
if (!promptList.contains(Prompt.LOGIN)) {
log.info("ACR is changed, adding prompt=login to prompts");
promptList.add(Prompt.LOGIN);
authzRequest.setPrompt(implode(promptList, " "));

sessionUser.setState(SessionIdState.UNAUTHENTICATED);
sessionUser.getSessionAttributes().put("prompt", authzRequest.getPrompt());
if (!sessionIdService.persistSessionId(sessionUser)) {
log.trace("Unable persist session_id, trying to update it.");
sessionIdService.updateSessionId(sessionUser);
}
sessionIdService.externalEvent(new SessionEvent(SessionEventType.UNAUTHENTICATED, sessionUser));
}
} else {
throw e;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.jans.as.server.authorize.ws.rs;

import io.jans.as.model.common.Prompt;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.ws.rs.core.SecurityContext;
Expand Down Expand Up @@ -118,6 +119,10 @@ public void setDisplay(String display) {
this.display = display;
}

public List<Prompt> getPromptList() {
return Prompt.fromString(prompt, " ");
}

public String getPrompt() {
return prompt;
}
Expand Down

0 comments on commit 2c79951

Please sign in to comment.