Search in sources :

Example 1 with RedirectMismatchException

use of org.springframework.security.oauth2.common.exceptions.RedirectMismatchException in project spring-security-oauth by spring-projects.

the class AuthorizationEndpoint method authorize.

@RequestMapping(value = "/oauth/authorize")
public ModelAndView authorize(Map<String, Object> model, @RequestParam Map<String, String> parameters, SessionStatus sessionStatus, Principal principal) {
    // Pull out the authorization request first, using the OAuth2RequestFactory. All further logic should
    // query off of the authorization request instead of referring back to the parameters map. The contents of the
    // parameters map will be stored without change in the AuthorizationRequest object once it is created.
    AuthorizationRequest authorizationRequest = getOAuth2RequestFactory().createAuthorizationRequest(parameters);
    Set<String> responseTypes = authorizationRequest.getResponseTypes();
    if (!responseTypes.contains("token") && !responseTypes.contains("code")) {
        throw new UnsupportedResponseTypeException("Unsupported response types: " + responseTypes);
    }
    if (authorizationRequest.getClientId() == null) {
        throw new InvalidClientException("A client id must be provided");
    }
    try {
        if (!(principal instanceof Authentication) || !((Authentication) principal).isAuthenticated()) {
            throw new InsufficientAuthenticationException("User must be authenticated with Spring Security before authorization can be completed.");
        }
        ClientDetails client = getClientDetailsService().loadClientByClientId(authorizationRequest.getClientId());
        // The resolved redirect URI is either the redirect_uri from the parameters or the one from
        // clientDetails. Either way we need to store it on the AuthorizationRequest.
        String redirectUriParameter = authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI);
        String resolvedRedirect = redirectResolver.resolveRedirect(redirectUriParameter, client);
        if (!StringUtils.hasText(resolvedRedirect)) {
            throw new RedirectMismatchException("A redirectUri must be either supplied or preconfigured in the ClientDetails");
        }
        authorizationRequest.setRedirectUri(resolvedRedirect);
        // We intentionally only validate the parameters requested by the client (ignoring any data that may have
        // been added to the request by the manager).
        oauth2RequestValidator.validateScope(authorizationRequest, client);
        // Some systems may allow for approval decisions to be remembered or approved by default. Check for
        // such logic here, and set the approved flag on the authorization request accordingly.
        authorizationRequest = userApprovalHandler.checkForPreApproval(authorizationRequest, (Authentication) principal);
        // TODO: is this call necessary?
        boolean approved = userApprovalHandler.isApproved(authorizationRequest, (Authentication) principal);
        authorizationRequest.setApproved(approved);
        // Validation is all done, so we can check for auto approval...
        if (authorizationRequest.isApproved()) {
            if (responseTypes.contains("token")) {
                return getImplicitGrantResponse(authorizationRequest);
            }
            if (responseTypes.contains("code")) {
                return new ModelAndView(getAuthorizationCodeResponse(authorizationRequest, (Authentication) principal));
            }
        }
        // Place auth request into the model so that it is stored in the session
        // for approveOrDeny to use. That way we make sure that auth request comes from the session,
        // so any auth request parameters passed to approveOrDeny will be ignored and retrieved from the session.
        model.put("authorizationRequest", authorizationRequest);
        return getUserApprovalPageResponse(model, authorizationRequest, (Authentication) principal);
    } catch (RuntimeException e) {
        sessionStatus.setComplete();
        throw e;
    }
}
Also used : AuthorizationRequest(org.springframework.security.oauth2.provider.AuthorizationRequest) ClientDetails(org.springframework.security.oauth2.provider.ClientDetails) OAuth2Authentication(org.springframework.security.oauth2.provider.OAuth2Authentication) Authentication(org.springframework.security.core.Authentication) InvalidClientException(org.springframework.security.oauth2.common.exceptions.InvalidClientException) RedirectMismatchException(org.springframework.security.oauth2.common.exceptions.RedirectMismatchException) ModelAndView(org.springframework.web.servlet.ModelAndView) UnsupportedResponseTypeException(org.springframework.security.oauth2.common.exceptions.UnsupportedResponseTypeException) InsufficientAuthenticationException(org.springframework.security.authentication.InsufficientAuthenticationException) RequestMapping(org.springframework.web.bind.annotation.RequestMapping)

Example 2 with RedirectMismatchException

use of org.springframework.security.oauth2.common.exceptions.RedirectMismatchException in project spring-security-oauth by spring-projects.

the class AuthorizationCodeTokenGranter method getOAuth2Authentication.

@Override
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
    Map<String, String> parameters = tokenRequest.getRequestParameters();
    String authorizationCode = parameters.get("code");
    String redirectUri = parameters.get(OAuth2Utils.REDIRECT_URI);
    if (authorizationCode == null) {
        throw new InvalidRequestException("An authorization code must be supplied.");
    }
    OAuth2Authentication storedAuth = authorizationCodeServices.consumeAuthorizationCode(authorizationCode);
    if (storedAuth == null) {
        throw new InvalidGrantException("Invalid authorization code: " + authorizationCode);
    }
    OAuth2Request pendingOAuth2Request = storedAuth.getOAuth2Request();
    // https://jira.springsource.org/browse/SECOAUTH-333
    // This might be null, if the authorization was done without the redirect_uri parameter
    String redirectUriApprovalParameter = pendingOAuth2Request.getRequestParameters().get(OAuth2Utils.REDIRECT_URI);
    if ((redirectUri != null || redirectUriApprovalParameter != null) && !pendingOAuth2Request.getRedirectUri().equals(redirectUri)) {
        throw new RedirectMismatchException("Redirect URI mismatch.");
    }
    String pendingClientId = pendingOAuth2Request.getClientId();
    String clientId = tokenRequest.getClientId();
    if (clientId != null && !clientId.equals(pendingClientId)) {
        // just a sanity check.
        throw new InvalidClientException("Client ID mismatch");
    }
    // Secret is not required in the authorization request, so it won't be available
    // in the pendingAuthorizationRequest. We do want to check that a secret is provided
    // in the token request, but that happens elsewhere.
    Map<String, String> combinedParameters = new HashMap<String, String>(pendingOAuth2Request.getRequestParameters());
    // Combine the parameters adding the new ones last so they override if there are any clashes
    combinedParameters.putAll(parameters);
    // Make a new stored request with the combined parameters
    OAuth2Request finalStoredOAuth2Request = pendingOAuth2Request.createOAuth2Request(combinedParameters);
    Authentication userAuth = storedAuth.getUserAuthentication();
    return new OAuth2Authentication(finalStoredOAuth2Request, userAuth);
}
Also used : OAuth2Request(org.springframework.security.oauth2.provider.OAuth2Request) HashMap(java.util.HashMap) OAuth2Authentication(org.springframework.security.oauth2.provider.OAuth2Authentication) Authentication(org.springframework.security.core.Authentication) OAuth2Authentication(org.springframework.security.oauth2.provider.OAuth2Authentication) RedirectMismatchException(org.springframework.security.oauth2.common.exceptions.RedirectMismatchException) InvalidClientException(org.springframework.security.oauth2.common.exceptions.InvalidClientException) InvalidRequestException(org.springframework.security.oauth2.common.exceptions.InvalidRequestException) InvalidGrantException(org.springframework.security.oauth2.common.exceptions.InvalidGrantException)

Example 3 with RedirectMismatchException

use of org.springframework.security.oauth2.common.exceptions.RedirectMismatchException in project ORCID-Source by ORCID.

the class OauthLoginController method authenticateAndAuthorize.

@RequestMapping(value = { "/oauth/custom/signin.json", "/oauth/custom/login.json" }, method = RequestMethod.POST)
@ResponseBody
public OauthAuthorizeForm authenticateAndAuthorize(HttpServletRequest request, HttpServletResponse response, @RequestBody OauthAuthorizeForm form) {
    // Clean form errors
    form.setErrors(new ArrayList<String>());
    RequestInfoForm requestInfoForm = (RequestInfoForm) request.getSession().getAttribute(REQUEST_INFO_FORM);
    boolean willBeRedirected = false;
    if (form.getApproved()) {
        // Validate name and password
        validateUserNameAndPassword(form);
        if (form.getErrors().isEmpty()) {
            try {
                // Authenticate user
                copy2FAFields(form, request);
                Authentication auth = authenticateUser(request, form.getUserName().getValue(), form.getPassword().getValue());
                profileEntityManager.updateLastLoginDetails(auth.getName(), OrcidRequestUtil.getIpAddress(request));
                // Create authorization params
                SimpleSessionStatus status = new SimpleSessionStatus();
                Map<String, Object> model = new HashMap<String, Object>();
                Map<String, String> params = new HashMap<String, String>();
                Map<String, String> approvalParams = new HashMap<String, String>();
                fillOauthParams(requestInfoForm, params, approvalParams, form.getPersistentTokenEnabled(), form.isEmailAccessAllowed());
                // Authorize
                try {
                    authorizationEndpoint.authorize(model, params, status, auth);
                } catch (RedirectMismatchException rUriError) {
                    String redirectUri = this.getBaseUri() + REDIRECT_URI_ERROR;
                    // Set the client id
                    redirectUri = redirectUri.replace("{0}", requestInfoForm.getClientId());
                    // Set the response type if needed
                    if (!PojoUtil.isEmpty(requestInfoForm.getResponseType()))
                        redirectUri += "&response_type=" + requestInfoForm.getResponseType();
                    // Set the redirect uri
                    if (!PojoUtil.isEmpty(requestInfoForm.getRedirectUrl()))
                        redirectUri += "&redirect_uri=" + requestInfoForm.getRedirectUrl();
                    // Set the scope param
                    if (!PojoUtil.isEmpty(requestInfoForm.getScopesAsString()))
                        redirectUri += "&scope=" + requestInfoForm.getScopesAsString();
                    // Copy the state param if present
                    if (!PojoUtil.isEmpty(requestInfoForm.getStateParam()))
                        redirectUri += "&state=" + requestInfoForm.getStateParam();
                    form.setRedirectUrl(redirectUri);
                    LOGGER.info("OauthLoginController being sent to client browser: " + form.getRedirectUrl());
                    return form;
                }
                // Approve
                RedirectView view = (RedirectView) authorizationEndpoint.approveOrDeny(approvalParams, model, status, auth);
                form.setRedirectUrl(view.getUrl());
                willBeRedirected = true;
            } catch (AuthenticationException ae) {
                if (ae.getCause() instanceof DisabledException) {
                    // Handle this message in angular to allow AJAX action
                    form.getErrors().add("orcid.frontend.security.orcid_deactivated");
                } else if (ae.getCause() instanceof UnclaimedProfileExistsException) {
                    String email = PojoUtil.isEmpty(form.getUserName()) ? null : form.getUserName().getValue();
                    String resendEmailUrl = createResendClaimUrl(email, request);
                    String errorMessage = getMessage("orcid.frontend.security.unclaimed_exists_1");
                    errorMessage += "<a href=\"" + resendEmailUrl + "\">";
                    errorMessage += getMessage("orcid.frontend.security.unclaimed_exists_2");
                    errorMessage += "</a>" + getMessage("orcid.frontend.security.unclaimed_exists_3");
                    form.getErrors().add(errorMessage);
                } else if (ae instanceof VerificationCodeFor2FARequiredException) {
                    form.setVerificationCodeRequired(true);
                } else if (ae instanceof Bad2FAVerificationCodeException) {
                    form.getErrors().add(getMessage("orcid.frontend.security.2fa.bad_verification_code"));
                } else if (ae instanceof Bad2FARecoveryCodeException) {
                    form.getErrors().add(getMessage("orcid.frontend.security.2fa.bad_recovery_code"));
                } else {
                    form.getErrors().add(getMessage("orcid.frontend.security.bad_credentials"));
                }
            }
        }
    } else {
        form.setRedirectUrl(buildDenyRedirectUri(requestInfoForm.getRedirectUrl(), requestInfoForm.getStateParam()));
        willBeRedirected = true;
    }
    // not be redirected yet
    if (willBeRedirected) {
        if (new HttpSessionRequestCache().getRequest(request, response) != null)
            new HttpSessionRequestCache().removeRequest(request, response);
        LOGGER.info("OauthConfirmAccessController form.getRedirectUri being sent to client browser: " + requestInfoForm.getRedirectUrl());
    }
    return form;
}
Also used : HashMap(java.util.HashMap) AuthenticationException(org.springframework.security.core.AuthenticationException) DisabledException(org.springframework.security.authentication.DisabledException) HttpSessionRequestCache(org.springframework.security.web.savedrequest.HttpSessionRequestCache) Bad2FAVerificationCodeException(org.orcid.frontend.web.exception.Bad2FAVerificationCodeException) UnclaimedProfileExistsException(org.orcid.core.security.UnclaimedProfileExistsException) VerificationCodeFor2FARequiredException(org.orcid.frontend.web.exception.VerificationCodeFor2FARequiredException) Bad2FARecoveryCodeException(org.orcid.frontend.web.exception.Bad2FARecoveryCodeException) Authentication(org.springframework.security.core.Authentication) RedirectMismatchException(org.springframework.security.oauth2.common.exceptions.RedirectMismatchException) RedirectView(org.springframework.web.servlet.view.RedirectView) RequestInfoForm(org.orcid.pojo.ajaxForm.RequestInfoForm) SimpleSessionStatus(org.springframework.web.bind.support.SimpleSessionStatus) RequestMapping(org.springframework.web.bind.annotation.RequestMapping) ResponseBody(org.springframework.web.bind.annotation.ResponseBody)

Example 4 with RedirectMismatchException

use of org.springframework.security.oauth2.common.exceptions.RedirectMismatchException in project spring-security-oauth by spring-projects.

the class AuthorizationCodeProviderTests method testWrongRedirectUri.

@Test
@OAuth2ContextConfiguration(resource = MyLessTrustedClient.class, initialize = false)
public void testWrongRedirectUri() throws Exception {
    approveAccessTokenGrant("http://anywhere", true);
    AccessTokenRequest request = context.getAccessTokenRequest();
    // The redirect is stored in the preserved state...
    context.getOAuth2ClientContext().setPreservedState(request.getStateKey(), "http://nowhere");
    // Finally everything is in place for the grant to happen...
    try {
        assertNotNull(context.getAccessToken());
        fail("Expected RedirectMismatchException");
    } catch (RedirectMismatchException e) {
    // expected
    }
    assertEquals(HttpStatus.BAD_REQUEST, tokenEndpointResponse.getStatusCode());
}
Also used : RedirectMismatchException(org.springframework.security.oauth2.common.exceptions.RedirectMismatchException) AccessTokenRequest(org.springframework.security.oauth2.client.token.AccessTokenRequest) OAuth2ContextConfiguration(org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration) Test(org.junit.Test)

Example 5 with RedirectMismatchException

use of org.springframework.security.oauth2.common.exceptions.RedirectMismatchException in project spring-security-oauth by spring-projects.

the class AuthorizationEndpoint method handleException.

private ModelAndView handleException(Exception e, ServletWebRequest webRequest) throws Exception {
    ResponseEntity<OAuth2Exception> translate = getExceptionTranslator().translate(e);
    webRequest.getResponse().setStatus(translate.getStatusCode().value());
    if (e instanceof ClientAuthenticationException || e instanceof RedirectMismatchException) {
        return new ModelAndView(errorPage, Collections.singletonMap("error", translate.getBody()));
    }
    AuthorizationRequest authorizationRequest = null;
    try {
        authorizationRequest = getAuthorizationRequestForError(webRequest);
        String requestedRedirectParam = authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI);
        String requestedRedirect = redirectResolver.resolveRedirect(requestedRedirectParam, getClientDetailsService().loadClientByClientId(authorizationRequest.getClientId()));
        authorizationRequest.setRedirectUri(requestedRedirect);
        String redirect = getUnsuccessfulRedirect(authorizationRequest, translate.getBody(), authorizationRequest.getResponseTypes().contains("token"));
        return new ModelAndView(new RedirectView(redirect, false, true, false));
    } catch (OAuth2Exception ex) {
        // response.
        return new ModelAndView(errorPage, Collections.singletonMap("error", translate.getBody()));
    }
}
Also used : ClientAuthenticationException(org.springframework.security.oauth2.common.exceptions.ClientAuthenticationException) UnapprovedClientAuthenticationException(org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException) AuthorizationRequest(org.springframework.security.oauth2.provider.AuthorizationRequest) RedirectMismatchException(org.springframework.security.oauth2.common.exceptions.RedirectMismatchException) ModelAndView(org.springframework.web.servlet.ModelAndView) RedirectView(org.springframework.web.servlet.view.RedirectView) OAuth2Exception(org.springframework.security.oauth2.common.exceptions.OAuth2Exception)

Aggregations

RedirectMismatchException (org.springframework.security.oauth2.common.exceptions.RedirectMismatchException)9 Authentication (org.springframework.security.core.Authentication)6 HashMap (java.util.HashMap)4 OAuth2Authentication (org.springframework.security.oauth2.provider.OAuth2Authentication)4 Test (org.junit.Test)3 InvalidClientException (org.springframework.security.oauth2.common.exceptions.InvalidClientException)3 OAuth2Request (org.springframework.security.oauth2.provider.OAuth2Request)3 RequestMapping (org.springframework.web.bind.annotation.RequestMapping)3 RedirectView (org.springframework.web.servlet.view.RedirectView)3 RequestInfoForm (org.orcid.pojo.ajaxForm.RequestInfoForm)2 OAuth2ContextConfiguration (org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration)2 AccessTokenRequest (org.springframework.security.oauth2.client.token.AccessTokenRequest)2 InvalidGrantException (org.springframework.security.oauth2.common.exceptions.InvalidGrantException)2 OAuth2Exception (org.springframework.security.oauth2.common.exceptions.OAuth2Exception)2 AuthorizationRequest (org.springframework.security.oauth2.provider.AuthorizationRequest)2 HttpSessionRequestCache (org.springframework.security.web.savedrequest.HttpSessionRequestCache)2 ResponseBody (org.springframework.web.bind.annotation.ResponseBody)2 SimpleSessionStatus (org.springframework.web.bind.support.SimpleSessionStatus)2 ModelAndView (org.springframework.web.servlet.ModelAndView)2 Calendar (java.util.Calendar)1