View Javadoc
1   /*
2    * Copyright 2009-2019 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  package org.springframework.security.oauth2.provider.endpoint;
17  
18  import org.apache.commons.logging.Log;
19  import org.apache.commons.logging.LogFactory;
20  import org.springframework.http.ResponseEntity;
21  import org.springframework.security.oauth2.common.OAuth2AccessToken;
22  import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
23  import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
24  import org.springframework.security.oauth2.provider.OAuth2Authentication;
25  import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
26  import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
27  import org.springframework.security.oauth2.provider.token.AccessTokenConverter;
28  import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
29  import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
30  import org.springframework.web.bind.annotation.ExceptionHandler;
31  import org.springframework.web.bind.annotation.RequestMapping;
32  import org.springframework.web.bind.annotation.RequestMethod;
33  import org.springframework.web.bind.annotation.RequestParam;
34  import org.springframework.web.bind.annotation.ResponseBody;
35  
36  import java.util.Map;
37  
38  /**
39   * Controller which decodes access tokens for clients who are not able to do so (or where opaque token values are used).
40   * 
41   * @author Luke Taylor
42   * @author Joel D'sa
43   */
44  @FrameworkEndpoint
45  public class CheckTokenEndpoint {
46  
47  	private ResourceServerTokenServices resourceServerTokenServices;
48  
49  	private AccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
50  
51  	protected final Log logger = LogFactory.getLog(getClass());
52  
53  	private WebResponseExceptionTranslator<OAuth2Exception> exceptionTranslator = new DefaultWebResponseExceptionTranslator();
54  
55  	public CheckTokenEndpoint(ResourceServerTokenServices resourceServerTokenServices) {
56  		this.resourceServerTokenServices = resourceServerTokenServices;
57  	}
58  	
59  	/**
60  	 * @param exceptionTranslator the exception translator to set
61  	 */
62  	public void setExceptionTranslator(WebResponseExceptionTranslator<OAuth2Exception> exceptionTranslator) {
63  		this.exceptionTranslator = exceptionTranslator;
64  	}
65  
66  	/**
67  	 * @param accessTokenConverter the accessTokenConverter to set
68  	 */
69  	public void setAccessTokenConverter(AccessTokenConverter accessTokenConverter) {
70  		this.accessTokenConverter = accessTokenConverter;
71  	}
72  
73  	@RequestMapping(value = "/oauth/check_token", method = RequestMethod.POST)
74  	@ResponseBody
75  	public Map<String, ?> checkToken(@RequestParam("token") String value) {
76  
77  		OAuth2AccessToken token = resourceServerTokenServices.readAccessToken(value);
78  		if (token == null) {
79  			throw new InvalidTokenException("Token was not recognised");
80  		}
81  
82  		if (token.isExpired()) {
83  			throw new InvalidTokenException("Token has expired");
84  		}
85  
86  		OAuth2Authentication authentication = resourceServerTokenServices.loadAuthentication(token.getValue());
87  
88  		Map<String, Object> response = (Map<String, Object>)accessTokenConverter.convertAccessToken(token, authentication);
89  
90  		// gh-1070
91  		response.put("active", true);	// Always true if token exists and not expired
92  
93  		return response;
94  	}
95  
96  	@ExceptionHandler(InvalidTokenException.class)
97  	public ResponseEntity<OAuth2Exception> handleException(Exception e) throws Exception {
98  		logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
99  		// This isn't an oauth resource, so we don't want to send an
100 		// unauthorized code here. The client has already authenticated
101 		// successfully with basic auth and should just
102 		// get back the invalid token error.
103 		@SuppressWarnings("serial")
104 		InvalidTokenException e400 = new InvalidTokenException(e.getMessage()) {
105 			@Override
106 			public int getHttpErrorCode() {
107 				return 400;
108 			}
109 		};
110 		return exceptionTranslator.translate(e400);
111 	}
112 
113 }