View Javadoc
1   /*
2    * Copyright 2002-2011 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.endpoint;
18  
19  import static org.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertNotNull;
21  import static org.junit.Assert.assertTrue;
22  import static org.mockito.Matchers.any;
23  import static org.mockito.Matchers.eq;
24  import static org.mockito.Mockito.when;
25  
26  import java.security.Principal;
27  import java.util.Arrays;
28  import java.util.Collections;
29  import java.util.HashMap;
30  import java.util.HashSet;
31  import java.util.Map;
32  
33  import org.junit.Before;
34  import org.junit.Test;
35  import org.junit.runner.RunWith;
36  import org.mockito.ArgumentCaptor;
37  import org.mockito.Mock;
38  import org.mockito.Mockito;
39  import org.mockito.runners.MockitoJUnitRunner;
40  import org.springframework.http.HttpMethod;
41  import org.springframework.http.HttpStatus;
42  import org.springframework.http.ResponseEntity;
43  import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
44  import org.springframework.security.core.authority.SimpleGrantedAuthority;
45  import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
46  import org.springframework.security.oauth2.common.OAuth2AccessToken;
47  import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
48  import org.springframework.security.oauth2.common.util.OAuth2Utils;
49  import org.springframework.security.oauth2.provider.ClientDetails;
50  import org.springframework.security.oauth2.provider.ClientDetailsService;
51  import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
52  import org.springframework.security.oauth2.provider.TokenGranter;
53  import org.springframework.security.oauth2.provider.TokenRequest;
54  import org.springframework.security.oauth2.provider.client.BaseClientDetails;
55  import org.springframework.web.HttpRequestMethodNotSupportedException;
56  
57  /**
58   * @author Dave Syer
59   * @author Rob Winch
60   */
61  @RunWith(MockitoJUnitRunner.class)
62  public class TokenEndpointTests {
63  
64  	@Mock
65  	private TokenGranter tokenGranter;
66  
67  	@Mock
68  	private OAuth2RequestFactory authorizationRequestFactory;
69  
70  	@Mock
71  	private ClientDetailsService clientDetailsService;
72  
73  	private String clientId = "client";
74  	private BaseClientDetails clientDetails = new BaseClientDetails();
75  
76  	private TokenEndpoint endpoint;
77  
78  	private Principal clientAuthentication = new UsernamePasswordAuthenticationToken("client", null,
79  			Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT")));
80  
81  	private TokenRequest createFromParameters(Map<String, String> parameters) {
82  		TokenRequest request = new TokenRequest(parameters, parameters.get(OAuth2Utils.CLIENT_ID),
83  				OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)),
84  				parameters.get(OAuth2Utils.GRANT_TYPE));
85  		return request;
86  	}
87  
88  	@Before
89  	public void init() {
90  		endpoint = new TokenEndpoint();
91  		endpoint.setTokenGranter(tokenGranter);
92  		endpoint.setOAuth2RequestFactory(authorizationRequestFactory);
93  		endpoint.setClientDetailsService(clientDetailsService);
94  		clientDetails.setClientId(clientId);
95  	}
96  
97  	@Test
98  	public void testGetAccessTokenWithNoClientId() throws HttpRequestMethodNotSupportedException {
99  
100 		HashMap<String, String> parameters = new HashMap<String, String>();
101 		parameters.put(OAuth2Utils.GRANT_TYPE, "authorization_code");
102 
103 		OAuth2AccessToken expectedToken = new DefaultOAuth2AccessToken("FOO");
104 		when(tokenGranter.grant(eq("authorization_code"), Mockito.any(TokenRequest.class))).thenReturn(
105 				expectedToken);
106 		@SuppressWarnings("unchecked")
107 		Map<String, String> anyMap = Mockito.any(Map.class);
108 		when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.any(ClientDetails.class))).thenReturn(
109 				createFromParameters(parameters));
110 
111 		clientAuthentication = new UsernamePasswordAuthenticationToken(null, null,
112 				Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT")));
113 		ResponseEntity<OAuth2AccessToken> response = endpoint.postAccessToken(clientAuthentication, parameters);
114 
115 		assertNotNull(response);
116 		assertEquals(HttpStatus.OK, response.getStatusCode());
117 		OAuth2AccessToken body = response.getBody();
118 		assertEquals(body, expectedToken);
119 		assertTrue("Wrong body: " + body, body.getTokenType() != null);
120 	}
121 
122 	@Test
123 	public void testGetAccessTokenWithScope() throws HttpRequestMethodNotSupportedException {
124 
125 		when(clientDetailsService.loadClientByClientId(clientId)).thenReturn(clientDetails);
126 
127 		HashMap<String, String> parameters = new HashMap<String, String>();
128 		parameters.put("client_id", clientId);
129 		parameters.put("scope", "read");
130 		parameters.put("grant_type", "authorization_code");
131 		parameters.put("code", "kJAHDFG");
132 
133 		OAuth2AccessToken expectedToken = new DefaultOAuth2AccessToken("FOO");
134 		ArgumentCaptor<TokenRequest> captor = ArgumentCaptor.forClass(TokenRequest.class);
135 
136 		when(tokenGranter.grant(eq("authorization_code"), captor.capture())).thenReturn(expectedToken);
137 		@SuppressWarnings("unchecked")
138 		Map<String, String> anyMap = Mockito.any(Map.class);
139 		when(authorizationRequestFactory.createTokenRequest(anyMap, eq(clientDetails))).thenReturn(
140 				createFromParameters(parameters));
141 
142 		ResponseEntity<OAuth2AccessToken> response = endpoint.postAccessToken(clientAuthentication, parameters);
143 
144 		assertNotNull(response);
145 		assertEquals(HttpStatus.OK, response.getStatusCode());
146 		OAuth2AccessToken body = response.getBody();
147 		assertEquals(body, expectedToken);
148 		assertTrue("Wrong body: " + body, body.getTokenType() != null);
149 		assertTrue("Scope of token request not cleared", captor.getValue().getScope().isEmpty());
150 	}
151 
152     @Test(expected = HttpRequestMethodNotSupportedException.class)
153     public void testGetAccessTokenWithUnsupportedRequestParameters() throws HttpRequestMethodNotSupportedException {
154         endpoint.getAccessToken(clientAuthentication, new HashMap<String, String>());
155     }
156 
157 	@Test
158 	public void testGetAccessTokenWithSupportedRequestParametersNotPost() throws HttpRequestMethodNotSupportedException {
159 		endpoint.setAllowedRequestMethods(new HashSet<HttpMethod>(Arrays.asList(HttpMethod.GET)));
160 		HashMap<String, String> parameters = new HashMap<String, String>();
161 		parameters.put("client_id", clientId);
162 		parameters.put("scope", "read");
163 		parameters.put("grant_type", "authorization_code");
164 		parameters.put("code", "kJAHDFG");
165 
166 		OAuth2AccessToken expectedToken = new DefaultOAuth2AccessToken("FOO");
167 		when(tokenGranter.grant(eq("authorization_code"), Mockito.any(TokenRequest.class))).thenReturn(
168 				expectedToken);
169 		@SuppressWarnings("unchecked")
170 		Map<String, String> anyMap = Mockito.any(Map.class);
171 		when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.any(ClientDetails.class))).thenReturn(
172 				createFromParameters(parameters));
173 
174 		ResponseEntity<OAuth2AccessToken> response = endpoint.getAccessToken(clientAuthentication, parameters);
175 		assertNotNull(response);
176 		assertEquals(HttpStatus.OK, response.getStatusCode());
177 		OAuth2AccessToken body = response.getBody();
178 		assertEquals(body, expectedToken);
179 		assertTrue("Wrong body: " + body, body.getTokenType() != null);
180 	}
181 
182 	@Test(expected = InvalidGrantException.class)
183 	public void testImplicitGrant() throws HttpRequestMethodNotSupportedException {
184 		HashMap<String, String> parameters = new HashMap<String, String>();
185 		parameters.put(OAuth2Utils.GRANT_TYPE, "implicit");
186 		parameters.put("client_id", clientId);
187 		parameters.put("scope", "read");
188 		@SuppressWarnings("unchecked")
189 		Map<String, String> anyMap = Mockito.any(Map.class);
190 		when(authorizationRequestFactory.createTokenRequest(anyMap, eq(clientDetails))).thenReturn(
191 				createFromParameters(parameters));
192 		when(clientDetailsService.loadClientByClientId(clientId)).thenReturn(clientDetails);
193 		endpoint.postAccessToken(clientAuthentication, parameters);
194 	}
195 
196 	// gh-1268
197 	@Test
198 	public void testGetAccessTokenReturnsHeaderContentTypeJson() throws Exception {
199 		when(clientDetailsService.loadClientByClientId(clientId)).thenReturn(clientDetails);
200 
201 		HashMap<String, String> parameters = new HashMap<String, String>();
202 		parameters.put("client_id", clientId);
203 		parameters.put("scope", "read");
204 		parameters.put("grant_type", "authorization_code");
205 		parameters.put("code", "kJAHDFG");
206 
207 		OAuth2AccessToken expectedToken = new DefaultOAuth2AccessToken("FOO");
208 
209 		when(tokenGranter.grant(eq("authorization_code"), any(TokenRequest.class))).thenReturn(expectedToken);
210 
211 		when(authorizationRequestFactory.createTokenRequest(any(Map.class), eq(clientDetails))).thenReturn(
212 				createFromParameters(parameters));
213 
214 		ResponseEntity<OAuth2AccessToken> response = endpoint.postAccessToken(clientAuthentication, parameters);
215 
216 		assertNotNull(response);
217 		assertEquals(HttpStatus.OK, response.getStatusCode());
218 		assertEquals("application/json;charset=UTF-8", response.getHeaders().get("Content-Type").iterator().next());
219 	}
220 }