简体   繁体   中英

Spring OAuth2 - User info in Client Credentials grant type

I've been developing Spring Cloud (with Netflix OSS stack) microservices architecture for some time. As you would expect, I've separated authorization server as a stand alone microservice. My front end application uses "password" grant type for user login purposes. However, I'm using "client-credentials" grant type for the rest calls that I make from front-end service to other back-end services. Client-credentials grant type is being used among other back-end services as well. By doing so, I am not able to get who is the actual invoker (currently logged in user) of a request. Is there a way to inject authentication and authorization info of the principal to the token that is being issued in client-credentials grant?

My Authorization Server Config class

@Configuration
@EnableAuthorizationServer
@Order(Ordered.HIGHEST_PRECEDENCE)
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {

@Autowired
private AuthenticationManager authenticationManager;

@Override
public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    oauthServer.tokenKeyAccess("permitAll()")
        .checkTokenAccess("isAuthenticated()");
}

@Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
    clients.inMemory()
        .withClient("testclient")
        .secret("{noop}testsecret")
        .authorizedGrantTypes("authorization_code","password","client_credentials")
        .scopes("ui")
        .autoApprove(true)
    // .accessTokenValiditySeconds(3600)
    .and()
        .withClient("backend-service")
        .secret("{noop}backendsecret")
        .authorizedGrantTypes("client_credentials","refresh_token")
        .scopes("server")
         .autoApprove(true)
}
@Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints.authenticationManager(authenticationManager);
    endpoints.tokenEnhancer(tokenEnhancer());
    endpoints.tokenStore(tokenStore());
}

@Bean
public TokenStore tokenStore() {
    //return new JdbcTokenStore(dataSource);
    return new InMemoryTokenStore();
}
@Bean
@Primary
public AuthorizationServerTokenServices tokenServices() {
    DefaultTokenServices tokenServices = new DefaultTokenServices();
    tokenServices.setTokenEnhancer(tokenEnhancer());
    tokenServices.setTokenStore(tokenStore());
    return tokenServices;
}

@Bean
public TokenEnhancer tokenEnhancer() {
    return new CustomTokenEnhancer();
}

Security Config Class

@Configuration
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.csrf().disable()
            .requestMatchers()
                .antMatchers("/login", "/oauth/authorize")
                .and()
                .authorizeRequests()
                .antMatchers("/resources/**", "/src/main/webapp/**","/css/**","/images/**").permitAll()
            .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
            .and()
            .logout()
            .permitAll().and().httpBasic().disable();

}

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/static/**","/resources/**", "/src/main/webapp/**","/css/**","/images/**");
}

@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().withUser("admin").password("{noop}a1b2c3#").roles("User");
}

}

I've tried to implement a Token Enhancer class to propogate additional data in token. However, I don't think this is the correct and secure way for what I'm trying to achieve.

public class CustomTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {
    final Map<String, Object> additionalInfo = new HashMap<>();

    additionalInfo.put("customInfo", "testdata");

    ((DefaultOAuth2AccessToken) oAuth2AccessToken).setAdditionalInformation(additionalInfo);

    return oAuth2AccessToken;
    }
}

Your assistance would be appreciated.

If you are using an oauth token generated using Client Credentials then you can not get user information. You can only get source of the request (client).

If want user information across micro services then you have to use password grant type to generate oauth token.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM