EnableOAuth2Sso simultaneously for multiple social networks

五迷三道 提交于 2019-11-29 15:48:27

The @EnableOAuth2Sso feature wasn't designed to support multiple providers as simple YAML declarations. Instead of using that you need to install 2 separate OAuth2AuthenticationProcessingFilters in your security configuration, each with a different login path, and then link to them from a UI.

Indeed, please check the link posted by Mario (not sure why it was downvoted..): social_login_manual

The link says that @EnableOAuth2Sso is essentially a combination of @EnableOAuth2Client and some additional magic. The downside is you can't easily customize its behavior to support multiple providers. Thus in the tutorial it is suggested to replace it with @EnableOAuth2Client instead and go by repeating what @EnableOAuth2Sso does under the hood with some custom additions.

So, here is how it looks like:

@SpringBootApplication
@EnableOAuth2Client
@RestController
public class SocialApplication extends WebSecurityConfigurerAdapter {

   private Filter ssoFilter() {
      CompositeFilter filter = new CompositeFilter();
      List<Filter> filters = new ArrayList<>();
      filters.add(ssoFilter(facebook(), "/login/facebook"));
      filters.add(ssoFilter(github(), "/login/github"));
      filter.setFilters(filters);
      return filter;
    }



 private Filter ssoFilter(ClientResources client, String path) {
      OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(path);
      OAuth2RestTemplate template = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
      filter.setRestTemplate(template);
      filter.setTokenServices(new UserInfoTokenServices(
          client.getResource().getUserInfoUri(), client.getClient().getClientId()));
      return filter;
    }

  @Bean
    @ConfigurationProperties("github")
    public ClientResources github() {
      return new ClientResources();
    }

  @Bean
    @ConfigurationProperties("facebook")
    public ClientResources facebook() {
      return new ClientResources();
    }

}

class ClientResources {

  @NestedConfigurationProperty
  private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();

  @NestedConfigurationProperty
  private ResourceServerProperties resource = new ResourceServerProperties();

  public AuthorizationCodeResourceDetails getClient() {
    return client;
  }

  public ResourceServerProperties getResource() {
    return resource;
  }
}

facebook:
  client:
    clientId: 233668646673605
    clientSecret: 33b17e044ee6a4fa383f46ec6e28ea1d
    accessTokenUri: https://graph.facebook.com/oauth/access_token
    userAuthorizationUri: https://www.facebook.com/dialog/oauth
    tokenName: oauth_token
    authenticationScheme: query
    clientAuthenticationScheme: form
  resource:
    userInfoUri: https://graph.facebook.com/me
github:
  client:
    clientId: bd1c0a783ccdd1c9b9e4
    clientSecret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1
    accessTokenUri: https://github.com/login/oauth/access_token
    userAuthorizationUri: https://github.com/login/oauth/authorize
    clientAuthenticationScheme: form
  resource:
    userInfoUri: https://api.github.com/user

I also stumbled upon this and many other questions about multiple authentication provider support. Syer's answer that core @EnableOAuth2Sso annotation wasn't designed for this was actually very helpful. It made me look elsewhere.

Benefiting from Nimbus OAuth library I designed another approach. It probably isn't clean and nice, but it does what I was planning. Separate authentication providers are defined in properties and selected based on URI path.

This is what I came up with: https://bitbucket.org/klaalo/orcidconnect/src/f3e4fada9827e47bd33efd579fd020c41e37ee2a/src/main/java/fi/csc/orcidconnect/oauth2client/

Basically, a provider is selected based on a decision made by DelegatingAuthenticationProviderEndpoint in SecurityConfiguration (on default package). AuthenticationProcessingFilter is waiting for authentication events and making redirects to authentication providers. On return it will validate received code and carries AuthenticationToken for custom AuthenticationProvider to evaluate.

Received UserDetails are persisted to User object in a Map.

Hope this helps.

The link you have provided only shows how to use the @EnableOAuth2Sso facilities that enables a single Authentication Server provider. In order to implement multiple providers you should follow :

https://spring.io/guides/tutorials/spring-boot-oauth2/#_social_login_manual

and implement a filter for each provider.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!