1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.security.oauth2.provider.approval;
18
19 import java.util.Calendar;
20 import java.util.Collection;
21 import java.util.Date;
22 import java.util.HashMap;
23 import java.util.HashSet;
24 import java.util.LinkedHashMap;
25 import java.util.Map;
26 import java.util.Set;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.springframework.beans.factory.InitializingBean;
31 import org.springframework.security.core.Authentication;
32 import org.springframework.security.oauth2.common.util.OAuth2Utils;
33 import org.springframework.security.oauth2.provider.AuthorizationRequest;
34 import org.springframework.security.oauth2.provider.ClientDetails;
35 import org.springframework.security.oauth2.provider.ClientDetailsService;
36 import org.springframework.security.oauth2.provider.ClientRegistrationException;
37 import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
38 import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus;
39 import org.springframework.util.Assert;
40
41
42
43
44
45
46
47 public class ApprovalStoreUserApprovalHandler implements UserApprovalHandler, InitializingBean {
48
49 private static Log logger = LogFactory.getLog(ApprovalStoreUserApprovalHandler.class);
50
51 private String scopePrefix = OAuth2Utils.SCOPE_PREFIX;
52
53 private ApprovalStore approvalStore;
54
55 private int approvalExpirySeconds = -1;
56
57 private ClientDetailsService clientDetailsService;
58
59
60
61
62
63
64 public void setClientDetailsService(ClientDetailsService clientDetailsService) {
65 this.clientDetailsService = clientDetailsService;
66 }
67
68
69
70
71
72
73 public void setScopePrefix(String scopePrefix) {
74 this.scopePrefix = scopePrefix;
75 }
76
77
78
79
80 public void setApprovalStore(ApprovalStore store) {
81 this.approvalStore = store;
82 }
83
84 private OAuth2RequestFactory requestFactory;
85
86 public void setRequestFactory(OAuth2RequestFactory requestFactory) {
87 this.requestFactory = requestFactory;
88 }
89
90 public void setApprovalExpiryInSeconds(int approvalExpirySeconds) {
91 this.approvalExpirySeconds = approvalExpirySeconds;
92 }
93
94 public void afterPropertiesSet() {
95 Assert.state(approvalStore != null, "ApprovalStore must be provided");
96 Assert.state(requestFactory != null, "OAuth2RequestFactory must be provided");
97 }
98
99 public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) {
100 return authorizationRequest.isApproved();
101 }
102
103 public AuthorizationRequestringframework/security/oauth2/provider/AuthorizationRequest.html#AuthorizationRequest">AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest,
104 Authentication userAuthentication) {
105
106 String clientId = authorizationRequest.getClientId();
107 Collection<String> requestedScopes = authorizationRequest.getScope();
108 Set<String> approvedScopes = new HashSet<String>();
109 Set<String> validUserApprovedScopes = new HashSet<String>();
110
111 if (clientDetailsService != null) {
112 try {
113 ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
114 for (String scope : requestedScopes) {
115 if (client.isAutoApprove(scope)) {
116 approvedScopes.add(scope);
117 }
118 }
119 if (approvedScopes.containsAll(requestedScopes)) {
120
121 Set<Approval> approvals = new HashSet<Approval>();
122 Date expiry = computeExpiry();
123 for (String approvedScope : approvedScopes) {
124 approvals.add(new Approval(userAuthentication.getName(), authorizationRequest.getClientId(),
125 approvedScope, expiry, ApprovalStatus.APPROVED));
126 }
127 approvalStore.addApprovals(approvals);
128
129 authorizationRequest.setApproved(true);
130 return authorizationRequest;
131 }
132 }
133 catch (ClientRegistrationException e) {
134 logger.warn("Client registration problem prevent autoapproval check for client=" + clientId);
135 }
136 }
137
138 if (logger.isDebugEnabled()) {
139 StringBuilder builder = new StringBuilder("Looking up user approved authorizations for ");
140 builder.append("client_id=" + clientId);
141 builder.append(" and username=" + userAuthentication.getName());
142 logger.debug(builder.toString());
143 }
144
145
146 Collection<Approval> userApprovals = approvalStore.getApprovals(userAuthentication.getName(), clientId);
147
148
149 Date today = new Date();
150 for (Approval approval : userApprovals) {
151 if (approval.getExpiresAt().after(today)) {
152 if (approval.getStatus() == ApprovalStatus.APPROVED) {
153 validUserApprovedScopes.add(approval.getScope());
154 approvedScopes.add(approval.getScope());
155 }
156 }
157 }
158
159 if (logger.isDebugEnabled()) {
160 logger.debug("Valid user approved/denied scopes are " + validUserApprovedScopes);
161 }
162
163
164
165 if (validUserApprovedScopes.containsAll(requestedScopes)) {
166 approvedScopes.retainAll(requestedScopes);
167
168 authorizationRequest.setScope(approvedScopes);
169 authorizationRequest.setApproved(true);
170 }
171
172 return authorizationRequest;
173
174 }
175
176 private Date computeExpiry() {
177 Calendar expiresAt = Calendar.getInstance();
178 if (approvalExpirySeconds == -1) {
179 expiresAt.add(Calendar.MONTH, 1);
180 }
181 else {
182 expiresAt.add(Calendar.SECOND, approvalExpirySeconds);
183 }
184 return expiresAt.getTime();
185 }
186
187
188
189
190
191
192
193
194
195
196
197
198 public AuthorizationRequestringframework/security/oauth2/provider/AuthorizationRequest.html#AuthorizationRequest">AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest,
199 Authentication userAuthentication) {
200
201 Set<String> requestedScopes = authorizationRequest.getScope();
202 Set<String> approvedScopes = new HashSet<String>();
203 Set<Approval> approvals = new HashSet<Approval>();
204
205 Date expiry = computeExpiry();
206
207
208 Map<String, String> approvalParameters = authorizationRequest.getApprovalParameters();
209 for (String requestedScope : requestedScopes) {
210 String approvalParameter = scopePrefix + requestedScope;
211 String value = approvalParameters.get(approvalParameter);
212 value = value == null ? "" : value.toLowerCase();
213 if ("true".equals(value) || value.startsWith("approve")) {
214 approvedScopes.add(requestedScope);
215 approvals.add(new Approval(userAuthentication.getName(), authorizationRequest.getClientId(),
216 requestedScope, expiry, ApprovalStatus.APPROVED));
217 }
218 else {
219 approvals.add(new Approval(userAuthentication.getName(), authorizationRequest.getClientId(),
220 requestedScope, expiry, ApprovalStatus.DENIED));
221 }
222 }
223 approvalStore.addApprovals(approvals);
224
225 boolean approved;
226 authorizationRequest.setScope(approvedScopes);
227 if (approvedScopes.isEmpty() && !requestedScopes.isEmpty()) {
228 approved = false;
229 }
230 else {
231 approved = true;
232 }
233 authorizationRequest.setApproved(approved);
234 return authorizationRequest;
235 }
236
237 @Override
238 public Map<String, Object> getUserApprovalRequest(AuthorizationRequest authorizationRequest,
239 Authentication userAuthentication) {
240 Map<String, Object> model = new HashMap<String, Object>();
241 model.putAll(authorizationRequest.getRequestParameters());
242 Map<String, String> scopes = new LinkedHashMap<String, String>();
243 for (String scope : authorizationRequest.getScope()) {
244 scopes.put(scopePrefix + scope, "false");
245 }
246 for (Approval approval : approvalStore.getApprovals(userAuthentication.getName(),
247 authorizationRequest.getClientId())) {
248 if (authorizationRequest.getScope().contains(approval.getScope())) {
249 scopes.put(scopePrefix + approval.getScope(),
250 approval.getStatus() == ApprovalStatus.APPROVED ? "true" : "false");
251 }
252 }
253 model.put("scopes", scopes);
254 return model;
255 }
256 }