Search in sources :

Example 96 with Approval

use of org.springframework.security.oauth2.provider.approval.Approval in project uaa by cloudfoundry.

the class UaaAuthorizationEndpoint method authorize.

@RequestMapping(value = "/oauth/authorize")
public ModelAndView authorize(Map<String, Object> model, @RequestParam Map<String, String> parameters, SessionStatus sessionStatus, Principal principal, HttpServletRequest request) {
    ClientDetails client;
    String clientId;
    try {
        clientId = parameters.get("client_id");
        client = loadClientByClientId(clientId);
    } catch (NoSuchClientException x) {
        throw new InvalidClientException(x.getMessage());
    }
    // 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;
    try {
        authorizationRequest = getOAuth2RequestFactory().createAuthorizationRequest(parameters);
    } catch (DisallowedIdpException x) {
        return switchIdp(model, client, clientId, request);
    }
    Set<String> responseTypes = authorizationRequest.getResponseTypes();
    String grantType = deriveGrantTypeFromResponseType(responseTypes);
    if (!supported_response_types.containsAll(responseTypes)) {
        throw new UnsupportedResponseTypeException("Unsupported response types: " + responseTypes);
    }
    if (authorizationRequest.getClientId() == null) {
        throw new InvalidClientException("A client id must be provided");
    }
    String resolvedRedirect = "";
    try {
        String redirectUriParameter = authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI);
        try {
            resolvedRedirect = redirectResolver.resolveRedirect(redirectUriParameter, client);
        } catch (RedirectMismatchException rme) {
            throw new RedirectMismatchException("Invalid redirect " + redirectUriParameter + " did not match one of the registered values");
        }
        if (!StringUtils.hasText(resolvedRedirect)) {
            throw new RedirectMismatchException("A redirectUri must be either supplied or preconfigured in the ClientDetails");
        }
        boolean isAuthenticated = (principal instanceof Authentication) && ((Authentication) principal).isAuthenticated();
        if (!isAuthenticated) {
            throw new InsufficientAuthenticationException("User must be authenticated with Spring Security before authorization can be completed.");
        }
        if (!(responseTypes.size() > 0)) {
            return new ModelAndView(new RedirectView(addQueryParameter(addQueryParameter(resolvedRedirect, "error", "invalid_request"), "error_description", "Missing response_type in authorization request")));
        }
        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);
        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") || responseTypes.contains("id_token")) {
                return getImplicitGrantOrHybridResponse(authorizationRequest, (Authentication) principal, grantType);
            }
            if (responseTypes.contains("code")) {
                return new ModelAndView(getAuthorizationCodeResponse(authorizationRequest, (Authentication) principal));
            }
        }
        if ("none".equals(authorizationRequest.getRequestParameters().get("prompt"))) {
            return new ModelAndView(new RedirectView(addFragmentComponent(resolvedRedirect, "error=interaction_required")));
        } else {
            // 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(AUTHORIZATION_REQUEST, authorizationRequest);
            model.put("original_uri", UrlUtils.buildFullRequestUrl(request));
            model.put(ORIGINAL_AUTHORIZATION_REQUEST, unmodifiableMap(authorizationRequest));
            return getUserApprovalPageResponse(model, authorizationRequest, (Authentication) principal);
        }
    } catch (RedirectMismatchException e) {
        sessionStatus.setComplete();
        throw e;
    } catch (Exception e) {
        sessionStatus.setComplete();
        logger.debug("Unable to handle /oauth/authorize, internal error", e);
        if ("none".equals(authorizationRequest.getRequestParameters().get("prompt"))) {
            return new ModelAndView(new RedirectView(addFragmentComponent(resolvedRedirect, "error=internal_server_error")));
        }
        throw e;
    }
}
Also used : AuthorizationRequest(org.springframework.security.oauth2.provider.AuthorizationRequest) ModelAndView(org.springframework.web.servlet.ModelAndView) InsufficientAuthenticationException(org.springframework.security.authentication.InsufficientAuthenticationException) UnauthorizedClientException(org.springframework.security.oauth2.common.exceptions.UnauthorizedClientException) OAuth2Exception(org.springframework.security.oauth2.common.exceptions.OAuth2Exception) UserDeniedAuthorizationException(org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException) RedirectMismatchException(org.springframework.security.oauth2.common.exceptions.RedirectMismatchException) AuthenticationException(org.springframework.security.core.AuthenticationException) BadClientCredentialsException(org.springframework.security.oauth2.common.exceptions.BadClientCredentialsException) HttpSessionRequiredException(org.springframework.web.HttpSessionRequiredException) InvalidRequestException(org.springframework.security.oauth2.common.exceptions.InvalidRequestException) UnsupportedResponseTypeException(org.springframework.security.oauth2.common.exceptions.UnsupportedResponseTypeException) ClientRegistrationException(org.springframework.security.oauth2.provider.ClientRegistrationException) ClientAuthenticationException(org.springframework.security.oauth2.common.exceptions.ClientAuthenticationException) InvalidClientException(org.springframework.security.oauth2.common.exceptions.InvalidClientException) NoSuchClientException(org.springframework.security.oauth2.provider.NoSuchClientException) IOException(java.io.IOException) AccessDeniedException(org.springframework.security.access.AccessDeniedException) InsufficientAuthenticationException(org.springframework.security.authentication.InsufficientAuthenticationException) InvalidScopeException(org.springframework.security.oauth2.common.exceptions.InvalidScopeException) UnapprovedClientAuthenticationException(org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException) 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) RedirectView(org.springframework.web.servlet.view.RedirectView) UnsupportedResponseTypeException(org.springframework.security.oauth2.common.exceptions.UnsupportedResponseTypeException) NoSuchClientException(org.springframework.security.oauth2.provider.NoSuchClientException) RequestMapping(org.springframework.web.bind.annotation.RequestMapping)

Example 97 with Approval

use of org.springframework.security.oauth2.provider.approval.Approval in project uaa by cloudfoundry.

the class AccessController method confirm.

@RequestMapping("/oauth/confirm_access")
public String confirm(Map<String, Object> model, final HttpServletRequest request, Principal principal, SessionStatus sessionStatus) {
    if (!(principal instanceof Authentication)) {
        sessionStatus.setComplete();
        throw new InsufficientAuthenticationException("User must be authenticated with before authorizing access.");
    }
    AuthorizationRequest clientAuthRequest = (AuthorizationRequest) model.remove(UaaAuthorizationEndpoint.AUTHORIZATION_REQUEST);
    if (clientAuthRequest == null) {
        model.put("error", "No authorization request is present, so we cannot confirm access (we don't know what you are asking for).");
    } else {
        String clientId = clientAuthRequest.getClientId();
        BaseClientDetails client = (BaseClientDetails) clientDetailsService.loadClientByClientId(clientId, IdentityZoneHolder.get().getId());
        BaseClientDetails modifiableClient = new BaseClientDetails(client);
        modifiableClient.setClientSecret(null);
        model.put("auth_request", clientAuthRequest);
        model.put("redirect_uri", getRedirectUri(modifiableClient, clientAuthRequest));
        Map<String, Object> additionalInfo = client.getAdditionalInformation();
        String clientDisplayName = (String) additionalInfo.get(ClientConstants.CLIENT_NAME);
        model.put("client_display_name", (clientDisplayName != null) ? clientDisplayName : clientId);
        // Find the auto approved scopes for this clients
        Set<String> autoApproved = client.getAutoApproveScopes();
        Set<String> autoApprovedScopes = new HashSet<>();
        if (autoApproved != null) {
            if (autoApproved.contains("true")) {
                autoApprovedScopes.addAll(client.getScope());
            } else {
                autoApprovedScopes.addAll(autoApproved);
            }
        }
        List<Approval> filteredApprovals = new ArrayList<Approval>();
        // Remove auto approved scopes
        List<Approval> approvals = approvalStore.getApprovals(Origin.getUserId((Authentication) principal), clientId, IdentityZoneHolder.get().getId());
        for (Approval approval : approvals) {
            if (!(autoApprovedScopes.contains(approval.getScope()))) {
                filteredApprovals.add(approval);
            }
        }
        ArrayList<String> approvedScopes = new ArrayList<String>();
        ArrayList<String> deniedScopes = new ArrayList<String>();
        for (Approval approval : filteredApprovals) {
            switch(approval.getStatus()) {
                case APPROVED:
                    approvedScopes.add(approval.getScope());
                    break;
                case DENIED:
                    deniedScopes.add(approval.getScope());
                    break;
                default:
                    logger.error("Encountered an unknown scope. This is not supposed to happen");
                    break;
            }
        }
        ArrayList<String> undecidedScopes = new ArrayList<String>();
        // Filter the scopes approved/denied from the ones requested
        for (String scope : clientAuthRequest.getScope()) {
            if (!approvedScopes.contains(scope) && !deniedScopes.contains(scope) && !autoApprovedScopes.contains(scope)) {
                undecidedScopes.add(scope);
            }
        }
        List<Map<String, String>> approvedScopeDetails = getScopes(approvedScopes);
        model.put("approved_scopes", approvedScopeDetails);
        List<Map<String, String>> undecidedScopeDetails = getScopes(undecidedScopes);
        model.put("undecided_scopes", undecidedScopeDetails);
        List<Map<String, String>> deniedScopeDetails = getScopes(deniedScopes);
        model.put("denied_scopes", deniedScopeDetails);
        List<Map<String, String>> allScopes = new ArrayList<>();
        allScopes.addAll(approvedScopeDetails);
        allScopes.addAll(undecidedScopeDetails);
        allScopes.addAll(deniedScopeDetails);
        model.put("scopes", allScopes);
        model.put("message", "To confirm or deny access POST to the following locations with the parameters requested.");
        Map<String, Object> options = new HashMap<String, Object>() {

            {
                put("confirm", new HashMap<String, String>() {

                    {
                        put("location", getLocation(request, "oauth/authorize"));
                        put("path", getPath(request, "oauth/authorize"));
                        put("key", OAuth2Utils.USER_OAUTH_APPROVAL);
                        put("value", "true");
                    }
                });
                put("deny", new HashMap<String, String>() {

                    {
                        put("location", getLocation(request, "oauth/authorize"));
                        put("path", getPath(request, "oauth/authorize"));
                        put("key", OAuth2Utils.USER_OAUTH_APPROVAL);
                        put("value", "false");
                    }
                });
            }
        };
        model.put("options", options);
    }
    return "access_confirmation";
}
Also used : BaseClientDetails(org.springframework.security.oauth2.provider.client.BaseClientDetails) AuthorizationRequest(org.springframework.security.oauth2.provider.AuthorizationRequest) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) InsufficientAuthenticationException(org.springframework.security.authentication.InsufficientAuthenticationException) Authentication(org.springframework.security.core.Authentication) Approval(org.cloudfoundry.identity.uaa.approval.Approval) HashMap(java.util.HashMap) Map(java.util.Map) HashSet(java.util.HashSet) RequestMapping(org.springframework.web.bind.annotation.RequestMapping)

Example 98 with Approval

use of org.springframework.security.oauth2.provider.approval.Approval in project uaa by cloudfoundry.

the class UserManagedAuthzApprovalHandler method isApproved.

@Override
public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) {
    String approvalParameter1 = OAuth2Utils.USER_OAUTH_APPROVAL;
    String flag = authorizationRequest.getApprovalParameters().get(approvalParameter1);
    boolean userApproval = flag != null && flag.toLowerCase().equals("true");
    if (logger.isDebugEnabled()) {
        StringBuilder builder = new StringBuilder("Looking up user approved authorizations for ");
        builder.append("client_id=").append(authorizationRequest.getClientId());
        builder.append(" and username=").append(userAuthentication.getName());
        logger.debug(builder.toString());
    }
    Collection<String> requestedScopes = authorizationRequest.getScope();
    // Factor in auto approved scopes
    Set<String> autoApprovedScopes = new HashSet<>();
    BaseClientDetails client = (BaseClientDetails) clientDetailsService.retrieve(authorizationRequest.getClientId(), identityZoneManager.getCurrentIdentityZoneId());
    if (client != null && requestedScopes != null) {
        autoApprovedScopes.addAll(client.getAutoApproveScopes());
        autoApprovedScopes = UaaTokenUtils.retainAutoApprovedScopes(requestedScopes, autoApprovedScopes);
    }
    // TODO: the "true" case is not tested
    if (userApproval) {
        // Store the scopes that have been approved / denied
        Date expiry = computeExpiry();
        // Get the approved scopes, calculate the denied scope
        Map<String, String> approvalParameters = authorizationRequest.getApprovalParameters();
        Set<String> approvedScopes = new HashSet<>(autoApprovedScopes);
        boolean foundUserApprovalParameter = false;
        for (String approvalParameter : approvalParameters.keySet()) {
            if (approvalParameter.startsWith(SCOPE_PREFIX)) {
                approvedScopes.add(approvalParameters.get(approvalParameter).substring(SCOPE_PREFIX.length()));
                foundUserApprovalParameter = true;
            }
        }
        if (foundUserApprovalParameter) {
            authorizationRequest.setScope(approvedScopes);
            for (String requestedScope : requestedScopes) {
                if (approvedScopes.contains(requestedScope)) {
                    Approval approval = new Approval().setUserId(getUserId(userAuthentication)).setClientId(authorizationRequest.getClientId()).setScope(requestedScope).setExpiresAt(expiry).setStatus(APPROVED);
                    approvalStore.addApproval(approval, identityZoneManager.getCurrentIdentityZoneId());
                } else {
                    Approval approval = new Approval().setUserId(getUserId(userAuthentication)).setClientId(authorizationRequest.getClientId()).setScope(requestedScope).setExpiresAt(expiry).setStatus(DENIED);
                    approvalStore.addApproval(approval, identityZoneManager.getCurrentIdentityZoneId());
                }
            }
        } else {
            // Deny all except auto approved scopes
            authorizationRequest.setScope(autoApprovedScopes);
            for (String requestedScope : requestedScopes) {
                if (!autoApprovedScopes.contains(requestedScope)) {
                    Approval approval = new Approval().setUserId(getUserId(userAuthentication)).setClientId(authorizationRequest.getClientId()).setScope(requestedScope).setExpiresAt(expiry).setStatus(DENIED);
                    approvalStore.addApproval(approval, identityZoneManager.getCurrentIdentityZoneId());
                }
            }
        }
        return userAuthentication.isAuthenticated();
    } else {
        // Find the stored approvals for that user and client
        List<Approval> userApprovals = approvalStore.getApprovals(getUserId(userAuthentication), authorizationRequest.getClientId(), identityZoneManager.getCurrentIdentityZoneId());
        // Look at the scopes and see if they have expired
        Set<String> approvedScopes = new HashSet<>(autoApprovedScopes);
        Set<String> validUserApprovedScopes = new HashSet<>(autoApprovedScopes);
        Date today = new Date();
        for (Approval approval : userApprovals) {
            if (approval.getExpiresAt().after(today)) {
                validUserApprovedScopes.add(approval.getScope());
                if (approval.getStatus() == APPROVED) {
                    approvedScopes.add(approval.getScope());
                }
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Valid user approved/denied scopes are " + validUserApprovedScopes);
        }
        // this request is approved
        if (validUserApprovedScopes.containsAll(requestedScopes) && userAuthentication.isAuthenticated()) {
            approvedScopes = UaaTokenUtils.retainAutoApprovedScopes(requestedScopes, approvedScopes);
            // Set only the scopes that have been approved by the user
            authorizationRequest.setScope(approvedScopes);
            return true;
        }
    }
    return false;
}
Also used : BaseClientDetails(org.springframework.security.oauth2.provider.client.BaseClientDetails) Approval(org.cloudfoundry.identity.uaa.approval.Approval)

Example 99 with Approval

use of org.springframework.security.oauth2.provider.approval.Approval in project uaa by cloudfoundry.

the class UserManagedAuthzApprovalHandlerTests method onlySomeRequestedScopeMatchesApproval.

@Test
void onlySomeRequestedScopeMatchesApproval() {
    AuthorizationRequest request = new AuthorizationRequest("foo", new HashSet<>(Arrays.asList("openid", "cloud_controller.read")));
    request.setApproved(false);
    approvalStore.addApproval(new Approval().setUserId(userId).setClientId("foo").setScope("cloud_controller.read").setExpiresAt(nextWeek).setStatus(APPROVED), currentIdentityZoneId);
    approvalStore.addApproval(new Approval().setUserId(userId).setClientId("foo").setScope("cloud_controller.write").setExpiresAt(nextWeek).setStatus(DENIED), currentIdentityZoneId);
    // The request is not approved because the user has not yet approved all
    // the scopes requested
    assertFalse(handler.isApproved(request, mockAuthentication));
}
Also used : AuthorizationRequest(org.springframework.security.oauth2.provider.AuthorizationRequest) Approval(org.cloudfoundry.identity.uaa.approval.Approval) Test(org.junit.jupiter.api.Test)

Example 100 with Approval

use of org.springframework.security.oauth2.provider.approval.Approval in project uaa by cloudfoundry.

the class UserManagedAuthzApprovalHandlerTests method someRequestedScopesMatchApproval.

@Test
void someRequestedScopesMatchApproval() {
    AuthorizationRequest request = new AuthorizationRequest("foo", new HashSet<>(Collections.singletonList("openid")));
    request.setApproved(false);
    approvalStore.addApproval(new Approval().setUserId(userId).setClientId("foo").setScope("openid").setExpiresAt(nextWeek).setStatus(APPROVED), currentIdentityZoneId);
    approvalStore.addApproval(new Approval().setUserId(userId).setClientId("foo").setScope("cloud_controller.read").setExpiresAt(nextWeek).setStatus(APPROVED), currentIdentityZoneId);
    approvalStore.addApproval(new Approval().setUserId(userId).setClientId("foo").setScope("cloud_controller.write").setExpiresAt(nextWeek).setStatus(APPROVED), currentIdentityZoneId);
    // The request is approved because the user has approved all the scopes
    // requested
    assertTrue(handler.isApproved(request, mockAuthentication));
    assertEquals(new HashSet<>(Collections.singletonList("openid")), request.getScope());
}
Also used : AuthorizationRequest(org.springframework.security.oauth2.provider.AuthorizationRequest) Approval(org.cloudfoundry.identity.uaa.approval.Approval) Test(org.junit.jupiter.api.Test)

Aggregations

AuthorizationRequest (org.springframework.security.oauth2.provider.AuthorizationRequest)46 Approval (org.cloudfoundry.identity.uaa.approval.Approval)43 OAuth2AccessToken (org.springframework.security.oauth2.common.OAuth2AccessToken)34 Authentication (org.springframework.security.core.Authentication)27 OAuth2Authentication (org.springframework.security.oauth2.provider.OAuth2Authentication)27 DefaultOAuth2AccessToken (org.springframework.security.oauth2.common.DefaultOAuth2AccessToken)25 Test (org.junit.Test)24 BaseClientDetails (org.springframework.security.oauth2.provider.client.BaseClientDetails)22 Date (java.util.Date)21 Test (org.junit.jupiter.api.Test)19 IsEmptyString.isEmptyString (org.hamcrest.text.IsEmptyString.isEmptyString)16 ClientDetails (org.springframework.security.oauth2.provider.ClientDetails)15 Approval (org.springframework.security.oauth2.provider.approval.Approval)15 LinkedMultiValueMap (org.springframework.util.LinkedMultiValueMap)9 RequestMapping (org.springframework.web.bind.annotation.RequestMapping)9 Map (java.util.Map)8 HashMap (java.util.HashMap)7 BasicCookieStore (org.apache.http.impl.client.BasicCookieStore)7 BasicClientCookie (org.apache.http.impl.cookie.BasicClientCookie)7 AuthorizationCodeResourceDetails (org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails)7