View Javadoc
1   package org.springframework.security.oauth2.common;
2   
3   import java.io.Serializable;
4   import java.util.Collections;
5   import java.util.Date;
6   import java.util.LinkedHashMap;
7   import java.util.Map;
8   import java.util.Set;
9   import java.util.StringTokenizer;
10  import java.util.TreeSet;
11  
12  /**
13   * Basic access token for OAuth 2.
14   * 
15   * @author Ryan Heaton
16   * @author Dave Syer
17   * @author Rob Winch
18   */
19  public class DefaultOAuth2AccessToken implements Serializable, OAuth2AccessToken {
20  
21  	private static final long serialVersionUID = 914967629530462926L;
22  
23  	private String value;
24  
25  	private Date expiration;
26  
27  	private String tokenType = BEARER_TYPE.toLowerCase();
28  
29  	private OAuth2RefreshToken refreshToken;
30  
31  	private Set<String> scope;
32  
33  	private Map<String, Object> additionalInformation = Collections.emptyMap();
34  
35  	/**
36  	 * Create an access token from the value provided.
37  	 */
38  	public DefaultOAuth2AccessToken(String value) {
39  		this.value = value;
40  	}
41  
42  	/**
43  	 * Private constructor for JPA and other serialization tools.
44  	 */
45  	@SuppressWarnings("unused")
46  	private DefaultOAuth2AccessToken() {
47  		this((String) null);
48  	}
49  
50  	/**
51  	 * Copy constructor for access token.
52  	 * 
53  	 * @param accessToken
54  	 */
55  	public DefaultOAuth2AccessToken(OAuth2AccessToken accessToken) {
56  		this(accessToken.getValue());
57  		setAdditionalInformation(accessToken.getAdditionalInformation());
58  		setRefreshToken(accessToken.getRefreshToken());
59  		setExpiration(accessToken.getExpiration());
60  		setScope(accessToken.getScope());
61  		setTokenType(accessToken.getTokenType());
62  	}
63  
64  	public void setValue(String value) {
65  		this.value = value;
66  	}
67  
68  	/**
69  	 * The token value.
70  	 * 
71  	 * @return The token value.
72  	 */
73  	public String getValue() {
74  		return value;
75  	}
76  
77  	public int getExpiresIn() {
78  		return expiration != null ? Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L)
79  				.intValue() : 0;
80  	}
81  
82  	protected void setExpiresIn(int delta) {
83  		setExpiration(new Date(System.currentTimeMillis() + delta));
84  	}
85  
86  	/**
87  	 * The instant the token expires.
88  	 * 
89  	 * @return The instant the token expires.
90  	 */
91  	public Date getExpiration() {
92  		return expiration;
93  	}
94  
95  	/**
96  	 * The instant the token expires.
97  	 * 
98  	 * @param expiration The instant the token expires.
99  	 */
100 	public void setExpiration(Date expiration) {
101 		this.expiration = expiration;
102 	}
103 
104 	/**
105 	 * Convenience method for checking expiration
106 	 * 
107 	 * @return true if the expiration is befor ethe current time
108 	 */
109 	public boolean isExpired() {
110 		return expiration != null && expiration.before(new Date());
111 	}
112 
113 	/**
114 	 * The token type, as introduced in draft 11 of the OAuth 2 spec. The spec doesn't define (yet) that the valid token
115 	 * types are, but says it's required so the default will just be "undefined".
116 	 * 
117 	 * @return The token type, as introduced in draft 11 of the OAuth 2 spec.
118 	 */
119 	public String getTokenType() {
120 		return tokenType;
121 	}
122 
123 	/**
124 	 * The token type, as introduced in draft 11 of the OAuth 2 spec.
125 	 * 
126 	 * @param tokenType The token type, as introduced in draft 11 of the OAuth 2 spec.
127 	 */
128 	public void setTokenType(String tokenType) {
129 		this.tokenType = tokenType;
130 	}
131 
132 	/**
133 	 * The refresh token associated with the access token, if any.
134 	 * 
135 	 * @return The refresh token associated with the access token, if any.
136 	 */
137 	public OAuth2RefreshToken getRefreshToken() {
138 		return refreshToken;
139 	}
140 
141 	/**
142 	 * The refresh token associated with the access token, if any.
143 	 * 
144 	 * @param refreshToken The refresh token associated with the access token, if any.
145 	 */
146 	public void setRefreshToken(OAuth2RefreshToken refreshToken) {
147 		this.refreshToken = refreshToken;
148 	}
149 
150 	/**
151 	 * The scope of the token.
152 	 * 
153 	 * @return The scope of the token.
154 	 */
155 	public Set<String> getScope() {
156 		return scope;
157 	}
158 
159 	/**
160 	 * The scope of the token.
161 	 * 
162 	 * @param scope The scope of the token.
163 	 */
164 	public void setScope(Set<String> scope) {
165 		this.scope = scope;
166 	}
167 
168 	@Override
169 	public boolean equals(Object obj) {
170 		return obj != null && toString().equals(obj.toString());
171 	}
172 
173 	@Override
174 	public int hashCode() {
175 		return toString().hashCode();
176 	}
177 
178 	@Override
179 	public String toString() {
180 		return String.valueOf(getValue());
181 	}
182 
183 	public static OAuth2AccessToken valueOf(Map<String, String> tokenParams) {
184 		DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(tokenParams.get(ACCESS_TOKEN));
185 
186 		if (tokenParams.containsKey(EXPIRES_IN)) {
187 			long expiration = 0;
188 			try {
189 				expiration = Long.parseLong(String.valueOf(tokenParams.get(EXPIRES_IN)));
190 			}
191 			catch (NumberFormatException e) {
192 				// fall through...
193 			}
194 			token.setExpiration(new Date(System.currentTimeMillis() + (expiration * 1000L)));
195 		}
196 
197 		if (tokenParams.containsKey(REFRESH_TOKEN)) {
198 			String refresh = tokenParams.get(REFRESH_TOKEN);
199 			DefaultOAuth2RefreshToken refreshToken = new DefaultOAuth2RefreshToken(refresh);
200 			token.setRefreshToken(refreshToken);
201 		}
202 
203 		if (tokenParams.containsKey(SCOPE)) {
204 			Set<String> scope = new TreeSet<String>();
205 			for (StringTokenizer tokenizer = new StringTokenizer(tokenParams.get(SCOPE), " ,"); tokenizer
206 					.hasMoreTokens();) {
207 				scope.add(tokenizer.nextToken());
208 			}
209 			token.setScope(scope);
210 		}
211 
212 		if (tokenParams.containsKey(TOKEN_TYPE)) {
213 			token.setTokenType(tokenParams.get(TOKEN_TYPE));
214 		}
215 
216 		return token;
217 	}
218 
219 	/**
220 	 * Additional information that token granters would like to add to the token, e.g. to support new token types.
221 	 * 
222 	 * @return the additional information (default empty)
223 	 */
224 	public Map<String, Object> getAdditionalInformation() {
225 		return additionalInformation;
226 	}
227 
228 	/**
229 	 * Additional information that token granters would like to add to the token, e.g. to support new token types. If
230 	 * the values in the map are primitive then remote communication is going to always work. It should also be safe to
231 	 * use maps (nested if desired), or something that is explicitly serializable by Jackson.
232 	 * 
233 	 * @param additionalInformation the additional information to set
234 	 */
235 	public void setAdditionalInformation(Map<String, Object> additionalInformation) {
236 		this.additionalInformation = new LinkedHashMap<String, Object>(additionalInformation);
237 	}
238 
239 }