From 874846c13e25ca583211634240ed6d1e8a82676b Mon Sep 17 00:00:00 2001 From: YuriyZ Date: Thu, 10 Oct 2024 18:23:22 +0300 Subject: [PATCH] feat(oxauth): first party apps - added validator #1925 https://github.com/GluuFederation/oxAuth/issues/1925 --- .../oxauth/client/AuthorizationResponse.java | 42 +++++---- .../rs/AuthorizationChallengeValidator.java | 89 +++++++++++++++++++ 2 files changed, 112 insertions(+), 19 deletions(-) create mode 100644 Server/src/main/java/org/gluu/oxauth/authorize/ws/rs/AuthorizationChallengeValidator.java diff --git a/Client/src/main/java/org/gluu/oxauth/client/AuthorizationResponse.java b/Client/src/main/java/org/gluu/oxauth/client/AuthorizationResponse.java index 9c40240835..1945b5cd9f 100644 --- a/Client/src/main/java/org/gluu/oxauth/client/AuthorizationResponse.java +++ b/Client/src/main/java/org/gluu/oxauth/client/AuthorizationResponse.java @@ -6,24 +6,6 @@ package org.gluu.oxauth.client; -import static org.gluu.oxauth.model.authorize.AuthorizeResponseParam.ACCESS_TOKEN; -import static org.gluu.oxauth.model.authorize.AuthorizeResponseParam.CODE; -import static org.gluu.oxauth.model.authorize.AuthorizeResponseParam.EXPIRES_IN; -import static org.gluu.oxauth.model.authorize.AuthorizeResponseParam.ID_TOKEN; -import static org.gluu.oxauth.model.authorize.AuthorizeResponseParam.SCOPE; -import static org.gluu.oxauth.model.authorize.AuthorizeResponseParam.SESSION_ID; -import static org.gluu.oxauth.model.authorize.AuthorizeResponseParam.SID; -import static org.gluu.oxauth.model.authorize.AuthorizeResponseParam.STATE; -import static org.gluu.oxauth.model.authorize.AuthorizeResponseParam.TOKEN_TYPE; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import javax.ws.rs.core.Response; - import org.apache.commons.lang.StringUtils; import org.gluu.oxauth.model.authorize.AuthorizeErrorResponseType; import org.gluu.oxauth.model.common.ResponseMode; @@ -32,6 +14,15 @@ import org.json.JSONException; import org.json.JSONObject; +import javax.ws.rs.core.Response; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import static org.gluu.oxauth.model.authorize.AuthorizeResponseParam.*; + /** * Represents an authorization response received from the authorization server. * @@ -52,6 +43,7 @@ public class AuthorizationResponse extends BaseResponse { private Map customParams; private ResponseMode responseMode; + private String errorTypeString; private AuthorizeErrorResponseType errorType; private String errorDescription; private String errorUri; @@ -67,7 +59,8 @@ public AuthorizationResponse(Response clientResponse) { try { JSONObject jsonObj = new JSONObject(entity); if (jsonObj.has("error")) { - errorType = AuthorizeErrorResponseType.fromString(jsonObj.getString("error")); + errorTypeString = jsonObj.getString("error"); + errorType = AuthorizeErrorResponseType.fromString(errorTypeString); } if (jsonObj.has("error_description")) { errorDescription = jsonObj.getString("error_description"); @@ -81,6 +74,9 @@ public AuthorizationResponse(Response clientResponse) { if (jsonObj.has("redirect")) { location = jsonObj.getString("redirect"); } + if (jsonObj.has("authorization_code")) { + code = jsonObj.getString("authorization_code"); + } } catch (JSONException e) { e.printStackTrace(); } @@ -173,6 +169,14 @@ private void processLocation() { } } + public String getErrorTypeString() { + return errorTypeString; + } + + public void setErrorTypeString(String errorTypeString) { + this.errorTypeString = errorTypeString; + } + /** * Returns the authorization code generated by the authorization server. * diff --git a/Server/src/main/java/org/gluu/oxauth/authorize/ws/rs/AuthorizationChallengeValidator.java b/Server/src/main/java/org/gluu/oxauth/authorize/ws/rs/AuthorizationChallengeValidator.java new file mode 100644 index 0000000000..0e24472c82 --- /dev/null +++ b/Server/src/main/java/org/gluu/oxauth/authorize/ws/rs/AuthorizationChallengeValidator.java @@ -0,0 +1,89 @@ +package org.gluu.oxauth.authorize.ws.rs; + +import org.apache.commons.lang.ArrayUtils; +import org.gluu.oxauth.model.authorize.AuthorizeErrorResponseType; +import org.gluu.oxauth.model.common.GrantType; +import org.gluu.oxauth.model.config.Constants; +import org.gluu.oxauth.model.configuration.AppConfiguration; +import org.gluu.oxauth.model.error.ErrorResponseFactory; +import org.gluu.oxauth.model.registration.Client; +import org.gluu.oxauth.service.ScopeService; +import org.slf4j.Logger; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.inject.Named; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +/** + * @author Yuriy Z + */ +@RequestScoped +@Named +public class AuthorizationChallengeValidator { + + @Inject + private Logger log; + + @Inject + private AppConfiguration appConfiguration; + + @Inject + private ErrorResponseFactory errorResponseFactory; + + @Inject + private ScopeService scopeService; + + public void validateGrantType(Client client, String state) { + if (client == null) { + final String msg = "Unable to find client."; + log.debug(msg); + throw new WebApplicationException(errorResponseFactory + .newErrorResponse(Response.Status.BAD_REQUEST) + .entity(errorResponseFactory.getErrorAsJson(AuthorizeErrorResponseType.UNAUTHORIZED_CLIENT, state, msg)) + .build()); + } + + if (client.getGrantTypes() == null || !Arrays.asList(client.getGrantTypes()).contains(GrantType.AUTHORIZATION_CODE)) { + String msg = String.format("Client %s does not support grant_type=authorization_code", client.getClientId()); + log.debug(msg); + throw new WebApplicationException(errorResponseFactory + .newErrorResponse(Response.Status.BAD_REQUEST) + .entity(errorResponseFactory.getErrorAsJson(AuthorizeErrorResponseType.UNAUTHORIZED_CLIENT, state, msg)) + .build()); + } + + final Set grantTypesSupported = appConfiguration.getGrantTypesSupported(); + if (grantTypesSupported == null || !grantTypesSupported.contains(GrantType.AUTHORIZATION_CODE)) { + String msg = "AS configuration does not allow grant_type=authorization_code"; + log.debug(msg); + throw new WebApplicationException(errorResponseFactory + .newErrorResponse(Response.Status.BAD_REQUEST) + .entity(errorResponseFactory.getErrorAsJson(AuthorizeErrorResponseType.UNAUTHORIZED_CLIENT, state, msg)) + .build()); + } + } + + public void validateAccess(Client client) { + if (client == null || ArrayUtils.isEmpty(client.getScopes())) { + log.debug("Client is null or have no scopes defined. Rejected request."); + throw new WebApplicationException( + Response.status(Response.Status.UNAUTHORIZED.getStatusCode()) + .entity(errorResponseFactory.getErrorAsJson(AuthorizeErrorResponseType.INVALID_REQUEST)) + .build()); + } + + List scopesAllowedIds = scopeService.getScopeIdsByDns(Arrays.asList(client.getScopes())); + + if (!scopesAllowedIds.contains(Constants.AUTHORIZATION_CHALLENGE_SCOPE)) { + log.debug("Client does not have required 'authorization_challenge' scope."); + throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED.getStatusCode()) + .entity(errorResponseFactory.getErrorAsJson(AuthorizeErrorResponseType.INVALID_REQUEST)) + .build()); + } + } +}