How do I implement Github OAuth2 login with Spring Boot using only REST api?

563 Views Asked by At

I am trying to implement Signup with Github in a sample project, where front-end code is made up of ReactJS and Backend API is made up of Spring Boot.

I am not using Server Template Engines such as ThymeLeaf or Mustache, but only creating RESTful APIs.

Below is my Spring Security Configuration.

@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final GithubOAuth2UserService githubOAuth2UserService;

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

        http
                .httpBasic().disable()
                .csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                    .authorizeRequests()
                        .antMatchers("/v1/health-check")
                        .permitAll()
                .and()
                    .logout()
                        .logoutSuccessUrl("/")
                .and()
                    .oauth2Login()
                        .userInfoEndpoint()
                            .userService(githubOAuth2UserService);
    }
}
  • Below is my code for GithubOAuth2UserService
@RequiredArgsConstructor
@Service
public class GithubOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
    private final UserRepository userRepository;

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2UserService<OAuth2UserRequest, OAuth2User> delegate = new DefaultOAuth2UserService();
        OAuth2User oAuth2User = delegate.loadUser(userRequest);

        String registrationId = userRequest.getClientRegistration().getRegistrationId();
        System.out.println(registrationId);
        String userNameAttributeName = userRequest.getClientRegistration()
                .getProviderDetails().getUserInfoEndpoint()
                .getUserNameAttributeName();
        System.out.println(userNameAttributeName);

        OAuthAttributes attributes = OAuthAttributes.ofGithub(userNameAttributeName, oAuth2User.getAttributes());

        User user = saveUser(attributes);

        return new DefaultOAuth2User(
                Collections.singleton(new SimpleGrantedAuthority(user.getRole().name())),
                attributes.getAttributes(),
                attributes.getNameAttributeKey()
        );
    }

    @Transactional
    protected User saveUser(OAuthAttributes attributes) {
        System.out.println("SAVE USER!");
        if(userRepository.findByEmail(attributes.getEmail()).isPresent()) {
            throw new UserEmailConflictException();
        } else {
            User user = attributes.toEntity();
            return userRepository.save(user);
        }
    }
}
  • Finally, OAuthAttributes is as below.
@Getter
public class OAuthAttributes {
    private Map<String, Object> attributes;
    private String nameAttributeKey;
    private String name;
    private String email;

    @Builder
    public OAuthAttributes(Map<String, Object> attributes, String nameAttributeKey, String name, String email) {
        this.attributes = attributes;
        this.nameAttributeKey = nameAttributeKey;
        this.name = name;
        this.email = email;
    }

    public static OAuthAttributes ofGithub(String userNameAttributeName, Map<String, Object> attributes) {
        return OAuthAttributes.builder()
                .name((String) attributes.get("name"))
                .email((String) attributes.get("email"))
                .attributes(attributes)
                .nameAttributeKey(userNameAttributeName)
                .build();
    }

    public User toEntity() {
        return User.builder()
                .name(name)
                .email(email)
                .build();
    }
}
  • Via PostMan, I can see the API result as below, but my ReactJS code doesn't show anything, and just refreshes the page.

enter image description here

  • On ReactJS, it calls this API like below.
// OnClick function
const result = await axios.get("http://localhost:8080/oauth2/authorization/github");
console.log(result);
  • UPDATE

  • I am getting CORS policy violation, and I configured this using a configuration class below. Is this related to SecurityConfig class ?

@Configuration
@EnableWebMvc
public class CORSConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("*").allowedMethods("*");
    }
}

Thank you so much in advance. If any code needs to be shown, I will happily edit this post.

0

There are 0 best solutions below