@Test
  public void testAuthorizationCodeGrant() {

    Authentication userAuthentication =
        new UsernamePasswordAuthenticationToken(
            "marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));

    parameters.clear();
    parameters.put(OAuth2Utils.CLIENT_ID, "foo");
    parameters.put(OAuth2Utils.SCOPE, "scope");
    OAuth2Request storedOAuth2Request =
        RequestTokenFactory.createOAuth2Request(
            parameters, "foo", null, true, Collections.singleton("scope"), null, null, null);

    String code =
        authorizationCodeServices.createAuthorizationCode(
            new OAuth2Authentication(storedOAuth2Request, userAuthentication));
    parameters.putAll(storedOAuth2Request.getRequestParameters());
    parameters.put("code", code);

    TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters);

    AuthorizationCodeTokenGranter granter =
        new AuthorizationCodeTokenGranter(
            providerTokenServices, authorizationCodeServices, clientDetailsService, requestFactory);
    OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest);
    assertTrue(providerTokenServices.loadAuthentication(token.getValue()).isAuthenticated());
  }
  @Test
  public void testScopesRegex() throws Exception {

    OAuth2Request clientAuthentication =
        RequestTokenFactory.createOAuth2Request(
            null,
            "foo",
            null,
            false,
            Collections.singleton("ns_admin:read"),
            null,
            null,
            null,
            null);

    Authentication userAuthentication = null;
    OAuth2Authentication oAuth2Authentication =
        new OAuth2Authentication(clientAuthentication, userAuthentication);
    MethodInvocation invocation =
        new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), "testOauthClient"));
    EvaluationContext context = handler.createEvaluationContext(oAuth2Authentication, invocation);
    Expression expression =
        handler.getExpressionParser().parseExpression("#oauth2.hasScopeMatching('.*_admin:read')");
    assertTrue((Boolean) expression.getValue(context));
    expression =
        handler
            .getExpressionParser()
            .parseExpression("#oauth2.hasAnyScopeMatching('.*_admin:write','.*_admin:read')");
    assertTrue((Boolean) expression.getValue(context));
  }
  @Test
  public void testOauthClient() throws Exception {
    AuthorizationRequest request = new AuthorizationRequest("foo", Collections.singleton("read"));
    request.setResourceIdsAndAuthoritiesFromClientDetails(
        new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT"));
    Authentication userAuthentication = null;

    OAuth2Request clientAuthentication =
        RequestTokenFactory.createOAuth2Request(
            request.getRequestParameters(),
            request.getClientId(),
            request.getAuthorities(),
            request.isApproved(),
            request.getScope(),
            request.getResourceIds(),
            request.getRedirectUri(),
            request.getResponseTypes(),
            request.getExtensions());

    OAuth2Authentication oAuth2Authentication =
        new OAuth2Authentication(clientAuthentication, userAuthentication);
    MethodInvocation invocation =
        new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), "testOauthClient"));
    EvaluationContext context = handler.createEvaluationContext(oAuth2Authentication, invocation);
    Expression expression =
        handler.getExpressionParser().parseExpression("#oauth2.clientHasAnyRole('ROLE_CLIENT')");
    assertTrue((Boolean) expression.getValue(context));
  }
  @Test
  public void testFindAccessTokensByUserName() {
    OAuth2Authentication expectedAuthentication =
        new OAuth2Authentication(
            RequestTokenFactory.createOAuth2Request("id", false),
            new TestAuthentication("test2", false));
    OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken");
    getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication);

    Collection<OAuth2AccessToken> actualOAuth2AccessTokens =
        getTokenStore().findTokensByUserName("test2");
    assertEquals(1, actualOAuth2AccessTokens.size());
  }
  @Test
  public void testReEvaluationWithDifferentRoot() throws Exception {
    Expression expression = handler.getExpressionParser().parseExpression("#oauth2.isClient()");
    MethodInvocation invocation =
        new SimpleMethodInvocation(
            this, ReflectionUtils.findMethod(getClass(), "testNonOauthClient"));
    Authentication clientAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar");
    EvaluationContext context = handler.createEvaluationContext(clientAuthentication, invocation);
    assertFalse((Boolean) expression.getValue(context));

    OAuth2Request storedOAuth2Request =
        RequestTokenFactory.createOAuth2Request(
            null, "foo", null, true, Collections.singleton("read"), null, null, null, null);

    OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(storedOAuth2Request, null);
    EvaluationContext anotherContext =
        handler.createEvaluationContext(oAuth2Authentication, invocation);
    assertTrue((Boolean) expression.getValue(anotherContext));
  }
  @Test
  public void testAuthorizationRedirectMismatch() {
    Map<String, String> initialParameters = new HashMap<String, String>();
    initialParameters.put(OAuth2Utils.REDIRECT_URI, "https://redirectMe");
    // AuthorizationRequest initialRequest = createFromParameters(initialParameters);
    // we fake a valid resolvedRedirectUri because without the client would never come this far
    // initialRequest.setRedirectUri(initialParameters.get(REDIRECT_URI));

    parameters.clear();
    parameters.put(OAuth2Utils.REDIRECT_URI, "https://redirectMe");
    parameters.put(OAuth2Utils.CLIENT_ID, "foo");
    OAuth2Request storedOAuth2Request =
        RequestTokenFactory.createOAuth2Request(
            parameters, "foo", null, true, null, null, "https://redirectMe", null);

    Authentication userAuthentication =
        new UsernamePasswordAuthenticationToken(
            "marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
    String code =
        authorizationCodeServices.createAuthorizationCode(
            new OAuth2Authentication(storedOAuth2Request, userAuthentication));

    Map<String, String> authorizationParameters = new HashMap<String, String>();
    authorizationParameters.put("code", code);

    // AuthorizationRequest oAuth2Request = createFromParameters(initialParameters);
    // oAuth2Request.setRequestParameters(authorizationParameters);

    TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters);
    tokenRequest.setRequestParameters(authorizationParameters);

    AuthorizationCodeTokenGranter granter =
        new AuthorizationCodeTokenGranter(
            providerTokenServices, authorizationCodeServices, clientDetailsService, requestFactory);
    try {
      granter.getOAuth2Authentication(client, tokenRequest);
      fail("RedirectMismatchException because of null redirect_uri in authorizationRequest");
    } catch (RedirectMismatchException e) {
    }
  }
/** @author Dave Syer */
public class TokenServicesWithTokenEnhancerTests {

  private DefaultTokenServices tokenServices = new DefaultTokenServices();

  private JwtTokenEnhancer jwtTokenEnhancer = new JwtTokenEnhancer();

  private TokenEnhancerChain enhancer = new TokenEnhancerChain();

  private UsernamePasswordAuthenticationToken user =
      new UsernamePasswordAuthenticationToken(
          "bob", "N/A", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));

  private OAuth2Request request =
      RequestTokenFactory.createOAuth2Request("client", true, Arrays.asList("read"));

  private OAuth2Authentication authentication = new OAuth2Authentication(request, user);

  @Before
  public void init() throws Exception {
    tokenServices.setClientDetailsService(
        new InMemoryClientDetailsServiceBuilder()
            .withClient("client")
            .authorizedGrantTypes("authorization_code")
            .scopes("read")
            .secret("secret")
            .and()
            .build());
    enhancer.setTokenEnhancers(Arrays.<TokenEnhancer>asList(jwtTokenEnhancer));
    jwtTokenEnhancer.afterPropertiesSet();
    tokenServices.setTokenStore(new JwtTokenStore(jwtTokenEnhancer));
    tokenServices.setTokenEnhancer(enhancer);
  }

  @Test
  public void scopePreservedWhenTokenCreated() {
    assertEquals("[read]", tokenServices.createAccessToken(authentication).getScope().toString());
    tokenServices.getAccessToken(authentication);
  }

  @Test
  public void scopePreservedWhenTokenDecoded() {
    OAuth2AccessToken token = tokenServices.createAccessToken(authentication);
    assertEquals(
        "[read]",
        tokenServices
            .loadAuthentication(token.getValue())
            .getOAuth2Request()
            .getScope()
            .toString());
  }

  @Test
  public void customUserPreservedWhenTokenDecoded() {
    DefaultAccessTokenConverter tokenConverter = new DefaultAccessTokenConverter();
    tokenConverter.setUserTokenConverter(
        new UserAuthenticationConverter() {

          @Override
          public Authentication extractAuthentication(Map<String, ?> map) {
            return new FooAuthentication((String) map.get("user"));
          }

          @Override
          public Map<String, ?> convertUserAuthentication(Authentication userAuthentication) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("user", userAuthentication.getName());
            map.put("foo", "bar");
            return map;
          }
        });
    jwtTokenEnhancer.setAccessTokenConverter(tokenConverter);
    OAuth2AccessToken token = tokenServices.createAccessToken(authentication);
    assertEquals(
        "bob",
        tokenServices.loadAuthentication(token.getValue()).getUserAuthentication().getName());
  }

  @Test
  public void additionalInfoPreservedWhenTokenDecoded() {
    TokenEnhancer info =
        new TokenEnhancer() {
          @Override
          public OAuth2AccessToken enhance(
              OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
            DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken);
            result.getAdditionalInformation().put("foo", "bar");
            return result;
          }
        };
    enhancer.setTokenEnhancers(Arrays.<TokenEnhancer>asList(info, jwtTokenEnhancer));
    OAuth2AccessToken token = tokenServices.createAccessToken(authentication);
    assertEquals("bar", token.getAdditionalInformation().get("foo"));
    assertEquals(
        "bar",
        tokenServices.readAccessToken(token.getValue()).getAdditionalInformation().get("foo"));
  }

  @SuppressWarnings("serial")
  protected static class FooAuthentication extends AbstractAuthenticationToken {

    private String name;

    public FooAuthentication(String name) {
      super(AuthorityUtils.commaSeparatedStringToAuthorityList("USER"));
      this.name = name;
    }

    @Override
    public Object getCredentials() {
      return "N/A";
    }

    @Override
    public Object getPrincipal() {
      return name;
    }
  }
}