View Javadoc
1   package org.springframework.security.oauth2.provider;
2   
3   import java.io.Serializable;
4   import java.util.Collection;
5   import java.util.Collections;
6   import java.util.HashMap;
7   import java.util.HashSet;
8   import java.util.Map;
9   import java.util.Set;
10  
11  import org.springframework.security.core.GrantedAuthority;
12  import org.springframework.security.oauth2.common.util.OAuth2Utils;
13  import org.springframework.web.bind.annotation.SessionAttributes;
14  
15  /**
16   * A request for authorization by an OAuth 2 Client, normally received and
17   * processed by the AuthorizationEndpoint. This class is meant to be manipulated
18   * throughout the authorization process, and is therefore treated as ephemeral
19   * and not to be stored long term. For long term storage, use the read-only
20   * {@link OAuth2Request} class.
21   * 
22   * HTTP request parameters are stored in the parameters map, and any processing
23   * the server makes throughout the lifecycle of a request are stored on
24   * individual properties. The original request parameters will remain available
25   * through the parameters map. For convenience, constants are defined in order
26   * to get at those original values. However, the parameters map is unmodifiable
27   * so that processing cannot drop the original values.
28   * 
29   * This class is {@link Serializable} in order to support storage of the
30   * authorization request as a {@link SessionAttributes} member while the end
31   * user through the authorization process (which may span several page
32   * requests).
33   * 
34   * @author Ryan Heaton
35   * @author Dave Syer
36   * @author Amanda Anganes
37   */
38  @SuppressWarnings("serial")
39  public class AuthorizationRequest extends BaseRequest implements Serializable {
40  
41  	/**
42  	 * Map to hold the original, unchanged parameter set submitted by a user to
43  	 * signal approval of the token grant approval. Once set this should not be
44  	 * modified.
45  	 */
46  	private Map<String, String> approvalParameters = Collections.unmodifiableMap(new HashMap<String, String>());
47  
48  	/**
49  	 * The value of the "state" parameter sent by the client in the request, if
50  	 * sent by the client. As this must be echoed back to the client unchanged,
51  	 * it should not be modified by any processing classes.
52  	 */
53  	private String state;
54  
55  	/**
56  	 * Resolved requested response types initialized (by the
57  	 * OAuth2RequestFactory) with the response types originally requested.
58  	 */
59  	private Set<String> responseTypes = new HashSet<String>();
60  
61  	/**
62  	 * Resolved resource IDs. This set may change during request processing.
63  	 */
64  	private Set<String> resourceIds = new HashSet<String>();
65  
66  	/**
67  	 * Resolved granted authorities for this request. May change during request
68  	 * processing.
69  	 */
70  	private Collection<? extends GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
71  
72  	/**
73  	 * Whether the request has been approved by the end user (or other process).
74  	 * This will be altered by the User Approval Endpoint and/or the
75  	 * UserApprovalHandler as appropriate.
76  	 */
77  	private boolean approved = false;
78  
79  	/**
80  	 * The resolved redirect URI of this request. A URI may be present in the
81  	 * original request, in the authorizationParameters, or it may not be
82  	 * provided, in which case it will be defaulted (by processing classes) to
83  	 * the Client's default registered value.
84  	 */
85  	private String redirectUri;
86  
87  	/**
88  	 * Extension point for custom processing classes which may wish to store
89  	 * additional information about the OAuth2 request. Since this class will
90  	 * create a serializable OAuth2Request, all members of this extension map
91  	 * must be serializable.
92  	 */
93  	private Map<String, Serializable> extensions = new HashMap<String, Serializable>();
94  
95  	/**
96  	 * Default constructor.
97  	 */
98  	public AuthorizationRequest() {
99  	}
100 
101 	/**
102 	 * Full constructor.
103 	 */
104 	public AuthorizationRequest(Map<String, String> authorizationParameters, Map<String, String> approvalParameters, String clientId, Set<String> scope, Set<String> resourceIds, Collection<? extends GrantedAuthority> authorities, boolean approved, String state, String redirectUri,
105 	        Set<String> responseTypes) {
106 		setClientId(clientId);
107 		setRequestParameters(authorizationParameters); // in case we need to
108 													   // wrap the collection
109 		setScope(scope); // in case we need to parse
110 		if (resourceIds != null) {
111 			this.resourceIds = new HashSet<String>(resourceIds);
112 		}
113 		if (authorities != null) {
114 			this.authorities = new HashSet<GrantedAuthority>(authorities);
115 		}
116 		this.approved = approved;
117 		this.resourceIds = resourceIds;
118 		this.redirectUri = redirectUri;
119 		if (responseTypes != null) {
120 			this.responseTypes = responseTypes;
121 		}
122 		this.state = state;
123 	}
124 
125 	public OAuth2Request createOAuth2Request() {
126 		return new OAuth2Request(getRequestParameters(), getClientId(), getAuthorities(), isApproved(), getScope(), getResourceIds(), getRedirectUri(), getResponseTypes(), getExtensions());
127 	}
128 
129 	/**
130 	 * Convenience constructor for unit tests, where client ID and scope are
131 	 * often the only needed fields.
132 	 * 
133 	 * @param clientId
134 	 * @param scopes
135 	 */
136 	public AuthorizationRequest(String clientId, Collection<String> scopes) {
137 		setClientId(clientId);
138 		setScope(scopes); // in case we need to parse
139 	}
140 
141 	/**
142 	 * Convenience method to set resourceIds and authorities on this request by
143 	 * inheriting from a ClientDetails object.
144 	 * 
145 	 * @param clientDetails
146 	 */
147 	public void setResourceIdsAndAuthoritiesFromClientDetails(ClientDetails clientDetails) {
148 		setResourceIds(clientDetails.getResourceIds());
149 		setAuthorities(clientDetails.getAuthorities());
150 	}
151 
152 	public Map<String, String> getApprovalParameters() {
153 		return approvalParameters;
154 	}
155 
156 	public void setApprovalParameters(Map<String, String> approvalParameters) {
157 		this.approvalParameters = approvalParameters;
158 	}
159 
160 	public String getState() {
161 		return state;
162 	}
163 
164 	public void setState(String state) {
165 		this.state = state;
166 	}
167 
168 	public Set<String> getResponseTypes() {
169 		return responseTypes;
170 	}
171 
172 	public void setResponseTypes(Set<String> responseTypes) {
173 		this.responseTypes = responseTypes;
174 	}
175 
176 	public void setRedirectUri(String redirectUri) {
177 		this.redirectUri = redirectUri;
178 	}
179 
180 	public void setApproved(boolean approved) {
181 		this.approved = approved;
182 	}
183 
184 	public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {
185 		if (authorities != null) {
186 			this.authorities = new HashSet<GrantedAuthority>(authorities);
187 		}
188 	}
189 
190 	/**
191 	 * @return the extensions
192 	 */
193 	public Map<String, Serializable> getExtensions() {
194 		return extensions;
195 	}
196 
197 	public void setExtensions(Map<String, Serializable> extensions) {
198 		this.extensions = extensions;
199 	}
200 
201 	public void setResourceIds(Set<String> resourceIds) {
202 		this.resourceIds = resourceIds;
203 	}
204 
205 	public void setClientId(String clientId) {
206 		super.setClientId(clientId);
207 	}
208 
209 	/**
210 	 * Set the scope value. If the collection contains only a single scope
211 	 * value, this method will parse that value into a collection using
212 	 * {@link OAuth2Utils#parseParameterList}.
213 	 * 
214 	 * @see TokenRequest#setScope
215 	 * 
216 	 * @param scope
217 	 */
218 	public void setScope(Collection<String> scope) {
219 		super.setScope(scope);
220 	}
221 
222 	/**
223 	 * Set the Request Parameters on this authorization request, which represent
224 	 * the original request parameters and should never be changed during
225 	 * processing. The map passed in is wrapped in an unmodifiable map instance.
226 	 * 
227 	 * @see TokenRequest#setRequestParameters
228 	 * 
229 	 * @param requestParameters
230 	 */
231 	public void setRequestParameters(Map<String, String> requestParameters) {
232 		super.setRequestParameters(requestParameters);
233 	}
234 
235 	/**
236 	 * @return the resourceIds
237 	 */
238 	public Set<String> getResourceIds() {
239 		return resourceIds;
240 	}
241 
242 	/**
243 	 * @return the authorities
244 	 */
245 	public Collection<? extends GrantedAuthority> getAuthorities() {
246 		return authorities;
247 	}
248 
249 	/**
250 	 * @return the approved
251 	 */
252 	public boolean isApproved() {
253 		return approved;
254 	}
255 
256 	/**
257 	 * @return the redirectUri
258 	 */
259 	public String getRedirectUri() {
260 		return redirectUri;
261 	}
262 
263 	@Override
264 	public int hashCode() {
265 		final int prime = 31;
266 		int result = super.hashCode();
267 		result = prime * result + ((approvalParameters == null) ? 0 : approvalParameters.hashCode());
268 		result = prime * result + ((responseTypes == null) ? 0 : responseTypes.hashCode());
269 		result = prime * result + ((state == null) ? 0 : state.hashCode());
270 		return result;
271 	}
272 
273 	@Override
274 	public boolean equals(Object obj) {
275 		if (this == obj)
276 			return true;
277 		if (!super.equals(obj))
278 			return false;
279 		if (getClass() != obj.getClass())
280 			return false;
281 		AuthorizationRequest other = (AuthorizationRequest) obj;
282 		if (approvalParameters == null) {
283 			if (other.approvalParameters != null)
284 				return false;
285 		} else if (!approvalParameters.equals(other.approvalParameters))
286 			return false;
287 		if (responseTypes == null) {
288 			if (other.responseTypes != null)
289 				return false;
290 		} else if (!responseTypes.equals(other.responseTypes))
291 			return false;
292 		if (state == null) {
293 			if (other.state != null)
294 				return false;
295 		} else if (!state.equals(other.state))
296 			return false;
297 		return true;
298 	}
299 
300 }