Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Social login, spring-security-oauth2 and spring-security-jwt?

I'm developing a rest service which is going to be available in browser via browser single page app and a mobile app. At the moment my service is working without spring at all. The oauth2 client is implemented inside filters so to say "by hand".

I'm trying to migrate it to spring boot. Much manuals read and much info googled and I'm trying to understand if the following is actually possible for a customer:

  1. Authorize with facebook oauth2 service (and get an access_token) with all the help from spring-security-oauth2.

  2. Create a JWT and pass it to the client so that all further requests are backed with the JWT.

Since in my opinion spring boot is all about the configuration and declarations I want to understand if this is possible with spring-security-oauth2 and spring-security-jwt?

I'm not askng for a solution but just a yes/no from knowledge bearers since I'm deep in the spring manuals and the answer becomes further...

like image 655
Grigory Avatar asked May 24 '16 19:05

Grigory


People also ask

What is the difference between JWT and Spring Security?

JSON Web Token has a broader approval, being mentioned in 29 company stacks & 15 developers stacks; compared to Spring Security, which is listed in 12 company stacks and 9 developer stacks.

Should I use JWT or OAuth2?

If you want to provide an API to 3rd party clients, you must use OAuth2 also. OAuth2 is very flexible. JWT implementation is very easy and does not take long to implement. If your application needs this sort of flexibility, you should go with OAuth2.

Does Spring Security use JWT?

Disclaimer: Spring Security 5+ has released OAuth JWT support. Using the latest version of OAuth for JWT support is recommended over the use of custom security or filters. Spring is considered a trusted framework in the Java ecosystem and is widely used.

Does Spring Security use OAuth2?

The Spring Security OAuth project has reached end of life and is no longer actively maintained by VMware, Inc. This project has been replaced by the OAuth2 support provided by Spring Security and Spring Authorization Server.


1 Answers

short answer: Yes you can do it!

You have to add security dependencies to your build.gradle or pom.xml file:

compile "org.springframework.boot:spring-boot-starter-security"
compile "org.springframework.security:spring-security-config"
compile "org.springframework.security:spring-security-data"
compile "org.springframework.security:spring-security-web"

compile "org.springframework.social:spring-social-security"
compile "org.springframework.social:spring-social-google"
compile "org.springframework.social:spring-social-facebook"
compile "org.springframework.social:spring-social-twitter"

then you have to add social config to your project alongside with your security config:

@Configuration
@EnableSocial
public class SocialConfiguration implements SocialConfigurer {

    private final Logger log = LoggerFactory.getLogger(SocialConfiguration.class);

    private final SocialUserConnectionRepository socialUserConnectionRepository;

    private final Environment environment;

    public SocialConfiguration(SocialUserConnectionRepository socialUserConnectionRepository,
            Environment environment) {

        this.socialUserConnectionRepository = socialUserConnectionRepository;
        this.environment = environment;
    }

    @Bean
    public ConnectController connectController(ConnectionFactoryLocator connectionFactoryLocator,
            ConnectionRepository connectionRepository) {

        ConnectController controller = new ConnectController(connectionFactoryLocator, connectionRepository);
        controller.setApplicationUrl(environment.getProperty("spring.application.url"));
        return controller;
    }

    @Override
    public void addConnectionFactories(ConnectionFactoryConfigurer connectionFactoryConfigurer, Environment environment) {
        // Google configuration
        String googleClientId = environment.getProperty("spring.social.google.client-id");
        String googleClientSecret = environment.getProperty("spring.social.google.client-secret");
        if (googleClientId != null && googleClientSecret != null) {
            log.debug("Configuring GoogleConnectionFactory");
            connectionFactoryConfigurer.addConnectionFactory(
                new GoogleConnectionFactory(
                    googleClientId,
                    googleClientSecret
                )
            );
        } else {
            log.error("Cannot configure GoogleConnectionFactory id or secret null");
        }

        // Facebook configuration
        String facebookClientId = environment.getProperty("spring.social.facebook.client-id");
        String facebookClientSecret = environment.getProperty("spring.social.facebook.client-secret");
        if (facebookClientId != null && facebookClientSecret != null) {
            log.debug("Configuring FacebookConnectionFactory");
            connectionFactoryConfigurer.addConnectionFactory(
                new FacebookConnectionFactory(
                    facebookClientId,
                    facebookClientSecret
                )
            );
        } else {
            log.error("Cannot configure FacebookConnectionFactory id or secret null");
        }

        // Twitter configuration
        String twitterClientId = environment.getProperty("spring.social.twitter.client-id");
        String twitterClientSecret = environment.getProperty("spring.social.twitter.client-secret");
        if (twitterClientId != null && twitterClientSecret != null) {
            log.debug("Configuring TwitterConnectionFactory");
            connectionFactoryConfigurer.addConnectionFactory(
                new TwitterConnectionFactory(
                    twitterClientId,
                    twitterClientSecret
                )
            );
        } else {
            log.error("Cannot configure TwitterConnectionFactory id or secret null");
        }

        // jhipster-needle-add-social-connection-factory
    }

    @Override
    public UserIdSource getUserIdSource() {
        return new AuthenticationNameUserIdSource();
    }

    @Override
    public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
        return new CustomSocialUsersConnectionRepository(socialUserConnectionRepository, connectionFactoryLocator);
    }

    @Bean
    public SignInAdapter signInAdapter(UserDetailsService userDetailsService, JHipsterProperties jHipsterProperties,
            TokenProvider tokenProvider) {
        return new CustomSignInAdapter(userDetailsService, jHipsterProperties,
            tokenProvider);
    }

    @Bean
    public ProviderSignInController providerSignInController(ConnectionFactoryLocator connectionFactoryLocator, UsersConnectionRepository usersConnectionRepository, SignInAdapter signInAdapter) {
        ProviderSignInController providerSignInController = new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, signInAdapter);
        providerSignInController.setSignUpUrl("/social/signup");
        providerSignInController.setApplicationUrl(environment.getProperty("spring.application.url"));
        return providerSignInController;
    }

    @Bean
    public ProviderSignInUtils getProviderSignInUtils(ConnectionFactoryLocator connectionFactoryLocator, UsersConnectionRepository usersConnectionRepository) {
        return new ProviderSignInUtils(connectionFactoryLocator, usersConnectionRepository);
    }
}

then you have to write adapter for your social login:

public class CustomSignInAdapter implements SignInAdapter {

    @SuppressWarnings("unused")
    private final Logger log = LoggerFactory.getLogger(CustomSignInAdapter.class);

    private final UserDetailsService userDetailsService;

    private final JHipsterProperties jHipsterProperties;

    private final TokenProvider tokenProvider;


    public CustomSignInAdapter(UserDetailsService userDetailsService, JHipsterProperties jHipsterProperties,
            TokenProvider tokenProvider) {
        this.userDetailsService = userDetailsService;
        this.jHipsterProperties = jHipsterProperties;
        this.tokenProvider = tokenProvider;
    }

    @Override
    public String signIn(String userId, Connection<?> connection, NativeWebRequest request){
        try {
            UserDetails user = userDetailsService.loadUserByUsername(userId);
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
                user,
                null,
                user.getAuthorities());

            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            String jwt = tokenProvider.createToken(authenticationToken, false);
            ServletWebRequest servletWebRequest = (ServletWebRequest) request;
            servletWebRequest.getResponse().addCookie(getSocialAuthenticationCookie(jwt));
        } catch (AuthenticationException ae) {
            log.error("Social authentication error");
            log.trace("Authentication exception trace: {}", ae);
        }
        return jHipsterProperties.getSocial().getRedirectAfterSignIn();
    }

    private Cookie getSocialAuthenticationCookie(String token) {
        Cookie socialAuthCookie = new Cookie("social-authentication", token);
        socialAuthCookie.setPath("/");
        socialAuthCookie.setMaxAge(10);
        return socialAuthCookie;
    }
}

you can find sample project in my github: https://github.com/ksadjad/oauth-test

like image 64
ksadjad Avatar answered Oct 05 '22 23:10

ksadjad



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!