OAuth2/OIDC authorization endpoint needs to return errors to the client with the redirect URI unless it is invalid
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/9ea9fac6 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/9ea9fac6 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/9ea9fac6 Branch: refs/heads/master-jaxrs-2.1 Commit: 9ea9fac627efc1255d0ad7723ba1025917b7b37b Parents: d243c99 Author: Sergey Beryozkin <[email protected]> Authored: Wed May 25 14:26:51 2016 +0100 Committer: Sergey Beryozkin <[email protected]> Committed: Wed May 25 14:26:51 2016 +0100 ---------------------------------------------------------------------- .../services/RedirectionBasedGrantService.java | 79 ++++++++++---------- .../oidc/idp/OidcAuthorizationCodeService.java | 7 +- .../security/oidc/idp/OidcImplicitService.java | 9 ++- 3 files changed, 50 insertions(+), 45 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/9ea9fac6/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java index 8e45c36..92f7c1c 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java @@ -38,7 +38,6 @@ import org.apache.cxf.common.util.StringUtils; import org.apache.cxf.jaxrs.utils.ExceptionUtils; import org.apache.cxf.rs.security.oauth2.common.Client; import org.apache.cxf.rs.security.oauth2.common.OAuthAuthorizationData; -import org.apache.cxf.rs.security.oauth2.common.OAuthError; import org.apache.cxf.rs.security.oauth2.common.OAuthPermission; import org.apache.cxf.rs.security.oauth2.common.OAuthRedirectionState; import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken; @@ -126,20 +125,21 @@ public abstract class RedirectionBasedGrantService extends AbstractOAuthService Client client = getClient(params); // Create a UserSubject representing the end user UserSubject userSubject = createUserSubject(sc, params); - return startAuthorization(params, userSubject, client); - } - - protected Response startAuthorization(MultivaluedMap<String, String> params, - UserSubject userSubject, - Client client) { if (authorizationFilter != null) { params = authorizationFilter.process(params, userSubject, client); } - // Validate the provided request URI, if any, against the ones Client provided // during the registration - String redirectUri = validateRedirectUri(client, params.getFirst(OAuthConstants.REDIRECT_URI)); + String redirectUri = validateRedirectUri(client, params.getFirst(OAuthConstants.REDIRECT_URI)); + + return startAuthorization(params, userSubject, client, redirectUri); + } + + protected Response startAuthorization(MultivaluedMap<String, String> params, + UserSubject userSubject, + Client client, + String redirectUri) { // Enforce the client confidentiality requirements if (!OAuthUtils.isGrantSupportedForClient(client, canSupportPublicClient(client), supportedGrantType)) { @@ -156,30 +156,25 @@ public abstract class RedirectionBasedGrantService extends AbstractOAuthService // Get the requested scopes String providedScope = params.getFirst(OAuthConstants.SCOPE); List<String> requestedScope = null; + List<OAuthPermission> requestedPermissions = null; try { requestedScope = OAuthUtils.getRequestedScopes(client, providedScope, useAllClientScopes, partialMatchScopeValidation); - } catch (OAuthServiceException ex) { - LOG.log(Level.FINE, "Error parsing scopes", ex); - return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_SCOPE); - } - // Convert the requested scopes to OAuthPermission instances - List<OAuthPermission> requestedPermissions = null; - try { requestedPermissions = getDataProvider().convertScopeToPermissions(client, requestedScope); } catch (OAuthServiceException ex) { - LOG.log(Level.FINE, "Error converting scopes into OAuthPermissions", ex); + LOG.log(Level.FINE, "Error processing scopes", ex); return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_SCOPE); } + // Validate the audience String clientAudience = params.getFirst(OAuthConstants.CLIENT_AUDIENCE); // Right now if the audience parameter is set it is expected to be contained // in the list of Client audiences set at the Client registration time. if (!OAuthUtils.validateAudience(clientAudience, client.getRegisteredAudiences())) { LOG.fine("Error validating audience parameter"); - throw new OAuthServiceException(new OAuthError(OAuthConstants.INVALID_REQUEST)); + return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_REQUEST); } // Request a new grant only if no pre-authorized token is available @@ -199,31 +194,39 @@ public abstract class RedirectionBasedGrantService extends AbstractOAuthService preAuthorizedToken = null; } } - final boolean authorizationCanBeSkipped = preAuthorizationComplete - || canAuthorizationBeSkipped(params, client, userSubject, requestedScope, requestedPermissions); - - // Populate the authorization challenge data - OAuthAuthorizationData data = - createAuthorizationData(client, params, redirectUri, userSubject, - requestedPermissions, - alreadyAuthorizedPerms, - authorizationCanBeSkipped); - if (authorizationCanBeSkipped) { - getMessageContext().put(AUTHORIZATION_REQUEST_PARAMETERS, params); - List<OAuthPermission> approvedScopes = - preAuthorizationComplete ? preAuthorizedToken.getScopes() : requestedPermissions; - return createGrant(data, - client, - requestedScope, - OAuthUtils.convertPermissionsToScopeList(approvedScopes), - userSubject, - preAuthorizedToken); + Response finalResponse = null; + try { + final boolean authorizationCanBeSkipped = preAuthorizationComplete + || canAuthorizationBeSkipped(params, client, userSubject, requestedScope, requestedPermissions); + + // Populate the authorization challenge data + OAuthAuthorizationData data = createAuthorizationData(client, params, redirectUri, userSubject, + requestedPermissions, + alreadyAuthorizedPerms, + authorizationCanBeSkipped); + + if (authorizationCanBeSkipped) { + getMessageContext().put(AUTHORIZATION_REQUEST_PARAMETERS, params); + List<OAuthPermission> approvedScopes = + preAuthorizationComplete ? preAuthorizedToken.getScopes() : requestedPermissions; + finalResponse = createGrant(data, + client, + requestedScope, + OAuthUtils.convertPermissionsToScopeList(approvedScopes), + userSubject, + preAuthorizedToken); + } else { + finalResponse = Response.ok(data).build(); + } + } catch (OAuthServiceException ex) { + finalResponse = createErrorResponse(params, redirectUri, ex.getError().getError()); } - return Response.ok(data).build(); + return finalResponse; } + //CHECKSTYLE:OFF public Set<String> getSupportedResponseTypes() { return supportedResponseTypes; http://git-wip-us.apache.org/repos/asf/cxf/blob/9ea9fac6/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/OidcAuthorizationCodeService.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/OidcAuthorizationCodeService.java b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/OidcAuthorizationCodeService.java index 519361c..e44c526 100644 --- a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/OidcAuthorizationCodeService.java +++ b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/OidcAuthorizationCodeService.java @@ -67,15 +67,16 @@ public class OidcAuthorizationCodeService extends AuthorizationCodeGrantService @Override protected Response startAuthorization(MultivaluedMap<String, String> params, UserSubject userSubject, - Client client) { + Client client, + String redirectUri) { // Validate the prompt - if it contains "none" then an error is returned with any other value List<String> promptValues = OidcUtils.getPromptValues(params); if (promptValues != null && promptValues.size() > 1 && promptValues.contains(OidcUtils.PROMPT_NONE_VALUE)) { LOG.log(Level.FINE, "The prompt value {} is invalid", params.getFirst(OidcUtils.PROMPT_PARAMETER)); - throw new OAuthServiceException(new OAuthError(OAuthConstants.INVALID_REQUEST)); + return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_REQUEST); } - return super.startAuthorization(params, userSubject, client); + return super.startAuthorization(params, userSubject, client, redirectUri); } @Override http://git-wip-us.apache.org/repos/asf/cxf/blob/9ea9fac6/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/OidcImplicitService.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/OidcImplicitService.java b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/OidcImplicitService.java index 03f626f..b5b2a6c 100644 --- a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/OidcImplicitService.java +++ b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/OidcImplicitService.java @@ -68,21 +68,22 @@ public class OidcImplicitService extends ImplicitGrantService { @Override protected Response startAuthorization(MultivaluedMap<String, String> params, UserSubject userSubject, - Client client) { + Client client, + String redirectUri) { // Validate the nonce, it must be present for the Implicit flow if (params.getFirst(OAuthConstants.NONCE) == null) { LOG.fine("A nonce is required for the Implicit flow"); - throw new OAuthServiceException(new OAuthError(OAuthConstants.INVALID_REQUEST)); + return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_REQUEST); } // Validate the prompt - if it contains "none" then an error is returned with any other value List<String> promptValues = OidcUtils.getPromptValues(params); if (promptValues.size() > 1 && promptValues.contains(OidcUtils.PROMPT_NONE_VALUE)) { LOG.log(Level.FINE, "The prompt value {} is invalid", params.getFirst(OidcUtils.PROMPT_PARAMETER)); - throw new OAuthServiceException(new OAuthError(OAuthConstants.INVALID_REQUEST)); + return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_REQUEST); } - return super.startAuthorization(params, userSubject, client); + return super.startAuthorization(params, userSubject, client, redirectUri); } @Override
