View Javadoc
1   /*
2    * Cloud Foundry 2012.02.03 Beta
3    * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
4    *
5    * This product is licensed to you under the Apache License, Version 2.0 (the "License").
6    * You may not use this product except in compliance with the License.
7    *
8    * This product includes a number of subcomponents with
9    * separate copyright notices and license terms. Your use of these
10   * subcomponents is subject to the terms and conditions of the
11   * subcomponent's license, as noted in the LICENSE file.
12   */
13  package org.springframework.security.oauth2.provider.token;
14  
15  import java.util.Arrays;
16  import java.util.Collection;
17  import java.util.Collections;
18  import java.util.Date;
19  import java.util.HashMap;
20  import java.util.LinkedHashSet;
21  import java.util.Map;
22  import java.util.Set;
23  
24  import org.springframework.security.core.Authentication;
25  import org.springframework.security.core.GrantedAuthority;
26  import org.springframework.security.core.authority.AuthorityUtils;
27  import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
28  import org.springframework.security.oauth2.common.OAuth2AccessToken;
29  import org.springframework.security.oauth2.provider.OAuth2Authentication;
30  import org.springframework.security.oauth2.provider.OAuth2Request;
31  
32  /**
33   * Default implementation of {@link AccessTokenConverter}.
34   * 
35   * @author Dave Syer
36   * @author Vedran Pavic
37   */
38  public class DefaultAccessTokenConverter implements AccessTokenConverter {
39  
40  	private UserAuthenticationConverter userTokenConverter = new DefaultUserAuthenticationConverter();
41  	
42  	private boolean includeGrantType;
43  
44  	private String scopeAttribute = SCOPE;
45  
46  	private String clientIdAttribute = CLIENT_ID;
47  
48  	/**
49  	 * Converter for the part of the data in the token representing a user.
50  	 * 
51  	 * @param userTokenConverter the userTokenConverter to set
52  	 */
53  	public void setUserTokenConverter(UserAuthenticationConverter userTokenConverter) {
54  		this.userTokenConverter = userTokenConverter;
55  	}
56  
57  	/**
58  	 * Flag to indicate the the grant type should be included in the converted token.
59  	 * 
60  	 * @param includeGrantType the flag value (default false)
61  	 */
62  	public void setIncludeGrantType(boolean includeGrantType) {
63  		this.includeGrantType = includeGrantType;	
64  	}
65  
66  	/**
67  	 * Set scope attribute name to be used in the converted token. Defaults to
68  	 * {@link AccessTokenConverter#SCOPE}.
69  	 *
70  	 * @param scopeAttribute the scope attribute name to use
71  	 */
72  	public void setScopeAttribute(String scopeAttribute) {
73  		this.scopeAttribute = scopeAttribute;
74  	}
75  
76  	/**
77  	 * Set client id attribute name to be used in the converted token. Defaults to
78  	 * {@link AccessTokenConverter#CLIENT_ID}.
79  	 *
80  	 * @param clientIdAttribute the client id attribute name to use
81  	 */
82  	public void setClientIdAttribute(String clientIdAttribute) {
83  		this.clientIdAttribute = clientIdAttribute;
84  	}
85  
86  	public Map<String, ?> convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
87  		Map<String, Object> response = new HashMap<String, Object>();
88  		OAuth2Request clientToken = authentication.getOAuth2Request();
89  
90  		if (!authentication.isClientOnly()) {
91  			response.putAll(userTokenConverter.convertUserAuthentication(authentication.getUserAuthentication()));
92  		} else {
93  			if (clientToken.getAuthorities()!=null && !clientToken.getAuthorities().isEmpty()) {
94  				response.put(UserAuthenticationConverter.AUTHORITIES,
95  							 AuthorityUtils.authorityListToSet(clientToken.getAuthorities()));
96  			}
97  		}
98  
99  		if (token.getScope()!=null) {
100 			response.put(scopeAttribute, token.getScope());
101 		}
102 		if (token.getAdditionalInformation().containsKey(JTI)) {
103 			response.put(JTI, token.getAdditionalInformation().get(JTI));
104 		}
105 
106 		if (token.getExpiration() != null) {
107 			response.put(EXP, token.getExpiration().getTime() / 1000);
108 		}
109 		
110 		if (includeGrantType && authentication.getOAuth2Request().getGrantType()!=null) {
111 			response.put(GRANT_TYPE, authentication.getOAuth2Request().getGrantType());
112 		}
113 
114 		response.putAll(token.getAdditionalInformation());
115 
116 		response.put(clientIdAttribute, clientToken.getClientId());
117 		if (clientToken.getResourceIds() != null && !clientToken.getResourceIds().isEmpty()) {
118 			response.put(AUD, clientToken.getResourceIds());
119 		}
120 		return response;
121 	}
122 
123 	public OAuth2AccessToken extractAccessToken(String value, Map<String, ?> map) {
124 		DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(value);
125 		Map<String, Object> info = new HashMap<String, Object>(map);
126 		info.remove(EXP);
127 		info.remove(AUD);
128 		info.remove(clientIdAttribute);
129 		info.remove(scopeAttribute);
130 		if (map.containsKey(EXP)) {
131 			token.setExpiration(new Date((Long) map.get(EXP) * 1000L));
132 		}
133 		if (map.containsKey(JTI)) {
134 			info.put(JTI, map.get(JTI));
135 		}
136 		token.setScope(extractScope(map));
137 		token.setAdditionalInformation(info);
138 		return token;
139 	}
140 
141 	public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
142 		Map<String, String> parameters = new HashMap<String, String>();
143 		Set<String> scope = extractScope(map);
144 		Authentication user = userTokenConverter.extractAuthentication(map);
145 		String clientId = (String) map.get(clientIdAttribute);
146 		parameters.put(clientIdAttribute, clientId);
147 		if (includeGrantType && map.containsKey(GRANT_TYPE)) {
148 			parameters.put(GRANT_TYPE, (String) map.get(GRANT_TYPE));
149 		}
150 		Set<String> resourceIds = new LinkedHashSet<String>(map.containsKey(AUD) ? getAudience(map)
151 				: Collections.<String>emptySet());
152 		
153 		Collection<? extends GrantedAuthority> authorities = null;
154 		if (user==null && map.containsKey(AUTHORITIES)) {
155 			@SuppressWarnings("unchecked")
156 			String[] roles = ((Collection<String>)map.get(AUTHORITIES)).toArray(new String[0]);
157 			authorities = AuthorityUtils.createAuthorityList(roles);
158 		}
159 		OAuth2Request request = new OAuth2Request(parameters, clientId, authorities, true, scope, resourceIds, null, null,
160 				null);
161 		return new OAuth2Authentication(request, user);
162 	}
163 
164 	private Collection<String> getAudience(Map<String, ?> map) {
165 		Object auds = map.get(AUD);
166 		if (auds instanceof Collection) {			
167 			@SuppressWarnings("unchecked")
168 			Collection<String> result = (Collection<String>) auds;
169 			return result;
170 		}
171 		return Collections.singleton((String)auds);
172 	}
173 
174 	private Set<String> extractScope(Map<String, ?> map) {
175 		Set<String> scope = Collections.emptySet();
176 		if (map.containsKey(scopeAttribute)) {
177 			Object scopeObj = map.get(scopeAttribute);
178 			if (String.class.isInstance(scopeObj)) {
179 				scope = new LinkedHashSet<String>(Arrays.asList(String.class.cast(scopeObj).split(" ")));
180 			} else if (Collection.class.isAssignableFrom(scopeObj.getClass())) {
181 				@SuppressWarnings("unchecked")
182 				Collection<String> scopeColl = (Collection<String>) scopeObj;
183 				scope = new LinkedHashSet<String>(scopeColl);	// Preserve ordering
184 			}
185 		}
186 		return scope;
187 	}
188 
189 }