728x90

Kakao Social Login 기능 추가

https://developers.kakao.com/

 

 

 



 

 

 




GitHub 연동까지 해 보세요. 

 

Storage ⇒ HTML5에 추가된 기능

https://developer.mozilla.org/ko/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API

 

브라우저에서 쿠키를 사용하는 것보다 훨씬 직관적으로 key/value 데이터를 안전하게 저장할 수 있는 메커니즘을 제공합니다.

 

  • sessionStorage는 페이지의 세션이 유지되는 동안 사용할 수 있는 각 origin별로 별도의 스토리지를 관리합니다. (페이지 리로딩 및 복원을 포함한, 브라우저가 열려있는 한 최대한 긴 시간 동안)
  • localStorage도 같은 일을 하지만, 브라우저가 닫히거나 다시 열리더라도 유지합니다.

 



JWS(JSON Web Token) 토큰 검증 후 사용자 프로필 조회(P126)



#1 auth0.com에 등록된 사용자 프로필 정보를 반환하는 람다 함수를 생성

#1-1 api-gateway-lambd-exec-role 역할을 생성

 

 

#1-2 람다 함수 생성

JSON Web Token 검증

auth0 엔드포인트를 호출해서 사용자 정보를 조회

웹 사이트에 응답을 전송

 

 



#1-3 작업 디렉터리 생성 및 필요 모듈 추가

PS C:\Users\i> cd C:\serverless\

PS C:\serverless> mkdir user-profile

PS C:\serverless> cd user-profile

PS C:\serverless\user-profile> npm init -y

PS C:\serverless\user-profile> npm install jsonwebtoken

PS C:\serverless\user-profile> npm install request



#1-4 package.json 파일에 deploy, predeploy 스크립트를 추가

c:\serverless\user-profile\package.json

{

  "name": "user-profile",

  "version": "1.0.0",

  "description": "",

  "main": "index.js",

  "scripts": {

    "predeploy": "del Lambda-Deployment.zip & zip -r Lambda-Deployment.zip * -x *.zip *.log node_modules/aws-sdk/*", 

    "deploy": "aws lambda update-function-code --function-name user-profile-람다함수의ARN --zip-file fileb://Lambda-Deployment.zip"

  },

  "keywords": [],

  "author": "",

  "license": "ISC",

  "dependencies": {

    "jsonwebtoken": "^8.5.1",

    "request": "^2.88.2"

  }

}

 

#1-5 index.js 파일 생성 및 소스 코드 추가

참고 : auth0.com에서 사용자 정보를 받아와서 반환 

https://auth0.com/docs/api/authentication#user-profile

 

c:\serverless\user-profile\index.js

// P130

// AWS 람다 서비스를 통해서 실행되는 코드

'use strict';



// https://www.npmjs.com/package/jsonwebtoken

// https://www.npmjs.com/package/request

var jwt = require('jsonwebtoken');

var request = require('request');



/*

event = {

  "accessToken": "w7agqIkUzCofd9nUelOxgd1zogqPpw9V",

  "authToken": "Bearer eyJhbGciOiJ~~~cCI6IkpXVCJ9.eyJnaXZlbl~~~pKNDQuZSJ9.mioxKcb1~~~W1LTk5_anGo"

};

*/

exports.handler = function (event, context, callback) {

    console.log(JSON.stringify(event));



    // event 객체에 authToken, accessToken 존재 여부를 확인

    // 만약, 존재하지 않으면 리턴

    if (!event.authToken) {

        callback('Could not find authToken');

        return;

    }

    if (!event.accessToken) {

        callback('Could not find access_token');

        return;

    }

    

    // authToken의 값을 공백문자를 기준으로 분리한 후 두번째 값을 id_token 변수에 할당

    // authToken은 Bearer 값.값.값 형식을 가짐

    var id_token = event.authToken.split(' ')[1];

    var access_token = event.accessToken;

    var body = {

        'id_token': id_token,

        'access_token': access_token

    };



    // 환경변수 DOMAIN의 값은 auth0.com에 설정되어 있는 어플리케이션의 도메인

    // auth0.com에 사용자 프로필 정보 조회에 필요한 값을 설정

    // ==> 로그인 시 전달받은 access token을 요청 파라미터로 전달

    // https://auth0.com/docs/api/authentication#user-profile

    var options = {

        url: 'https://' + process.env.DOMAIN + '/userinfo',

        method: 'GET',

        json: true,

        body: body

    };



    // auth0.com으로 사용자 프로필 정보를 조회

    request(options, function (error, response, body) {

        if (!error && response.statusCode === 200) {

            // 정상적으로 조회한 경우 호출한 곳으로 프로필 정보를 반환

            callback(null, body);

        } else {

            callback(error);

        }

    });

};




#1-6 람다 함수를 배포

PS C:\serverless\user-profile> npm run deploy



#1-7 환경변수 등록

 

 

#1-8 람다 함수 테스트

소셜 로그인 후 브라우저 개발자 도구를 이용해서 localStorage에 저장된 accessToken과 idToken 값을 추출

 

user-profile 람다 함수의 event로 전달 (authToken의 값은 localStorage에 있는 idToken값을 할당)

{

"accessToken": "ifzF3bnON0RH9E2VBHem15ygluDSuftA", 

"authToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Im9VWmF6dzRINnNkWFhqYzRtem13ciJ9.eyJuaWNrbmFtZSI6Im15YW5qaW5pIiwibmFtZSI6Il4uLl52IiwicGljdHVyZSI6Imh0dHA6Ly9rLmtha2FvY2RuLm5ldC9kbi9QMWpYYi9idHFHa1djN2JuRC9ZVGd4VWtNMEM0dm5sRXNjZDNxd2gwL2ltZ18xMTB4MTEwLmpwZyIsInVwZGF0ZWRfYXQiOiIyMDIxLTAzLTE2VDA0OjUwOjEwLjAyOVoiLCJlbWFpbCI6Im15YW5qaW5pQGtha2FvLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpc3MiOiJodHRwczovL25hYW5qaW5pLnVzLmF1dGgwLmNvbS8iLCJzdWIiOiJvYXV0aDJ8a2FrYW98MTUwOTIzOTQ4OCIsImF1ZCI6IkJBZEVlWlRrRmxBZHlDMWE3bldFTkIzc1J5ZHBCeVhSIiwiaWF0IjoxNjE1ODcwNDQxLCJleHAiOjE2MTU5MDY0NDEsImF0X2hhc2giOiJjZEsxenJnZU9sMlFaLVY2YnNsb2JBIiwibm9uY2UiOiJ5Y25rcFFsUC1iT3ZWeExhQl9FZGN4aTdzemM2eWJqfiJ9.sTTMxgRgivW1AaylaJ0PomkBAa0AXuTYaR5_cce1WQgY3pQNxhdJgDcYPNButLTo0pc0v1FKOb4ypmcqW79Ypq3vDkQyYQNDgooio67q_XGSgbVaKAk3MYlpHOrIwPgZpks7SlzQ6ALILm2fFbtPM3bvQvwcZcp4rcvCx1bm5TV69HsPfWfzBH7H-_XFZA61TlANmWuNOoZRqopCVQpSA8KHTo0Qxyn5gvBthRu0sQNoh67L-oLfxZHZfCN3GFeIREPFlBs9WJgn6LZ4nSUQL5XVW-4IBLN_lO3HgTlKsexcKSgeJMI8R_h0mqBkl4cgsVRyCV4xfWIAM_CdFRT8bg"

}

 

 

 

참고: 테스트 케이스를 만드는 스크립트

var accessToken = localStorage.getItem('accessToken');

var idToken = localStorage.getItem('idToken');

var event = { accessToken: accessToken, authToken: idToken };

console.log(event);




테스트 수행 시 응답(response)에 사용자 프로필이 출력되는 것을 확인

 

#2 API Gateway 설정

웹 사이트의 요청을 받아서 user-profile 람다 함수를 호출

 

#2-1 REST API 구축

 

 

#2-2 리소스 생성

 

 

#2-3 메서드 생성



#2-4 CORS 활성화

 

 

#2-5 매핑 생성

웹 사이트의 Authorization 헤더를 통해 전달된 JWT 토큰을 람다 함수에서 사용할 수 있도록 event 객체의 값으로 설정

 

웹 브라우저  -----------------------> API Gateway ----------------------> user-profile 람다 함수

(웹 사이트)

               Authorization: JWT_TOKEN                         event = { authToken: JWT_TOKEN, … }

            ~~~~~~~~~~~~~~~~~~~~~~~~              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                                      |                                                                            |

                                      +---------------- 맵핑(mapping) --------------+

 

 

 

{

    "authToken": "$input.params('Authorization')", 

    "accessToken": "$input.params('AccessToken')"

}

 

참고 : API Gateway 매핑 템플릿과 액세스 로깅 변수 참조

https://docs.aws.amazon.com/ko_kr/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#input-variable-reference



#2-6 API 배포



API Gateway 및 리소스 URL로 접근하면 오류를 반환 ⇒ 내부 수행에 필요한 값이 전달되지 않기 때문



#3 API Gateway를 통해서 람다 함수를 호출(실행)하도록 웹 페이스를 수정 (P138)

프로필 보기 기능을 추가 구현

 

#3-1 config.js 파일에 API Gateway 호출 URL을 등록

c:\serverless\24-hour-video\js\config.js

var configConstants = {

    auth0: {

        domain: 'naanjini.us.auth0.com',

        clientId: 'BAdEeZTkFlAdyC1a7nWENB3sRydpByXR'

    },

    // API Gateway 호출 URL

    apiBaseUrl: 'https://vfhp67njsk.execute-api.us-east-1.amazonaws.com/dev'

};



#3-2 user-controller.js 파일에 Show Profile 버튼을 클릭했을 때 동작을 추가 (이벤트 핸들러를 추가)

c:\serverless\24-hour-video\js\user-controller.js

 

 // 특정 이벤트에 반응하는 함수를 정의

    wireEvents: function() {

        var that = this;

 

        // P138

        // Show profile 버튼 클릭 이벤트 핸들러

        this.uiElements.profileButton.click(function(e) {

            // user-profile 리소스 호출 URL

            var url = that.data.config.apiBaseUrl + '/user-profile';



            // 지정된 URL 주소로 GET 방식의 요청을 전달

            $.get(url, function(data, status) {

                console.log('data', data);

                console.log('status', status);

            }).fail(function(e) {

                console.log(e);

            });

        });



        //          :

        //     (이하 생략)

        //          :



#4 사용자 프로필 조회 테스트 

#4-1 콘솔창에 오류 메시지를 확인



 

본 요청(main request)에 AccessToken이라는 요청 헤더가 포함되어 있음 ⇒ 기원이 다른 서버(API 게이트웨이)에서 해당 헤더를 처리할 수 있는지 여부를 먼저 확인(preflighted request)

 

 

프리플라이트 요청 결과에 access-control-allow-headers에 AccessToken이 포함되어 있지 않음 ⇒ Request header field accesstoken is not allowed by Access-Control-Allow-Headers in preflight response. 오류가 발생

 

해결방안 ⇒ 기원이 다른 서버(API Gateway)에서 Access-Control-Allow-Headers 응답 헤더에 AccessToken을 추가



#4-2 Access-Control-Allow-Headers 응답 헤더에 AccessToken을 추가

 

 



#4-3 프로필 요청 테스트

 

 

 

프리플라이트 요청의 응답에는 access-control-allow-headers 헤더를 확인

 

본 요청의 응답에는 access-control-allow-origin 헤더를 확인

 

CORS(교차 기원 자원 공유)

https://developer.mozilla.org/ko/docs/Web/HTTP/CORS



웹(WEB) = 공유 ⇒ 교차 기원 요청이 가능

                                    ~~~~

                                     origin = 기원 = 출처

 

 



HTTP 요청은 기본적으로 교차 기원 요청(Cross Origin Request)이 가능

기원이 다른 JS 파일, 이미지 파일을 가져와서 서비스(보여지고 실행) 가능

 

http://127.0.0.1:8000/cors_test.html

<html>

<head></head>

<body>

    <img src="http://127.0.0.1:8000/tile.png" height="200">

    <img src="https://s.pstatic.net/static/www/img/uit/2020/sp_shop_bffdc9.png" height="200">



    <script src="http://127.0.0.1:8000/js/main.js"></script>

    <script src="https://nid.naver.com/login/js/bvsd.1.3.4.min.js"></script>



</body>

</html>



http://127.0.0.1:8000/cors_test.html

http://127.0.0.1:8000/tile.png

http://127.0.0.1:8000/js/main.js

https://s.pstatic.net/static/www/img/uit/2020/sp_shop_bffdc9.png ⇐ 기원이 다름에도 불구하고 가져와서 사용이 가능

https://nid.naver.com/login/js/bvsd.1.3.4.min.js



스크립트 내에서 교차 기원 요청은 보안 상의 이유로 제한 ⇒ SOP(Same Origin Policy: 동일 기원/출처 정책)

~~~~~~~~~~~~ ⇒ ajax 통신 = XMLHttpRequest 객체를 이용한 비동기 통신

 

SOP ⇒ XMLHttpRequest 객체를 사용해서 가져오는 리소스는 해당 웹 애플리케이션과 동일한 기원으로 제한



<html>

<head></head>

<body>

    <img src="tile.png" height="200">

    <img src="https://s.pstatic.net/static/www/img/uit/2020/sp_shop_bffdc9.png" height="200">



    <script src="js/main.js"></script>

    <script src="https://nid.naver.com/login/js/bvsd.1.3.4.min.js"></script>



    <script>

        var xhr = new XMLHttpRequest();

        xhr.onreadystatechange = function() {

            if (this.readyState == 4 && this.status == 200) {

                console.log(xhr.responseText);

            }

        };

        // XMLHttpRequest를 이용해서 동일 기원의 자원을 요청

        xhr.open("GET", "http://127.0.0.1:8000/js/main.js", true);

        xhr.send();

    </script>

</body>

</html>

 





<html>

<head></head>

<body>

    <img src="tile.png" height="200">

    <img src="https://s.pstatic.net/static/www/img/uit/2020/sp_shop_bffdc9.png" height="200">



    <script src="js/main.js"></script>

    <script src="https://nid.naver.com/login/js/bvsd.1.3.4.min.js"></script>



    <script>

        var xhr = new XMLHttpRequest();

        xhr.onreadystatechange = function() {

            if (this.readyState == 4 && this.status == 200) {

                console.log(xhr.responseText);

            }

        };

        // XMLHttpRequest를 이용해서 교차 기원의 자원을 요청

        xhr.open("GET", "https://nid.naver.com/login/js/bvsd.1.3.4.min.js", true);

        xhr.send();

    </script>

</body>

</html>

 



CORS(Cross Origin Resource Sharing: 교차 기원 자원 공유)

⇒ SOP를 완화하는 정책

⇒ Access-Control-Allow-Origin 응답 헤더를 이용해서 자원 사용 여부를 허가

 



단순 요청(simple request)

 

프리플라이트 요청(preflighted request)

 

728x90

'CLOUD > AWS' 카테고리의 다른 글

3/19 - AWS 15차시  (0) 2021.03.19
3/17 - AWS 14차시  (1) 2021.03.17
3/15 - AWS 12차시  (0) 2021.03.15
3/12 - AWS 11차시  (0) 2021.03.12
3/11 - AWS 10차시  (0) 2021.03.11

+ Recent posts