/** * */ package com.iflytek.edu.cloud.oauth2.support; import java.security.Principal; import java.util.Collections; import java.util.Map; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.BadClientCredentialsException; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.InvalidRequestException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.exceptions.UnsupportedGrantTypeException; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2RequestValidator; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.endpoint.AbstractEndpoint; import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpoint; import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; /** * Create on @2014年8月4日 @下午7:23:23 * @author libinsong1204@gmail.com */ @FrameworkEndpoint public class TokenEndpoint extends AbstractEndpoint { private OAuth2RequestValidator oauth2RequestValidator = new DefaultOAuth2RequestValidator(); @RequestMapping(value = "/oauth/token") public ResponseEntity<OAuth2AccessToken> getAccessToken(Principal principal, @RequestParam Map<String, String> parameters) { if (!(principal instanceof Authentication)) { throw new InsufficientAuthenticationException( "There is no client authentication. Try adding an appropriate authentication filter."); } String clientId = getClientId(principal); ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId); TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient); if (clientId != null && !clientId.equals("")) { // Only validate the client details if a client authenticated during this // request. if (!clientId.equals(tokenRequest.getClientId())) { // double check to make sure that the client ID in the token request is the same as that in the // authenticated client throw new InvalidClientException("Given client ID does not match authenticated client"); } } //check appkey disabled Map<String, Object> additionalInformation = authenticatedClient.getAdditionalInformation(); if(additionalInformation != null) { Object enabled = additionalInformation.get("enabled"); if(enabled != null && !(Boolean)enabled) { throw new InvalidRequestException("appkey have been disabled"); } } if (authenticatedClient != null) { oauth2RequestValidator.validateScope(tokenRequest, authenticatedClient); } if (!StringUtils.hasText(tokenRequest.getGrantType())) { throw new InvalidRequestException("Missing grant type"); } if (tokenRequest.getGrantType().equals("implicit")) { throw new InvalidGrantException("Implicit grant type not supported from token endpoint"); } if (isAuthCodeRequest(parameters)) { // The scope was requested or determined during the authorization step if (!tokenRequest.getScope().isEmpty()) { logger.debug("Clearing scope of incoming token request"); tokenRequest.setScope(Collections.<String> emptySet()); } } if (isRefreshTokenRequest(parameters)) { // A refresh token has its own default scopes, so we should ignore any added by the factory here. tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE))); } OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest); if (token == null) { throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType()); } //jsonp String callback = parameters.get("callback"); return getResponse(token, callback); } /** * @param principal the currently authentication principal * @return a client id if there is one in the principal */ protected String getClientId(Principal principal) { Authentication client = (Authentication) principal; if (!client.isAuthenticated()) { throw new InsufficientAuthenticationException("The client is not authenticated."); } String clientId = client.getName(); if (client instanceof OAuth2Authentication) { // Might be a client and user combined authentication clientId = ((OAuth2Authentication) client).getOAuth2Request().getClientId(); } return clientId; } @ExceptionHandler(ClientRegistrationException.class) public ResponseEntity<OAuth2Exception> handleClientRegistrationException(Exception e) throws Exception { logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); return getExceptionTranslator().translate(new BadClientCredentialsException()); } @ExceptionHandler(OAuth2Exception.class) public ResponseEntity<OAuth2Exception> handleException(Exception e) throws Exception { logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); return getExceptionTranslator().translate(e); } private ResponseEntity<OAuth2AccessToken> getResponse(OAuth2AccessToken accessToken, String callback) { HttpHeaders headers = new HttpHeaders(); headers.set("Cache-Control", "no-store"); headers.set("Pragma", "no-cache"); if(StringUtils.hasText(callback)) headers.set("callback", callback); return new ResponseEntity<OAuth2AccessToken>(accessToken, headers, HttpStatus.OK); } private boolean isRefreshTokenRequest(Map<String, String> parameters) { return "refresh_token".equals(parameters.get("grant_type")) && parameters.get("refresh_token") != null; } private boolean isAuthCodeRequest(Map<String, String> parameters) { return "authorization_code".equals(parameters.get("grant_type")) && parameters.get("code") != null; } public void setOAuth2RequestValidator(OAuth2RequestValidator oauth2RequestValidator) { this.oauth2RequestValidator = oauth2RequestValidator; } }