클라우드 컴퓨팅 & NoSQL/Vert.x & Node.js

빠르게 훝어 보는 node.js - #15 - Passport를 이용한 OAuth 2.0 API 인증 (Facebook 1/2)

Terry Cho 2014. 6. 30. 00:46

빠르게 훝어보는 node.js

#15  - Passport를 이용한 OAuth 2.0 API 인증 (Facebook 1/2)

조대협 (http://bcho.tistory.com)



REST 기반의 OPEN API 인증을 고민하다가 보니, 가장 많이 쓰이는게, OAuth 2.0이라서, OAuth 2.0을 보다보니, 도저히 이해가 안되겠다 싶어서, 간단하게 직접 구현해보기로 했다. OAuth 서버를 구현하기전에 먼저 테스트 클라이언트가 필요했기 때문에, node.js + passport 를 이용해서 facebook API를 호출하는 간단한 웹 사이트를 만들어보기로 했다.

Facebook API는 기본적으로 OAuth 2.0을 사용하고, Passport 모듈에서 잘 추상화된 라이브러리를 제공하기 때문에 쉽게 구축할 수 있으리라 생각했다. 실제로 구축해보니, 간단한 예제를 만드는데 약 1시간 30분 정도가 소요되었다.

자아 그러면 이제부터 Passport node.js를 이용해서 간단한 Facebook API를 호출하는 예제를 만들어보도록 하자.

OAuth 2.0

먼저 OAuth 2.0에 대한 개념을 알아보도록 하자. OAuth 2.0, 서비스에 대한 Authentication (인증) Authorization(권한 인가)에 대한 포괄적인 프레임웍이다. 특히 API 인증에 유용하게 사용될 수 있는데, 사용하는 애플리케이션의 타입(,모바일,자바스크립트)에 따라서 다양한 인증 메카니즘을 제공한다. 이를 grant type이라고 하는데, 대표적으로 4가지 형태의 grant type을 제공한다.

Ÿ   Authorization Code for webserver

Ÿ   Implicit for browser-based or mobile apps

Ÿ   Resource owner password credential for logging in with a username and password

Ÿ   Client credential for application access

다른 grant type에 대해서는 차차 소개하기로 하고, 오늘은 authorization code 방식의 grant type에 대해서 알아보도록 하자.

※ 다른 grant type에 대해서는 http://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#web-server-apps 에 잘 정리가 되어 있다.

지금 구축하려고 하는 것은 facebook API를 내 서비스 웹서버에서 호출하는 시나리오이다.

Facebook API를 호출하기 위해서는 node.js 애플리케이션을 facebook 에 등록해야 한다. 이 등록은 facebook developer portal을 통해서 진행할 수 있는데, 아래 그림과 같이



1.  포탈에 node.js 사이트 관련 정보 (서비스 URL, CallBack URL, 서비스 명 등)을 입력하면,

2.  포탈에서 client_id client_secret을 발급해준다. client_id는 서버에서 발급되는 node.js 만든 서비스에 대한 id 라고 생각하면 되고, client_secret은 그 id에 대한 일종의 인증용 패스워드이다. (절대로 외부에 노출되면 안되는)

3.  이렇게 받은 client_id client_secret node.js 애플리케이션 내에 저장한다.

이렇게 해서 node.js 애플리케이션이 만들어졌으면 호출을 해보자. 호출은 다음과 같은 순서로 이루어 진다. 잠깐 용어를 짚고 넘어가면 OAuth 2.0에서는 Facebook 과 같이 Protected resource (API)를 제공하는 서버를 Resource Server 라고 하고, node.js와 같이 Protected resource (API)에 대한 접근을 요청하는 대상을 Client 라고 정의 한다. Client Resource Server에 접근할때, 사용자의 신분 (id,password)를 기반으로 하여, Resource Server에 접근하는데, 이러한 사용자를 User 라고 정의한다. 그러면 다음과 같은 흐름을 보자.



1.  먼저 사용자는 Web Browser에서, node.js 서버로 서비스를 요청한다.

2.  Node.js 서버는 사용자가 로그인이 되어 있지 않은 상태라면, Facebook log in URL에 대한 rediretion URL을 브라우져에게 보낸다. 이 때, node.js 서버임을 식별하기 위해서 client_id와 몇 가지 추가적인 정보를 보내는데, 그 내용은 다음과 같다.

Ÿ   client_id : 사용자를 통해서 인증을 요청하는 서비스가 앞에서 등록한 node.js 애플리케이션임을 알려준다.

Ÿ   redirect_url : 페이스북 인증서버에서 인증이 끝난후에, 인증 결과를 받을 node.js  애플리케이션으 HTTP URL을 정의한다.

Ÿ   scope : 페이스북에 접근을 요청한 리소스 목록을 정의한다. 예를 들어, 글쓰기, 읽기, 사진 올리기, 연락처 공유등과 같이 리소스에 대한 범주를 정의한다. Oauth 2.0의 특징중의 하나가 단순히 사용자 인증(Authentication)만을 하는 것이 아니라, 사용자가 소유한 리소스중, 접근을 허가 하는 권한 제어(Authorization) 기능을 함께 제공한다는 것이다.

https://oauth2 authorizationserver.com/auth?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=photos

실제 facebook redirection URL

https://www.facebook.com/login.php?skip_api_login=1&api_key=253044994897796&signed_next=1&next=https://www.facebook.com/v2.0/dialog/oauth?redirect_uri=http://localhost:8080/auth/facebook/callback&scope=read_stream&response_type=code&client_id=253044994897796&ret=login&cancel_uri=http://localhost:8080/auth/facebook/callback?error=access_denied&error_code=200&error_description=Permissions error&error_reason=user_denied#_=_&display=page

3.  Browser Redirect URL을 받아서,페이스북의 인증 서버 URL Redirect를 한다.

4.  페이스북 인증 서버는 log in page를 사용자에게 보낸다.



5.  사용자는 사용자 ID PASSWORD를 입력한다.

인증이 되고 나면, scope에 의해서 리소스에 대한 접근 요청을 허가할 것인지를 물어보는데, 아래는 node.js 애플리케이션이 글쓰기 권한을 요청했을때 사용자에게 node.js 애플리케이션에 글쓰기 권한을 허용할지를 물어보는 화면이다.



6.  페이스북의 인증서버는 ID,PASSWORD를 인증과 권한 획득에 성공하면, 인증과 권한 획득에 성공했다는  Authorization Code와 함께, 다시 2에서 정의된 Service Consumer node.js server callback URL (redirect_url= redirect_uri=http://localhost:8080/auth/facebook/callback ) redirect request를 보낸다.

7.  Browser는 위에서 받은 Authorization code와 함께, 앞에서 받은 node.js 서버의 callback URL redirect를 한다.

http://localhost:8080/auth/facebook/callback?code=AQAKlwhopD1DD5(중략)

8.  Node.js 서버는 이 사용자가 인증 되었음  증명하는 받은 authorization code를 가지고, 페이스북의 authorization server에 문의한다.
POST https://api.oauth2server.com/token
    grant_type=authorization_code&
    code=AUTH_CODE_HERE&
    redirect_uri=REDIRECT_URI&
    client_id=CLIENT_ID&
    client_secret=CLIENT_SECRET

Ÿ   grant_type : grant type은 앞에서 설명한 4개중에서, 현재 사용하는 grant type authorization code 방식이기 때문에 이를 정의한다.

Ÿ   code : 앞에서 받은 authorization code

Ÿ   redirect_uri

Ÿ   client_id : node.js 서버를 인증하기 위한 client id. 앞서 developer portal에서 발급받아서, node.js 서버 애플리케이션안에 넣어놓았다.

Ÿ   client_secret : node.js 서버를 인증하기 위한 client_secret(password). 앞서 developer portal에서 발급받아서, node.js 서버 애플리케이션안에 넣어놓았다.

9.  페이스북의 authorization server는 이 authorization code를 가지고해당 요청이 인증되었음을 확인하고, node.js 서버에게로 API 접근을 허용하는 access_token을 발급한다.

10. Node.js 서버는 이 access_token을 가지고 페이스북 API에 접근을 요청하면, 페이스북 API서버는 access_token을 통해서 API 접근 가능 여부를 판단한 후, 인가된 요청인 경우 API 요청을 수락하여 서비스를 제공한다.

간단하게 authorization code 방식을 이용한 애플리케이션 인증 방식에 대해서 알아보았다. 몇가지 더 짚고 넘어가면, authorization code 방식의 장점은 node.js 서버가 사용자 id,password를 알수 없다. API를 제공하는 서비스 제공자 입장에서, 3’rd party (협력 파트너)에게 자사의 사용자 id,password를 노출 시킬 필요가 없기 때문에, 파트너를 대상으로 안전하게 서비스 사용자의 id,password 없이 사용자 인증을 진행할 수 있다.

아울러 access_token에 대해서 몇가지 짚고 넘어갈것이 있는데, access_token을 취득한 이후에는 별도의 사용자 인증 절차가 필요하지 않다. Node.js 서버에서 access_token만을 기억하고 있으면 해당 사용자에 대한 리소스를 호출하는 API를 이 access_token을 통해서 호출할 수 있다. (즉 호출할때 마다 매번 사용자 인증을 할 필요가 없다는 말이다.)


다음글에서는 실제로 Passport 모듈을 이용하여 Facebook Open API를 호출하는 방법을 설명하도록 하겠다.