ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OAuth(3) - Facebook 인증
    OAUTH 공부자료 2019. 10. 18. 15:11

    (1) Spring Boot 프로젝트 생성

     

    (2) index.html 파일 만들기

     

    index.html

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8"/>
        <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
        <title>OAuth2 Sample Application</title>
        <meta name="description" content="OAuth2 Sample Application"/>
        <meta name="viewport" content="width=device-width"/>
        <base href="/"/>
        <link rel="stylesheet" type="text/css" href="/webjars/bootstrap/css/bootstrap.min.css"/>
        <script type="text/javascript" src="/webjars/jquery/jquery.min.js"></script>
        <script type="text/javascript" src="/webjars/bootstrap/js/bootstrap.min.js"></script>
    </head>
    <body>
    <h1>OAuth2 Sample Application</h1>
    <div class="unauthenticated">
        <a class="btn" href="/login">Login</a>
    </div>
    <div class="authenticated" style="display: none">
        Logged in as: <span id="user"></span>
        <div><button onClick="logout()" class="btn">Logout</button></div>
    </div>
    </body>
    </html>

    index.html파일을 src/main/resources/static에 추가하고 아래와 같이 작성한다. <head> 안쪽에 webjars가 보이는데 클라이언트 사이드에서 사용하는 javascript 또는 css 라이브러리 등을 jar 형태로 import시킬 수 있는 기능이라고 보면 되겠다. 

     

    (3) pom.xml에 dependency 추가 (webjars, Security)

    pom.xml

    		<!-- webjars -->
            <dependency>
                <groupId>org.webjars</groupId>
                <artifactId>jquery</artifactId>
                <version>2.1.1</version>
            </dependency>
            <dependency>
                <groupId>org.webjars</groupId>
                <artifactId>bootstrap</artifactId>
                <version>3.2.0</version>
            </dependency>
            <dependency>
                <groupId>org.webjars</groupId>
                <artifactId>webjars-locator-core</artifactId>
            </dependency>
    
            <!-- Security -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.security.oauth.boot</groupId>
                <artifactId>spring-security-oauth2-autoconfigure</artifactId>
                <version>2.0.0.RELEASE</version>
            </dependency>

    bootstrap과 jquery를 추가하였다. webjars-locator-core라는 녀석은 앞서 추가한 webjars들의 path를 지정해주는 역할이라고 보면 좋을 것 같다. 앞서 index.html에서 /webjars/**에 위치한 js 파일과 css파일을 불러오기 위한 dependency이다.

    어플리케이션을 안전하게 만들기 위해서는 Spring Security와 관련된 dependency를 적용해야 한다. 

     

    (4) Application.java@EnableOAuth2Sso 추가

    Application.java

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
    
    @SpringBootApplication
    @EnableOAuth2Sso // <-- 이부분을 추가한다.
    public class FacebookloginApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(FacebookloginApplication.class, args);
        }
    
    }

    Facebook으로 연결하기 위하여 Application.java @EnableOAuth2Sso 어노테이션을 추가한다.

     

     

    (5) application.yml 파일 생성

    application.yml

    security:
      oauth2:
        client:
          clientId: 페이스북 개발자 모드에서 ClientID 발급 필요
          clientSecret: 페이스북 개발자 모드에서 ClientSecret 발급 필요
          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
    
    spring.main.allow-bean-definition-overriding: true
    

    -다음과 같이 페이스북 관련 정보를 기입한다. https://developers.facebook.com/apps/ 에 접속한 후 ClientID와  ClientSecret키 발급 받아야한다. (7)에서 다룰 예정이다

    - spring.main.allow-bean-definition-overriding: true 는 다음과 같은 오류를 해결할 수 있다

    (6) application.properties 에서 서버포트 변경 (선택)

    application.properties

    server.port=8999

    기본포트는 localhost:8080 이지만 해당포트가 이미 사용중이어서 연결에 실패할 경우, 다른포트로 연결해주자

     

    (7) 페이스북에서 ClientID와 ClientSecret 키 발급받기

     7-1 https://developers.facebook.com/apps/에 접속

     7-2 새 앱 추가하기 클릭 후 앱 ID 생성

    7-3 설정-기본설정에 들어가면 앱 ID-ClientID, 앱 시크릿 코드-ClientSecret

     

     

    (8) 페이스북에서 리디렉션 URI 설정

    (6)에서 설정했던 서버포트를 리디렉션 URI로 입력한다.

    만약 (6)에서 application.properties를 수정하지 않았다면 localhost:8080, localhost:8080/login을 추가하면된다

     

    (9) 서버를 실행하고 해당포트로 접속한다

    제연님으로 계속하기를 클릭하면

     

    앱에서 정보 수신에 대해 동의버튼을 누르면 원래 우리가 호출하려 했던 index.html과 같은 화면이 등장할 것이다.

    이러한 화면이 나올 시 OAuth를 활용한 Facebook 연동은 완료된 것이다

     

    (10) Welcome Page 만들기

    Facebook 로그인 링크와 로그인 되었을 때 사용자 정보를 출력하는 페이지를 작성해보자

     

    index.html에 추가

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8"/>
        <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
        <title>OAuth2 Sample Application</title>
        <meta name="description" content="OAuth2 Sample Application"/>
        <meta name="viewport" content="width=device-width"/>
        <base href="/"/>
        <link rel="stylesheet" type="text/css" href="/webjars/bootstrap/css/bootstrap.min.css"/>
        <script type="text/javascript" src="/webjars/jquery/jquery.min.js"></script>
        <script type="text/javascript" src="/webjars/bootstrap/js/bootstrap.min.js"></script>
    </head>
    <body>
    <h1>OAuth2 Sample Application</h1>
    <div class="container unauthenticated">
        Facebook : <a href="/login">로그인</a>
    </div>
    <div class="container authenticated" style="display:none">
        로그인 되었습니다 : <span id="user"></span>
    </div>
    
    <script type="text/javascript">
        $.get("/user", function(data) {
            $("#user").html(data.userAuthentication.details.name);
            $(".unauthenticated").hide()
            $(".authenticated").show()
        });
    </script>
    
    </body>
    </html>

    authenticated unauthenticated 클래스를 통해 인증 여부를 확인하고 그에 따라 display를 해주는 부분이다. 이에 대한 내용을 jQuery를 사용하여 작성하자. 

     

    UserController.java 파일 생성

    package com.example.facebooklogin;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.security.Principal;
    
    @RestController
    public class UserController {
        @RequestMapping("/user")
        public Principal user(Principal principal) {
            return principal;
        }
    }
    

    위 javascript 소스코드처럼 /user 에 대한 부분을 작성해야 한다

     

     

    Application.java에 추가

    package com.example.facebooklogin;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    // Application.java
    @SpringBootApplication
    @EnableOAuth2Sso
    public class FacebookloginApplication extends WebSecurityConfigurerAdapter {
        public static void main(String[] args) {
            SpringApplication.run(FacebookloginApplication.class, args);
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/**")
                    .authorizeRequests()
                    .antMatchers("/", "/login**", "/webjars/**", "/error**")
                    .permitAll()
                    .anyRequest()
                    .authenticated();
        }
    }

    잘 작동하지만 사용자가 링크를 클릭 할 수가 없다. 로그인 링크를 표시하려면 WebSecurityConfigurer를 추가하여 설정을 한다. WebSecurityConfigurerAdapter를 상속받고 configure()를 작성한다. 그리고 인증을 처리하는 로그인 엔드포인트와 다른 요청들에 대한 인증이 필요하도록 설정한다. 이제 서버를 재시작하고 접속하면 로그인 링크가 등장하고 로그인을 실행하면 로그인된 사용자의 정보가 등장할 것이다.

     

     

    localhost:8999에 접속할 시

     

    Facebook 로그인을 클릭할 시

     

    (11) 로그아웃 기능 구현

     

     

    index.html

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8"/>
        <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
        <title>OAuth2 Sample Application</title>
        <meta name="description" content="OAuth2 Sample Application"/>
        <meta name="viewport" content="width=device-width"/>
        <base href="/"/>
        <link rel="stylesheet" type="text/css" href="/webjars/bootstrap/css/bootstrap.min.css"/>
        <script type="text/javascript" src="/webjars/jquery/jquery.min.js"></script>
        <script type="text/javascript" src="/webjars/bootstrap/js/bootstrap.min.js"></script>
    </head>
    <body>
    <h1>OAuth2 Sample Application</h1>
    <div class="container unauthenticated">
        Facebook : <a href="/login">로그인</a>
    </div>
    <div class="container authenticated" style="display:none">
        로그인 되었습니다 : <span id="user"></span>
        <div>
            <button onClick="logout()" class="btn btn-primary">로그아웃</button>
        </div>
    </div>
    
    <script type="text/javascript">
        $.get("/user", function(data) {
            $("#user").html(data.userAuthentication.details.name);
            $(".unauthenticated").hide()
            $(".authenticated").show()
        });
        var logout = function() {
            $.post("/logout", function() {
                $("#user").html('');
                $(".unauthenticated").show();
                $(".authenticated").hide();
            });
            return true;
        }
    </script>
    
    </body>
    </html>

    index.html authenticated클래스 안쪽에 로그아웃 버튼을 추가하고 로그아웃 버튼에 대한 이벤트 함수를 작성한다.

    서버사이드 역시 /logout에 대한 엔드포인트가 필요하다. 조금 전 작성했던 configure()에 로그아웃에 대한 엔드포인트를 작성하자. /logout은 POST메소드로 요청할 필요가 있다. 또한 CSRF(Cross Site Request Forgery)로부터 보호해야 한다. 현재 세션에 이로부터 보호하는 토큰값이 있기 때문에 클라이언트 단에서 이에 대한 값을 가지고 있어야 한다.

     

    application.java

    package com.example.facebooklogin;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
    
    // Application.java
    @SpringBootApplication
    @EnableOAuth2Sso
    public class FacebookloginApplication extends WebSecurityConfigurerAdapter {
        public static void main(String[] args) {
            SpringApplication.run(FacebookloginApplication.class, args);
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/**")
                    .authorizeRequests()
                    .antMatchers("/", "/login**", "/webjars/**", "/error**")
                    .permitAll()
                    .anyRequest()
                    .authenticated()
                    .and().logout().logoutSuccessUrl("/").permitAll()
                    .and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
        }
    }

    CSRF 토큰을 클라이언트 단에 추가하기

    이번 샘플에서는 자바스크립트 프레임워크 등을 사용하지 않기 때문에 pom.xml에 라이브러리를 추가하는 것으로 대체한다. 라이브러리를 추가하고 html에 적용해보자.

     

    pom.xml에 추가

    <dependency>
      <groupId>org.webjars</groupId>
      <artifactId>js-cookie</artifactId>
      <version>2.1.0</version>
    </dependency>

    index.html에 추가

    <script type="text/javascript" src="/webjars/js-cookie/js.cookie.js"></script>
    $.ajaxSetup({
      beforeSend : function(xhr, settings) {
        if (settings.type == 'POST' || settings.type == 'PUT'
        ||  settings.type == 'DELETE') {
          if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
            xhr.setRequestHeader("X-XSRF-TOKEN", Cookies.get('XSRF-TOKEN'));
          }
        }
      }
    });

     

    어플리케이션을 재시작하고 결과를 확인해본다.

    로그아웃을 클릭할 시 초기 로그인 페이지로 이동한다

     

     

    참고자료 : https://hwiveloper.github.io/2019/04/05/spring-boot-oauth2-facebook/

     

    스프링부트 OAuth2 - 1. Facebook 인증

    https://spring.io/guides/tutorials/spring-boot-oauth2/ 를 참조하여 작성하였습니다. 개인적으로 서버사이드 프로그래밍을 하면서 가장 어렵기도 하고 귀찮은 부분이 인증하는 부분이라고 생각한다. 로직을 작성해 나간다기 보다는 클라이언트와 서버사이드 간의 통신을 통해 사용자를 인지하고 이를 세션 등으로 관리할 뿐 아니

    hwiVeloper.github.io

    참고자료 : https://spring.io/guides/tutorials/spring-boot-oauth2/

     

    Spring Boot and OAuth2

    this tutorial is designed to be completed in 2-3 hours, it provides deeper, in-context explorations of enterprise application development topics, leaving you ready to implement real-world solutions.

    spring.io

    참고자료 : https://redstapler.co/facebook-login-oauth2-spring-boot/

     

    Facebook Login with OAuth2 in Spring Boot | Red Stapler

    How to use OAuth2 with Spring Boot to create and Application with Facebook Login

    redstapler.co

     

    댓글

Designed by Tistory.