View Javadoc
1   /*
2    * Copyright 2012-2013 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.security.oauth2.provider;
18  
19  import java.io.Serializable;
20  import java.util.Collection;
21  import java.util.Collections;
22  import java.util.HashMap;
23  import java.util.HashSet;
24  import java.util.LinkedHashSet;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import org.springframework.security.oauth2.common.util.OAuth2Utils;
29  
30  /**
31   * 
32   * A base class for the three "*Request" classes used in processing OAuth 2
33   * authorizations. This class should <strong>never</strong> be used directly,
34   * and it should <strong>never</strong> be used as the type for a local or other
35   * variable.
36   * 
37   * @author Dave Syer
38   * 
39   */
40  @SuppressWarnings("serial")
41  abstract class BaseRequest implements Serializable {
42  
43  	/**
44  	 * Resolved client ID. This may be present in the original request
45  	 * parameters, or in some cases may be inferred by a processing class and
46  	 * inserted here.
47  	 */
48  	private String clientId;
49  
50  	/**
51  	 * Resolved scope set, initialized (by the OAuth2RequestFactory) with the
52  	 * scopes originally requested. Further processing and user interaction may
53  	 * alter the set of scopes that is finally granted and stored when the
54  	 * request processing is complete.
55  	 */
56  	private Set<String> scope = new HashSet<String>();
57  
58  	/**
59  	 * Map of parameters passed in to the Authorization Endpoint or Token
60  	 * Endpoint, preserved unchanged from the original request. This map should
61  	 * not be modified after initialization. In general, classes should not
62  	 * retrieve values from this map directly, and should instead use the
63  	 * individual members on this class.
64  	 * 
65  	 * The OAuth2RequestFactory is responsible for initializing all members of
66  	 * this class, usually by parsing the values inside the requestParmaeters
67  	 * map.
68  	 * 
69  	 */
70  	private Map<String, String> requestParameters = Collections
71  			.unmodifiableMap(new HashMap<String, String>());
72  
73  	public String getClientId() {
74  		return clientId;
75  	}
76  
77  	public Set<String> getScope() {
78  		return scope;
79  	}
80  
81  	/**
82  	 * Warning: most clients should use the individual properties of this class,
83  	 * such as {{@link #getScope()} or { {@link #getClientId()}, rather than
84  	 * retrieving values from this map.
85  	 * 
86  	 * @return the original, unchanged set of request parameters
87  	 */
88  	public Map<String, String> getRequestParameters() {
89  		return requestParameters;
90  	}
91  
92  	@Override
93  	public int hashCode() {
94  		final int prime = 31;
95  		int result = 1;
96  		result = prime * result
97  				+ ((clientId == null) ? 0 : clientId.hashCode());
98  		result = prime
99  				* result
100 				+ ((requestParameters == null) ? 0 : requestParameters
101 						.hashCode());
102 		result = prime * result + ((scope == null) ? 0 : scope.hashCode());
103 		return result;
104 	}
105 
106 	@Override
107 	public boolean equals(Object obj) {
108 		if (this == obj)
109 			return true;
110 		if (obj == null)
111 			return false;
112 		if (getClass() != obj.getClass())
113 			return false;
114 		BaseRequest other = (BaseRequest) obj;
115 		if (clientId == null) {
116 			if (other.clientId != null)
117 				return false;
118 		} else if (!clientId.equals(other.clientId))
119 			return false;
120 		if (requestParameters == null) {
121 			if (other.requestParameters != null)
122 				return false;
123 		} else if (!requestParameters.equals(other.requestParameters))
124 			return false;
125 		if (scope == null) {
126 			if (other.scope != null)
127 				return false;
128 		} else if (!scope.equals(other.scope))
129 			return false;
130 		return true;
131 	}
132 
133 	protected void setScope(Collection<String> scope) {
134 		if (scope != null && scope.size() == 1) {
135 			String value = scope.iterator().next();
136 			/*
137 			 * This is really an error, but it can catch out unsuspecting users
138 			 * and it's easy to fix. It happens when an AuthorizationRequest
139 			 * gets bound accidentally from request parameters using
140 			 * @ModelAttribute.
141 			 */
142 			if (value.contains(" ") || value.contains(",")) {
143 				scope = OAuth2Utils.parseParameterList(value);
144 			}
145 		}
146 		this.scope = Collections
147 				.unmodifiableSet(scope == null ? new LinkedHashSet<String>()
148 						: new LinkedHashSet<String>(scope));
149 	}
150 
151 	protected void setRequestParameters(Map<String, String> requestParameters) {
152 		if (requestParameters != null) {
153 			this.requestParameters = Collections
154 					.unmodifiableMap(new HashMap<String, String>(requestParameters));
155 		}
156 	}
157 
158 	protected void setClientId(String clientId) {
159 		this.clientId = clientId;
160 	}
161 
162 }