All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.cloudfoundry.identity.uaa.oauth.UserManagedAuthzApprovalHandler Maven / Gradle / Ivy

There is a newer version: 4.30.0
Show newest version
/*******************************************************************************
 *     Cloud Foundry
 *     Copyright (c) [2009-2016] Pivotal Software, Inc. All Rights Reserved.
 *
 *     This product is licensed to you under the Apache License, Version 2.0 (the "License").
 *     You may not use this product except in compliance with the License.
 *
 *     This product includes a number of subcomponents with
 *     separate copyright notices and license terms. Your use of these
 *     subcomponents is subject to the terms and conditions of the
 *     subcomponent's license, as noted in the LICENSE file.
 *******************************************************************************/
package org.cloudfoundry.identity.uaa.oauth;

import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.APPROVED;
import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.DENIED;

import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cloudfoundry.identity.uaa.authentication.Origin;
import org.cloudfoundry.identity.uaa.approval.Approval;
import org.cloudfoundry.identity.uaa.approval.ApprovalStore;
import org.cloudfoundry.identity.uaa.resources.QueryableResourceManager;
import org.cloudfoundry.identity.uaa.util.UaaTokenUtils;
import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;

public class UserManagedAuthzApprovalHandler implements UserApprovalHandler {

    private static final String SCOPE_PREFIX = "scope.";

    private static Log logger = LogFactory.getLog(UserManagedAuthzApprovalHandler.class);

    private final String approvalParameter = OAuth2Utils.USER_OAUTH_APPROVAL;

    private ApprovalStore approvalStore;

    private QueryableResourceManager clientDetailsService;

    private int approvalExpiryInMillis = -1;

    /**
     * @param clientDetailsService the clientDetailsService to set
     */
    public void setClientDetailsService(QueryableResourceManager clientDetailsService) {
        this.clientDetailsService = clientDetailsService;
    }

    public void setApprovalStore(ApprovalStore approvalStore) {
        this.approvalStore = approvalStore;
    }

    @Override
    public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) {

        String flag = authorizationRequest.getApprovalParameters().get(approvalParameter);
        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 requestedScopes = authorizationRequest.getScope();

        // Factor in auto approved scopes
        Set autoApprovedScopes = new HashSet<>();
        BaseClientDetails client = (BaseClientDetails) clientDetailsService.retrieve(authorizationRequest.getClientId(), IdentityZoneHolder.get().getId());
        if (client != null && requestedScopes != null) {
            autoApprovedScopes.addAll(client.getAutoApproveScopes());
            autoApprovedScopes = UaaTokenUtils.retainAutoApprovedScopes(requestedScopes, autoApprovedScopes);
        }
        //translate scope to user scopes - including wild cards

        if (userApproval) {
            // Store the scopes that have been approved / denied
            Date expiry = computeExpiry();

            // Get the approved scopes, calculate the denied scope
            Map approvalParameters = authorizationRequest.getApprovalParameters();
            Set approvedScopes = new HashSet<>();
            approvedScopes.addAll(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, IdentityZoneHolder.get().getId());
                    }
                    else {
                        Approval approval = new Approval()
                            .setUserId(getUserId(userAuthentication))
                            .setClientId(authorizationRequest.getClientId())
                            .setScope(requestedScope)
                            .setExpiresAt(expiry)
                            .setStatus(DENIED);
                        approvalStore.addApproval(approval, IdentityZoneHolder.get().getId());
                    }
                }

            }
            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, IdentityZoneHolder.get().getId());
                    }
                }
            }

            if (userAuthentication.isAuthenticated()) {
                return true;
            }

        } else {
            // Find the stored approvals for that user and client
            List userApprovals = approvalStore.getApprovals(getUserId(userAuthentication), authorizationRequest.getClientId(), IdentityZoneHolder.get().getId());

            // Look at the scopes and see if they have expired
            Set validUserApprovedScopes = new HashSet<>();
            Set approvedScopes = new HashSet<>();
            approvedScopes.addAll(autoApprovedScopes);
            validUserApprovedScopes.addAll(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);
            }

            // If the requested scopes have already been acted upon by the user,
            // 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;
    }

    protected String getUserId(Authentication authentication) {
        return Origin.getUserId(authentication);
    }

    private Date computeExpiry() {
        Calendar expiresAt = Calendar.getInstance();
        if (approvalExpiryInMillis == -1) { // use default of 1 month
            expiresAt.add(Calendar.MONTH, 1);
        }
        else {
            expiresAt.add(Calendar.MILLISECOND, approvalExpiryInMillis);
        }
        return expiresAt.getTime();
    }

    public void setApprovalExpiryInSeconds(int approvalExpirySeconds) {
        this.approvalExpiryInMillis = approvalExpirySeconds * 1000;
    }

    @Override
    public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) {
        return authorizationRequest;
    }

    @Override
    public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) {
        return authorizationRequest;
    }

    @Override
    public Map getUserApprovalRequest(AuthorizationRequest authorizationRequest, Authentication userAuthentication) {
        Map model = new HashMap();
        model.putAll(authorizationRequest.getRequestParameters());
        return model;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy