diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthorizeRestWebServiceImpl.java b/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthorizeRestWebServiceImpl.java index 8a26e044740..93882e34eb9 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthorizeRestWebServiceImpl.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthorizeRestWebServiceImpl.java @@ -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; @@ -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; @@ -132,7 +130,7 @@ public class AuthorizeRestWebServiceImpl implements AuthorizeRestWebService { private SessionIdService sessionIdService; @Inject - CookieService cookieService; + private CookieService cookieService; @Inject private ScopeChecker scopeChecker; @@ -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 scopes = scopeChecker.checkScopesPolicy(client, authzRequest.getScope()); @@ -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())) { @@ -997,30 +990,6 @@ private void updateSessionForROPC(HttpServletRequest httpRequest, SessionId sess } } - private void checkAcrChanged(String acrValuesStr, List 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 getGenericRequestMap(HttpServletRequest httpRequest) { Map result = new HashMap<>(); for (Entry entry : httpRequest.getParameterMap().entrySet()) { diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthorizeRestWebServiceValidator.java b/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthorizeRestWebServiceValidator.java index 318d2fc76bc..ae8c97da660 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthorizeRestWebServiceValidator.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthorizeRestWebServiceValidator.java @@ -7,10 +7,12 @@ 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; @@ -18,10 +20,16 @@ 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; @@ -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; /** @@ -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); } @@ -148,23 +163,27 @@ public void validateRequestJwt(String request, String requestUri, RedirectUriRes } } - public void validate(List responseTypes, List 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 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()); @@ -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()); @@ -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 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; + } + } + } } diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthzRequest.java b/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthzRequest.java index 1947c152077..b3668b19c17 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthzRequest.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthzRequest.java @@ -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; @@ -118,6 +119,10 @@ public void setDisplay(String display) { this.display = display; } + public List getPromptList() { + return Prompt.fromString(prompt, " "); + } + public String getPrompt() { return prompt; }