org.springframework.security.oauth2.provider.approval.ApprovalStoreUserApprovalHandler Maven / Gradle / Ivy
Show all versions of spring-security-oauth2 Show documentation
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.oauth2.provider.approval;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
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.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus;
import org.springframework.util.Assert;
/**
* A user approval handler that remembers approval decisions by consulting existing approvals.
*
*
* @deprecated See the OAuth 2.0 Migration Guide for Spring Security 5.
*
* @author Dave Syer
*
*/
@Deprecated
public class ApprovalStoreUserApprovalHandler implements UserApprovalHandler, InitializingBean {
private static Log logger = LogFactory.getLog(ApprovalStoreUserApprovalHandler.class);
private String scopePrefix = OAuth2Utils.SCOPE_PREFIX;
private ApprovalStore approvalStore;
private int approvalExpirySeconds = -1;
private ClientDetailsService clientDetailsService;
/**
* Service to load client details (optional) for auto approval checks.
*
* @param clientDetailsService a client details service
*/
public void setClientDetailsService(ClientDetailsService clientDetailsService) {
this.clientDetailsService = clientDetailsService;
}
/**
* The prefix applied to incoming parameters that signal approval or denial of a scope.
*
* @param scopePrefix the prefix (default {@link OAuth2Utils#SCOPE_PREFIX})
*/
public void setScopePrefix(String scopePrefix) {
this.scopePrefix = scopePrefix;
}
/**
* @param store the approval to set
*/
public void setApprovalStore(ApprovalStore store) {
this.approvalStore = store;
}
private OAuth2RequestFactory requestFactory;
public void setRequestFactory(OAuth2RequestFactory requestFactory) {
this.requestFactory = requestFactory;
}
public void setApprovalExpiryInSeconds(int approvalExpirySeconds) {
this.approvalExpirySeconds = approvalExpirySeconds;
}
public void afterPropertiesSet() {
Assert.state(approvalStore != null, "ApprovalStore must be provided");
Assert.state(requestFactory != null, "OAuth2RequestFactory must be provided");
}
public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) {
return authorizationRequest.isApproved();
}
public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest,
Authentication userAuthentication) {
String clientId = authorizationRequest.getClientId();
Collection requestedScopes = authorizationRequest.getScope();
Set approvedScopes = new HashSet();
Set validUserApprovedScopes = new HashSet();
if (clientDetailsService != null) {
try {
ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
for (String scope : requestedScopes) {
if (client.isAutoApprove(scope)) {
approvedScopes.add(scope);
}
}
if (approvedScopes.containsAll(requestedScopes)) {
// gh-877 - if all scopes are auto approved, approvals still need to be added to the approval store.
Set approvals = new HashSet();
Date expiry = computeExpiry();
for (String approvedScope : approvedScopes) {
approvals.add(new Approval(userAuthentication.getName(), authorizationRequest.getClientId(),
approvedScope, expiry, ApprovalStatus.APPROVED));
}
approvalStore.addApprovals(approvals);
authorizationRequest.setApproved(true);
return authorizationRequest;
}
}
catch (ClientRegistrationException e) {
logger.warn("Client registration problem prevent autoapproval check for client=" + clientId);
}
}
if (logger.isDebugEnabled()) {
StringBuilder builder = new StringBuilder("Looking up user approved authorizations for ");
builder.append("client_id=" + clientId);
builder.append(" and username=" + userAuthentication.getName());
logger.debug(builder.toString());
}
// Find the stored approvals for that user and client
Collection userApprovals = approvalStore.getApprovals(userAuthentication.getName(), clientId);
// Look at the scopes and see if they have expired
Date today = new Date();
for (Approval approval : userApprovals) {
if (approval.getExpiresAt().after(today)) {
if (approval.getStatus() == ApprovalStatus.APPROVED) {
validUserApprovedScopes.add(approval.getScope());
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)) {
approvedScopes.retainAll(requestedScopes);
// Set only the scopes that have been approved by the user
authorizationRequest.setScope(approvedScopes);
authorizationRequest.setApproved(true);
}
return authorizationRequest;
}
private Date computeExpiry() {
Calendar expiresAt = Calendar.getInstance();
if (approvalExpirySeconds == -1) { // use default of 1 month
expiresAt.add(Calendar.MONTH, 1);
}
else {
expiresAt.add(Calendar.SECOND, approvalExpirySeconds);
}
return expiresAt.getTime();
}
/**
* Requires the authorization request to be explicitly approved, including all individual scopes, and the user to be
* authenticated. A scope that was requested in the authorization request can be approved by sending a request
* parameter scope.<scopename>
equal to "true" or "approved" (otherwise it will be assumed to
* have been denied). The {@link ApprovalStore} will be updated to reflect the inputs.
*
* @param authorizationRequest The authorization request.
* @param userAuthentication the current user authentication
*
* @return An approved request if all scopes have been approved by the current user.
*/
public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest,
Authentication userAuthentication) {
// Get the approved scopes
Set requestedScopes = authorizationRequest.getScope();
Set approvedScopes = new HashSet();
Set approvals = new HashSet();
Date expiry = computeExpiry();
// Store the scopes that have been approved / denied
Map approvalParameters = authorizationRequest.getApprovalParameters();
for (String requestedScope : requestedScopes) {
String approvalParameter = scopePrefix + requestedScope;
String value = approvalParameters.get(approvalParameter);
value = value == null ? "" : value.toLowerCase();
if ("true".equals(value) || value.startsWith("approve")) {
approvedScopes.add(requestedScope);
approvals.add(new Approval(userAuthentication.getName(), authorizationRequest.getClientId(),
requestedScope, expiry, ApprovalStatus.APPROVED));
}
else {
approvals.add(new Approval(userAuthentication.getName(), authorizationRequest.getClientId(),
requestedScope, expiry, ApprovalStatus.DENIED));
}
}
approvalStore.addApprovals(approvals);
boolean approved;
authorizationRequest.setScope(approvedScopes);
if (approvedScopes.isEmpty() && !requestedScopes.isEmpty()) {
approved = false;
}
else {
approved = true;
}
authorizationRequest.setApproved(approved);
return authorizationRequest;
}
@Override
public Map getUserApprovalRequest(AuthorizationRequest authorizationRequest,
Authentication userAuthentication) {
Map model = new HashMap();
model.putAll(authorizationRequest.getRequestParameters());
Map scopes = new LinkedHashMap();
for (String scope : authorizationRequest.getScope()) {
scopes.put(scopePrefix + scope, "false");
}
for (Approval approval : approvalStore.getApprovals(userAuthentication.getName(),
authorizationRequest.getClientId())) {
if (authorizationRequest.getScope().contains(approval.getScope())) {
scopes.put(scopePrefix + approval.getScope(),
approval.getStatus() == ApprovalStatus.APPROVED ? "true" : "false");
}
}
model.put("scopes", scopes);
return model;
}
}