OAuth2

기본 설정

  • spring boot 2.0.0
  • spring security 5.0.0

Dependency

/*oauth2 를 위해 아래 2개의 dependencies 필요.*/
compile ('org.springframework.security:spring-security-oauth2-client')
compile ('org.springframework.security:spring-security-oauth2-jose')

Configuration

  • application.yml
spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: 283082856244-lfjqd0vbudb2c1fvolgl6d5a444fc3im.apps.googleusercontent.com
            client-secret: 4w6UG90Rod6rzPGwax_LLwDQ  //랜덤으로 적은 것임
          facebook:
            client-id: 429830609684099
            client-secret: 2940f70d34e1ca670b5cb326515e7a69 //랜덤으로 적은 것임

SecurityConfig

아래 설정대로라면, /secret/** 또는 /userinfo 접속시 oauth2Login 페이지로 redirect 하게 된다.

package com.example.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
public class SecurityConfig {

    @Configuration
    public static class WebBaseSecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .authorizeRequests()
                        .antMatchers("/secret/**", "/userinfo").authenticated()
                        .anyRequest().permitAll()
                    .and()
                    .oauth2Login()
                        .loginPage("/signIn");
        }
    }
}

redirect 된 페이지에서는 /oauth2/authorization/{registrationId} 로 redirect 하는 <a> 태그가 있으면 된다. 클릭시 해당 oauth2 provider 의 로그인 페이지로 간다. (/oauth2/authorization/google)

웹에서

  • controller
    • 파라미터로 OAuth2AuthenticationToken authentication 를 받는다.
package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;

import java.util.Collections;
import java.util.Map;

@Controller
public class HomeController {

    @Autowired
    private OAuth2AuthorizedClientService authorizedClientService;

    @GetMapping("/")
    public String index() {
        return "index";
    }

    @RequestMapping("/secret")
    public String oauth2SignIn(Model model, OAuth2AuthenticationToken authentication) {
        OAuth2AuthorizedClient authorizedClient = this.getAuthorizedClient(authentication);
        model.addAttribute("userName", authentication.getName()); //id
        model.addAttribute("clientName", authorizedClient.getClientRegistration().getClientName()); //google, facebook 등

        return "secret";
    }

    @RequestMapping("/userinfo")
    public String userInfo(Model model, OAuth2AuthenticationToken authentication) {

        OAuth2AuthorizedClient authorizedClient = this.getAuthorizedClient(authentication);
        model.addAttribute("userAttributes", this.oauth2UserAttributes(authorizedClient));

        return "userInfo";
    }

    private OAuth2AuthorizedClient getAuthorizedClient(OAuth2AuthenticationToken authentication) {
        return this.authorizedClientService.loadAuthorizedClient(
                authentication.getAuthorizedClientRegistrationId( ), authentication.getName());
    }

    /**
     * @param authorizedClient
     * @return -
     * * @examples
     * * * @google
     * * * * sub : 110233381282913480987  => authentication.getName() 과 같다.
     * * * * name : ­길병찬[소프트웨어학부]     => given_name + " " + family_name 이다.
     * * * * given_name : 길병찬[소프트웨어학부]
     * * * * family_name :  ­
     * * * * picture : https://lh3.googleusercontent.com/-XdUIqdMkCWA/AAAAAAAAAAI/AAAAAAAAAAA/4252rscbv5M/photo.jpg
     * * * * email : [email protected]
     * * * * email_verified : true
     * * * * locale : ko
     * * * * hd : kookmin.ac.kr  => 이메일 도메인을 의미한다.
     * 
     * * * @facebook
     * * * * name : 길병찬
     * * * * id : 1236697273129887  => authentication.getName() 과 같다.
     */
    private Map oauth2UserAttributes(OAuth2AuthorizedClient authorizedClient) {
        String userInfoEndpointUri = authorizedClient.getClientRegistration()
                .getProviderDetails().getUserInfoEndpoint().getUri();

        Map userAttributes = Collections.emptyMap();

        if (!StringUtils.isEmpty(userInfoEndpointUri)) {
            RestTemplate restTemplate = new RestTemplate();
            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.AUTHORIZATION, "Bearer " + authorizedClient.getAccessToken()
                    .getTokenValue());
            String body = "";
            HttpEntity entity = new HttpEntity(body, headers);
            ResponseEntity<Map> response = restTemplate
                    .exchange(userInfoEndpointUri, HttpMethod.GET, entity, Map.class);
            userAttributes = response.getBody();
        }

        return userAttributes;
    }

    @GetMapping("/signIn")
    public String signIn() {
        return "signIn";
    }
}

REST 하게

앱에서

Custom Login Page

(SecurityConfig 에서 설정한 loginPageuriController 에서 @GetMapping하는 것이 필요하다.)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>로그인</h1>

<a th:href="@{/oauth2/authorization/google}">sign in with Google</a>
<br>
<a th:href="@{/oauth2/authorization/facebook}">sign in with Facebook</a>

</body>
</html>

DB 기반 로그인과 같이하기

Role

google, facebook, github, okta 이외의 provider

  • 카카오

results matching ""

    No results matching ""