Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 509 Vote(s) - 3.46 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Spring Boot + Oauth2 client credentials

#1
I am trying to protect my microservices on Spring Boot using Oath2 with Client Credentials flow.

By the way, those microservices will only talk each other over the middleware layer, I mean no user credentials are needed to allow the authorization (user login process as Facebook).

I have looked for samples on the Internet showing how to create an authorization and resource server to manage this communication. However I just found examples explaining how to do it using user credentials (three legs).

Does anyone have any sample how to do it in Spring Boot and Oauth2? If it is possible give further details about the scopes used, token exchanging would be grateful.

Reply

#2
We have REST services protected with Oauth2 Client credentials scheme. The Resource and authorization service are running in the same app, but can be split into different apps.

@Configuration
public class SecurityConfig {

@Configuration
@EnableResourceServer
protected static class ResourceServer extends ResourceServerConfigurerAdapter {

// Identifies this resource server. Usefull if the AuthorisationServer authorises multiple Resource servers
private static final String RESOURCE_ID = "*****";

@Resource(name = "OAuth")
@Autowired
DataSource dataSource;

@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests().anyRequest().authenticated();
// @formatter:on
}

@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(RESOURCE_ID);
resources.tokenStore(tokenStore());
}

@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
}

@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

@Resource(name = "OAuth")
@Autowired
DataSource dataSource;

@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore());
}

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource);
}
}
}

Datasource config for the Oauth2 tables:

@Bean(name = "OAuth")
@ConfigurationProperties(prefix="datasource.oauth")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}

Communicating with authentication & resource server goes as followed

curl -H "Accept: application/json" user:password@localhost:8080/oauth/token -d grant_type=client_credentials
curl -H "Authorization: Bearer token" localhost:8080/...

The following record is present in the Oauth2 Database:

client_id resource_ids client_secret scope authorized_grant_types web_server_redirect_uri authorities access_token_validity refresh_token_validity additional_information autoapprove
user **** password NULL client_credentials NULL X NULL NULL NULL NULL


Resttemplate configuration in client application

@Configuration
@EnableOAuth2Client
public class OAuthConfig {

@Value("${OAuth2ClientId}")
private String oAuth2ClientId;

@Value("${OAuth2ClientSecret}")
private String oAuth2ClientSecret;

@Value("${Oauth2AccesTokenUri}")
private String accessTokenUri;

@Bean
public RestTemplate oAuthRestTemplate() {
ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setId("1");
resourceDetails.setClientId(oAuth2ClientId);
resourceDetails.setClientSecret(oAuth2ClientSecret);
resourceDetails.setAccessTokenUri(accessTokenUri);

/*

When using @EnableOAuth2Client spring creates a OAuth2ClientContext for us:

"The OAuth2ClientContext is placed (for you) in session scope to keep the state for different users separate.
Without that you would have to manage the equivalent data structure yourself on the server,
mapping incoming requests to users, and associating each user with a separate instance of the OAuth2ClientContext."
(

[To see links please register here]

)

Internally the SessionScope works with a threadlocal to store variables, hence a new thread cannot access those.
Therefore we can not use @Async

Solution: create a new OAuth2ClientContext that has no scope.
*Note: this is only safe when using client_credentials as OAuth grant type!

*/

// OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, oauth2ClientContext);
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, new DefaultOAuth2ClientContext());

return restTemplate;
}
}

You can inject the restTemplate to talk (Asynchronously) to the Oauth2 secured service.
We do not use scope at the moment.
Reply

#3
Update with Spring-boot-2.7 and Java 17.

[To see links please register here]



public class SecurityConfig {

@Value("${spring.social.facebook.appSecret}")
String appSecret;

@Value("${spring.social.facebook.appId}")
String appId;

@Autowired
private UserDetailsService userDetailsService;

@Autowired
private FacebookConnectionSignup facebookConnectionSignup;

@Bean
public AuthenticationManager authManager(HttpSecurity http) throws Exception {
return http.getSharedObject(AuthenticationManagerBuilder.class)
.userDetailsService(userDetailsService)
.and()
.build();
}

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.antMatchers("/login*", "/signin/**", "/signup/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout();
return http.build();
}

@Bean
// @Primary
public ProviderSignInController providerSignInController() {
ConnectionFactoryLocator connectionFactoryLocator = connectionFactoryLocator();
UsersConnectionRepository usersConnectionRepository = getUsersConnectionRepository(connectionFactoryLocator);
((InMemoryUsersConnectionRepository) usersConnectionRepository).setConnectionSignUp(facebookConnectionSignup);
return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new FacebookSignInAdapter());
}

private ConnectionFactoryLocator connectionFactoryLocator() {
ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
registry.addConnectionFactory(new FacebookConnectionFactory(appId, appSecret));
return registry;
}

private UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
return new InMemoryUsersConnectionRepository(connectionFactoryLocator);
}
}

FacebookSignInAdapter

@Service
public class FacebookSignInAdapter implements SignInAdapter {
@Override
public String signIn(String localUserId, Connection<?> connection, NativeWebRequest request) {
System.out.println(" ====== Sign In adapter");
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(connection.getDisplayName(), null, Arrays.asList(new SimpleGrantedAuthority("FACEBOOK_USER"))));
return null;
}
}


Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through