오픈 API는 웹상에서 공개된 RESTfull URL을 통해서 데이터를 요청하고 받는 인터페이스를 정의하고 이용할 수 있는 것입니다.

오픈 API : http://enc.daum.net/dic100/contents.do?query1=10XX317748


티스토리의 오픈 API 의 인증은 페이스북이나 트위터등에서 널리 사용되고 있는 OAuth 2.0 프로토콜을 사용하고 있다. 1.0 에 비해 인크립션이나 프로세스가 많이 생략되어 비교적 구현이 간편한 편이다. 사용을 위해서는 우선, 컨슈머 등록을 통해 Client IDSecret Key 를 발급받아야 한다. 스펙에서 얘기하는 Service Provider 는 여기서 티스토리 인증서버가 되고, Consumer 는 인증요청을 하는 사용자 어플리케이션 또는 서버가 된다.


컨슈머 등록

예를 들어, 구현하고자 하는 서비스는 블로그에 댓글이 달렸을 경우, 트레이에서 버블 팝업등으로 사용자에게 알려주는 데스크탑 어플리케이션으로 서비스 형태'PC어플리케이션', 서비스 권한은 최신 댓글 목록만 받으면 되니 '읽기전용' 으로 설정하였다. 서비스 URL 및 CallBack 경로는 해당 서비스를 나타내는 URL 또는 자신의 블로그등을 입력하면 되는데, CallBack 경로는 인증시 Access Token 이 리다이렉트 되는 경로이다.


등록을 완료하면 위와 같이 Client IDSecret Key 가 발급되는데, 구현하고자 하는 해당 서비스에 맞는 OAuth 2.0 프로세는 Implicit Grant Flow 로 JSP 등의 서버 사이드의 Authorization Code 인증 방식과 달리, Client ID 만 가지고 서비스 권한 요청이 가능하다.


Implicit Grant Flow


  1. 클라이언트(Consumer)에서 티스토리 서버(Service Provider)로 Access Token 을 요청하면,
  2. 사용자 로그인(ID/PASS)을 요구한다. 성공적으로 로그인이 되면,
  3. Consumer 등록시에 입력된 Callback 경로로 Access Token 을 실어 리다이렉트 시킨다.
  4. 해당 Access Token 과 조회할 블로그 아이디(targetUrl)로 최근댓글목록 API 호출.
  5. XML 리턴. (API URL에 &ouput=json 파라미터를 추가하여 호출하면, JSON 리턴)

티스토리 인증 가이드의 설명과 달리, Access Token 의 만료시간을 뜻하는 expires_in 파라미터는 리다이렉트 URL에 실려오지 않는다. 테스트 결과, 유효시간은 3600(60분) 으로 디폴트 설정되어 있다. 관련오류를 고객센터에 문의를 하였는데, 현재까지(10일 경과) 답변은 없는 상태이다. OAuth 2.0 스펙에서는, expires_in'RECOMMENDED' 항목으로 필수는 아니나 생략하였을 경우, 문서상이나 기타 다른 방법으로 기본 설정된 값을 명시하게 되어 있다.


해당 Access Token 이 시간경과(60분)로 인해 만료되면, 티스토리 API 호출 시, Access Token 이 만료되었다는 XML을 다음과 같이 리턴하게 된다.


이 경우, 새로운 Access Token 을 발급받아(1~3번) 사용하여야 한다. 만일, User Login 에 사용한 어플리케이션의 웹 브라우저 인스턴스를 종료하였다면 또 다시 사용자 로그인을 해야 하는 문제가 생기니, 로그인에 사용한 해당 브라우저의 인스턴스를 어플리케이션 종료시점까지 유지시켜줘야 한다.


시나리오


어플리케이션을 실행하면, 사용자 로그인 화면이 뜨고 사용자가 ID/PASS 를 입력하여 로그인에 성공하면 어플리케이션은 시스템 트레이로 이동하여 백그라운드에서 설정한 주기(ex. 10분)마다 최근 댓글 목록을 요청하여 갱신된 목록과 직전의 목록을 비교한다. 새로운 댓글이 존재할 경우 버블팝업으로 표시하고, 해당 팝업을 클릭할 경우, 해당 댓글의 블로그 페이지로 이동한다.


마치며


OAuth 1.0 과 비교하여, 2.0 인증은 그야말로 간편 그 자체다. 어찌보면, 2.0 스펙이 복잡하고 까다로웠던 1.0 스펙과 호환되지 않는건 당연해 보인다. 티스토리 인증 가이드에 설명이 비교적 잘 되어 있고, 스펙 자체도 간략한 편이라 적용에 큰 무리는 없지만 원체 블로그에 댓글이 잘 달리지도 않거니와 실제 사용성도 떨어져 보여, 댓글알림 어플리케이션 구현은 아마도 안할 것 같다;;;


'프로그램 > application(트위터api,오픈api,oauth)' 카테고리의 다른 글

RIA  (0) 2012.10.04
트위터 API twitter4j 사용하기 - 1. OAuth 접속  (0) 2012.06.14
OAuth 가젯 작성  (0) 2012.06.14
OAuth에대한 설명  (0) 2012.06.14
웹 서비스  (0) 2012.02.13
Posted by wrnly


트위터 API로 트위터에 접속하는 방법을 설명한다. 언어는 JSP이고 라이브러리는 twitter4j이다.
이클립스 설정은 아래의 글을 확인하면 된다. 
2011/08/16 - [개발/Java] - 이클립스 JSP 톰캣 연동

개괄적인 트위터 API의 예제에 대한것은 트랙백을 참고하고, 소스위주로 설명한다. 아직은 서버가 없으므로 localhost에서 톰캣으로 한다. 

먼저 트위터 개발자 계정(http://dev.twitter.com)에 가서 create an app을 한다.

application을 만들었으면 거기서 customer key와 customer secret을 복사하여 twitter.java에 다음과 같이 입력한다.

public class TwitterClient {
 public TwitterClient() {
  System.out.println("TwitterClient.TwitterClient");
 }

 Twitter twitter;

 RequestToken requestToken = null;
 AccessToken accessToken = null;
 
 final String CONSUMER_KEY = "IAsSj*****************";
 final String CONSUMER_SECRET = "MKxMB**********************************";

그리고 Callback URL을 등록을 한다. localhost는 등록이 되지 않으므로 127.0.0.1:8080으로 등록하자. 위에서는 http://127.0.0.1:8080/twt/redirect.jsp로 등록을 했다.

다음 이클립스 화면과 같이 TwitterClient.java와 index.jsp, main.jsp, signin.jsp, redirect.jsp를 만들자.


index.jsp는 그냥 main.jsp로 redirect하는 역할만 한다. 나중에 메인 페이지를 다른것으로 만들기 위해서 만들어 놨다.
<script>
location.href = "main.jsp";
</script>

main.jsp는 signin.jsp에 링크만 걸어놨다.
<a href="signin.jsp">트위터</a>

signin.jsp는 requestToken을 만들고 authorizationURL을 만들어서 twitter로 redirect를 한다. requestToken을 만드는 과정은 twitter4j에 customer key와 customer secret을 넘겨주면 완성된다. redirect.jsp에 넘겨주기 위해 생성된 requestToken과 TwitterClient 객체를 session에 저장한다.

[signin.jsp]
<%@page import="twt.TwitterClient"%>
<%@page import="twitter4j.auth.RequestToken"%>
<%
TwitterClient tw = new TwitterClient();

RequestToken token = tw.getRequestToken();
String authUrl = token.getAuthorizationURL();

session.setAttribute("requestToken", token);
session.setAttribute("tw", tw);
%>

<script>
location.href = "<%=authUrl%>";
</script>

[TwitterClient.java]
 public RequestToken getRequestToken()
 {
  twitter = new TwitterFactory().getInstance();
  twitter.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);

  requestToken = null;
  try {
   requestToken = twitter.getOAuthRequestToken();
  }
  catch(TwitterException te) {
   te.printStackTrace();
  }
  
  System.out.print("TwitterClient.getRequestToken: ");
  System.out.print(requestToken.getToken() + " ");
  System.out.println(requestToken.getAuthorizationURL());
  return requestToken;
 }


그러면 이제 최종적으로 redirect.jsp를 보자. 이 페이지는 twitter 서버에서 등록해둔 호출 서버로 redirect page로 redirect되는데 우리가 127.0.0.1로 해놓았기 때문에 다시 우리 데스크탑 서버로 돌아온다. 
parameter중에서 oauth_token이 그 응답이다. 이것을 가지고 아까 저장해준 TwitterClient와 RequestToken을 꺼내서 getAccessToken을 하면 접속이 완료된다. 그후에 타임라인을 테스트하는 함수인 printStatuses를 부르면 이클립스 콘솔창에 현재 타임라인이 나타나는 것을 볼수 있다.
[rediect.jsp]
<%@page import="twt.TwitterClient"%>
<%@page import="twitter4j.auth.AccessToken"%>
<%@page import="twitter4j.auth.RequestToken"%>

<%
// twitter에서 넘겨줌
String oauth_token = request.getParameter("oauth_token");

// signin.jsp에서 저장한 것들
RequestToken token = (RequestToken)session.getAttribute("requestToken");
TwitterClient tw = (TwitterClient)session.getAttribute("tw");

tw.getAccessToken(oauth_token, token);
tw.printStatuses(); 
%>

[TwitterClient.java]
 public AccessToken getAccessToken(String oauthToken, RequestToken requestToken)
 {
  if(requestToken == null) {
   System.out.print("requestToken == null");
  }
  if(oauthToken == null) {
   System.out.print("oauthToken == null");
  }
  
  twitter = new TwitterFactory().getInstance();
  twitter.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
  System.out.println("TwitterClient.getAccessToken: ");
  
  if(requestToken.getToken().equals(oauthToken)) {
   try {
    System.out.print("requestToken: ");
    System.out.print(requestToken.getToken() + " ");
    System.out.println(requestToken.getTokenSecret());

    accessToken = twitter.getOAuthAccessToken(requestToken);
    //accessToken = twitter.getOAuthAccessToken(token.getToken(), token.getTokenSecret());
    twitter.setOAuthAccessToken(accessToken);
    
    System.out.print("accessToken: ");
    System.out.print(accessToken.getToken() + " ");
    System.out.println(accessToken.getTokenSecret());
   }
   catch(TwitterException te) {
    te.printStackTrace();
   }
  }
  else {
   System.out.println("oauth_token error");  
  }
  return accessToken;
 }
 public void printStatuses()
 {
  ResponseList<Status> statuses;   
  Paging page = new Paging(); 
  page.count(20); 
  page.setPage(1);   
  
  try {   
   statuses = twitter.getHomeTimeline(page);
   for (Status status : statuses) {    
    //status.getId()    
    System.out.println(status.getUser().getScreenName() + ":" + status.getText());     
    //status.getUser().getScreenName()     
    //status.getUser().getURL()    
    //status.getText()    
    //status.getCreatedAt()    
    //status.getUser().getProfileImageURL()    
    //status.getSource() 
   }   
  } 
  catch(TwitterException te) {
   te.printStackTrace();
  } 
 }

이제 실행을 해보자. 서버의 hostname은 반드시 127.0.0.1이고 port는 8080이어야 한다. hostname이 localhost라면 session문제가 생기므로 새로운 서버를 만들기 바란다.

signin.jsp를 실행한 화면

애플리케이션 승인후에 redirect.jsp를 부르는 화면


redirect.jsp로 와서 timeline을 display하는 화면


소스파일 첨부:

 

추가:
C:\Program Files\Apache Software Foundation\Tomcat 7.0\lib에 twitter4j-core-2.2.4.jar를 복사하여 넣어야지 실행시 twitter4j 컴파일 에러가 발생하지 않는다.
 


Posted by wrnly

이 문서에서는 OAuth 기능을 사용하여 인증을 수행하는 가젯을 작성하는 방법에 대해 설명합니다. OAuth는 makeRequest() 함수와 연결하여 사용하며, makeRequest() 함수를 사용하여 원격 콘텐츠를 가져오는 데 대한 일반적인 설명은 원격 콘텐츠 가져오기를 참조하십시오.

이 문서에서는 iGoogle에서 실행하며 OAuth 프로토콜을 지원하는 웹사이트에서 사용자의 개인정보에 액세스할 수 있는 가젯을 작성하는 가장 간단한 사용 사례에 대해 주로 알아봅니다. 이 방법은 OAuth를 사용하는 단 하나의 방법이기도 합니다. 나아가 컨테이너에서 실행하는 오픈소셜 가젯에서도 이 문서에 설명된 기술을 사용하여 OAuth로 보호된 데이터에 액세스할 수 있게 됩니다. 이때 컨테이너인 iGoogle은 iGoogle에서 사용자가 추가하는 가젯이 해당 사용자에게만 표시되므로 가장 단순한 형태로 표시됩니다. 소셜 네트워킹 컨테이너에서는 가젯을 보는 사람이 가젯을 추가한 데이터 소유자와 다를 수도 있으므로 좀 더 복잡하게 표시됩니다. 서비스 제공업체에서 소셜 네트워킹 컨테이너에 OAuth를 지원하는 방법은 오픈소셜을 사용하도록 설정된 소셜 네트워크의 OAuth 사용 가젯 문서를 참조하십시오.

OAuth 프록시란 무엇인가요?

대부분의 인터넷 서비스에서는 사용자를 대신하여 해당 인터넷 서비스 저장소의 개인정보에 액세스 권한을 부여하는 REST API를 제공하기 시작했습니다. 예를 들어 인터넷 서비스에서 사용자에게 본인의 사진, 이메일, 주소록, 건강 기록 등에 대한 액세스 권한을 부여할 수 있습니다. OAuth는 표준의 하나로 개인정보의 계정 소유자가 다른 웹사이트(또는 가젯)에서의 데이터 액세스를 허용하도록 호스팅 서비스에 지정할 수 있습니다. OAuth 프록시는 가젯의 OAuth 표준을 사용하기 쉽도록 하기 위해 설계되었습니다.

참고: OAuth 프록시는 오픈소셜 컨테이너에서 실행되는 가젯의 gadgets.* API에서만 지원됩니다. 기존 가젯의 API에서는 지원하지 않습니다. 현재 iGoogle이라는 가젯 컨테이너에서 이 기능을 지원합니다. 한편 Shindig라는 오픈소스 프로젝트를 통해 OAuth 프록시 기능뿐 아니라 가젯 명세를 구현합니다. 다른 많은 인터넷 웹사이트에서도 이 기술을 평가 및 구현하는 중입니다.

대상

이 문서는 OAuth 프로토콜을 사용하여 사용자의 서비스와 통신하려는 가젯 개발자용으로 작성되었으며, 액세스하려는 서비스에 친숙하고 액세스/인증 문제가 포함되어 있음을 알고 있다는 전제 하에 설명합니다. 가젯 인증 프록시 서비스를 사용할 때는 몇 가지 서비스 특정 세부사항을 알고 있어야 합니다.

목차

  1. OAuth 프록시란 무엇인가요?
  2. OAuth를 지원하는 REST API가 있는 인터넷 서비스는 무엇인가요?
  3. 주요 개념
  4. 서비스 제공업체 선택
    1. Google 서비스 제공업체
    2. 비 Google 서비스 제공업체
  5. 엔드포인트 선택
  6. 예제 가젯 둘러보기
  7. OAuth 가젯 구현
    1. 예제 가젯
    2. OAuth 섹션
    3. 승인 과정 구현
    4. makeRequest()에 대해 자세히 알아보기
  8. Google 데이터 API: 대안적 접근방식
  9. 팝업 창 건너뛰기
    1. 사전 승인 URL 구현
    2. 사용자 환경설정 추가
  10. 기타 예제
  11. 고급 OAuth 기술

OAuth를 지원하는 REST API가 있는 인터넷 서비스는 무엇인가요?

Google에서 사용 가능한 모든 REST API(웹 응용프로그램에 대한 OAuth 인증 및 Google 데이터 API 문서 참조)뿐 아니라 MySpace의 데이터 가용성 API에서 OAuth를 지원합니다. OAuth 커뮤니티 wiki에는 이외에도 OAuth 사용 API를 제공하는 서비스 제공업체가 추가로 나와 있습니다.

주요 개념

아래 표에는 기본적인 OAuth 용어에 대한 정의가 나와 있습니다. 자세한 내용은 OAuth 상세정보 및 웹 응용프로그램에 대한 OAuth 인증을 참조하십시오.

용어정의
서비스 제공업체OAuth를 통한 액세스를 허용하는 웹 응용프로그램입니다. 예를 들어 Google이나 MySpace입니다.
사용자서비스 제공업체에 계정을 보유한 개인으로 서비스 제공업체에 OAuth를 통해 액세스할 수 있는 데이터를 보유할 수 있습니다. 예를 들어 가젯이 OAuth를 통해 사용자의 Google 캘린더 데이터에 액세스할 수 있습니다.
소비자OAuth를 사용하여 사용자 대신 서비스 제공업체에 액세스하는 웹사이트 또는 웹 응용프로그램입니다. 이런 맥락에서 OAuth를 통해 사용자의 데이터에 액세스하는 가젯은 소비자가 됩니다.
보호된 리소스서비스 제공업체에서 관리하는 데이터로 소비자(가젯)가 인증을 통해 이 데이터에 액세스할 수 있습니다.
컨테이너컨테이너란 가젯을 포함하는 오픈소셜 환경입니다. 예를 들어 iGoogle은 컨테이너입니다. 컨테이너는 가젯을 대신하여 다양한 기능을 지원할 뿐 아니라 가젯의 레이아웃 및 제어를 관리합니다. OAuth 가젯은 OAuth를 지원하는 컨테이너에서만 실행할 수 있습니다. 가젯이 OAuth를 사용하는 경우 실제로는 컨테이너에서 가젯 대신 OAuth 프로토콜에 필요한 모든 디지털 서명을 처리하여 해당 프로토콜을 실행합니다.
소비자 키가젯이 서비스 제공업체에서 해당 가젯을 식별하도록 사용하는 값으로서oauth_consumer_key 매개변수에 해당하는 값입니다. 자세한 내용은 OAuth 상세정보를 참조하십시오.
소비자 비밀번호가젯에서 소비자 키 소유권을 설정하는 데 사용하는 비밀번호입니다.
요청 토큰가젯에서 사용자의 인증을 얻을 때 사용하는 값으로서 액세스 토큰과 교환됩니다.
액세스 토큰가젯에서 사용자 대신 보호된 리소스에 액세스하는 데 사용하는 값으로서 사용자의 서비스 제공업체 자격 증명 대신 사용합니다.
토큰 비밀번호가젯에서 해당 토큰의 소유권을 설정하는 데 사용하는 비밀번호입니다.

예를 들어 Google 데이터 API를 통해 사용자의 비공개 캘린더 데이터에 액세스하는 가젯이 있다고 합시다. 이 시나리오에서 Google은 서비스 제공업체이고 가젯은 소비자입니다. 사용자는 가젯을 사용하여 개인 캘린더 데이터에 액세스하는 사람입니다.

사용자가 처음 가젯을 실행하면 가젯은 사용자를 서비스 제공업체 사이트로 보내고 해당 사이트에서는 사용자에게 사용자의 캘린더 데이터에 액세스할 수 있는 권한을 가젯에 허용하도록 요청합니다. 이러한 인증은 OAuth를 통해 처리됩니다. 사용자가 본인의 Google 계정에 로그인하여 가젯에 권한을 부여하는 순간부터 가젯은 사용자가 명시적으로 부여한 권한을 취소하지 않는 한 계속 사용자의 캘린더 데이터에 액세스할 수 있습니다. 사용자는 로그인하여 가젯을 통해 데이터에 액세스할 수 있는 권한을 다시 부여할 필요가 없습니다.

서비스 제공업체 선택

OAuth 가젯을 만드는 첫 번째 단계는 서비스 제공업체 선택입니다. 다음과 같은 두 가지의 OAuth 사용 사례가 있습니다.

  • Google Data 또는 다른 Google 서비스 제공업체의 데이터를 요청하는 경우.
  • Google 이외의 서비스 제공업체의 데이터를 요청하는 경우.

옵션에 대한 자세한 내용은 다음과 같습니다.

Google 서비스 제공업체

Google 데이터 API에 액세스하는 경우에는 액세스하려는 Google 데이터 REST API 엔드포인트를 지정하기만 하면 됩니다.<ModulePrefs> 섹션의 <OAuth> 섹션과 엔드포인트에서 데이터를 요청하는 가젯의 코드에서 엔드포인트를 지정합니다.

비 Google 서비스 제공업체

비 Google 엔드포인트에 액세스할 경우 보통 비 Google 서비스 제공업체에 해당 응용프로그램을 등록해야 합니다(예: MySpace 등록 참조). 회사에서 자사의 OAuth 서비스 제공업체 엔드포인트를 노출하려 하는 경우 회사에서 작성한 가젯에 한한 경우라도 Google에서 유지 관리하는 고급 OAuth 기술 사이트 내용을 참조하시기 바랍니다. 

사용자가 Google 이외의 서비스 제공업체에 응용프로그램을 등록하면 해당 서비스 제공업체는 응용프로그램에서 서비스 제공업체에 보내는 모든 요청에 디지털 서명을 하는 데 사용하는 OAuth 소비자 비밀번호를 제공합니다. 가젯은 누구나 액세스할 수 있으므로 비밀번호와 같은 유형의 정보를 저장하기에 적당하지 않습니다. 대신 가젯을 실행할 컨테이너를 제공하는 웹사이트에 OAuth 소비자 비밀번호를 등록할 수 있는데 이때 해당 웹사이트가 OAuth 프록시를 제공해야 합니다.

iGoogle의 경우 OAuth 소비자 비밀번호를 등록하려면 다음 정보를 포함한 메일을 oauthproxyreg@google.com으로 보내면 됩니다.

  • 가젯의 URL.
  • 서비스 제공업체에서 사용자에게 할당한 OAuth 소비자 키. OAuth 소비자 키는 제3자 웹 응용프로그램임을 식별하는 도메인입니다. 이 도메인은 서비스 제공업체에 응용프로그램을 등록할 때 사용하는 도메인이므로 서비스 제공업체는 등록한 응용프로그램의 요청임을 식별할 수 있습니다.
  • 서비스 제공업체에서 사용자에게 할당한 OAuth 소비자 비밀번호. 이 비밀번호는 응용프로그램에서 서비스 제공업체에 보내는 모든 요청에 디지털 서명을 하는 데 사용합니다.
  • 서비스 제공업체와의 대칭 또는 비대칭 서명 사용 여부(또는 모른다고 할 수 있음).

OAuth 소비자 비밀번호를 등록해야만 가젯이 작동합니다. 가젯의 URL을 변경하면 해당 가젯의 비밀번호를 다시 등록해야 합니다.

대부분의 OAuth 서비스 제공업체는 OAuth 소비자 키와 소비자 비밀번호를 요청할 경우 OAuth callback URL을 입력하도록 요청합니다. 가젯에 http://oauth.gmodules.com/gadgets/oauthcallback의 콜백 URL을 지정할 수 있습니다.

OAuth 서비스 제공업체 참고사항

개발 커뮤니티에서 이러한 직접 입력 단계를 거치지 않도록 하려면 대신 iGoogle에서 직접 디지털 서명을 승인하도록 OAuth 구성을 추가할 수 있습니다. iGoogle은 현재 OAuth 표준에 정의된 RSA_SHA1 서명 메서드와 여기에서 다양한 프로그래밍 언어로 구현된 OAuth 라이브러리로 쉽게 가져올 수 있는 자체 서명 인증서 형태로 제공하는 공개 키를 사용합니다.

-----BEGIN CERTIFICATE-----
MIIDBDCCAm2gAwIBAgIJAK8dGINfkSTHMA0GCSqGSIb3DQEBBQUAMGAxCzAJBgNV
BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzETMBEG
A1UEChMKR29vZ2xlIEluYzEXMBUGA1UEAxMOd3d3Lmdvb2dsZS5jb20wHhcNMDgx
MDA4MDEwODMyWhcNMDkxMDA4MDEwODMyWjBgMQswCQYDVQQGEwJVUzELMAkGA1UE
CBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxEzARBgNVBAoTCkdvb2dsZSBJ
bmMxFzAVBgNVBAMTDnd3dy5nb29nbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GN
ADCBiQKBgQDQUV7ukIfIixbokHONGMW9+ed0E9X4m99I8upPQp3iAtqIvWs7XCbA
bGqzQH1qX9Y00hrQ5RRQj8OI3tRiQs/KfzGWOdvLpIk5oXpdT58tg4FlYh5fbhIo
VoVn4GvtSjKmJFsoM8NRtEJHL1aWd++dXzkQjEsNcBXwQvfDb0YnbQIDAQABo4HF
MIHCMB0GA1UdDgQWBBSm/h1pNY91bNfW08ac9riYzs3cxzCBkgYDVR0jBIGKMIGH
gBSm/h1pNY91bNfW08ac9riYzs3cx6FkpGIwYDELMAkGA1UEBhMCVVMxCzAJBgNV
BAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUg
SW5jMRcwFQYDVQQDEw53d3cuZ29vZ2xlLmNvbYIJAK8dGINfkSTHMAwGA1UdEwQF
MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAYpHTr3vQNsHHHUm4MkYcDB20a5KvcFoX
gCcYtmdyd8rh/FKeZm2me7eQCXgBfJqQ4dvVLJ4LgIQiU3R5ZDe0WbW7rJ3M9ADQ
FyQoRJP8OIMYW3BoMi0Z4E730KSLRh6kfLq4rK6vw7lkH9oynaHHWZSJLDAp17cP
j+6znWkN9/g=
-----END CERTIFICATE-----

iGoogle은 OAuth 가젯 확장 기능 초안에서 대표로 서비스 제공업체에 대한 요청을 수행할 가젯의 URL을 제공합니다.

엔드포인트 선택

엔드포인트는 가젯이 서비스 제공업체를 통해 개인정보에 액세스하는 데 사용하는 URL입니다. 사용 가능한 엔드포인트를 검색하려면 서비스 제공업체 문서를 참조하십시오. 가젯이 Google 데이터 API를 지원하는 Google 서비스를 통해 데이터를 요청하는 경우 각 서비스에서 지원하는 엔드포인트를 보려면 Google 데이터 API 문서를 참조하십시오. 일부 엔드포인트의 경우 OAuth를 통해 수행하는 인증이 필요하지만 인증이 필요하지 않은 경우도 있습니다. 다음은 Google 데이터 엔드포인트의 몇 가지 예입니다.

  • http://www.google.com/m8/feeds/contacts/default/full/ -- 현재 로그인한 사용자의 연락처가 들어있는 피드를 가져옵니다.
  • http://gdata.youtube.com/feeds/api/users/default/uploads?alt=json -- 현재 로그인한 사용자가 업로드한 YouTube 동영상을 포함한 JSON 형식의 피드를 가져옵니다.
  • http://gdata.youtube.com/feeds/api/users/username/uploads -- 사용자 이름에 지정된 사용자의 YouTube 동영상을 포함한 피드를 가져옵니다. 이 경우 인증이 필요하지 않습니다.

가젯은 특정 범위 내 데이터에만 액세스할 수 있습니다. 가젯이 scope=http://www.google.com/m8/feeds/에 대한 액세스를 요청하는 경우에는 연락처 API의 엔드포인트(피드)만 사용할 수 있습니다. 하나의 가젯이 여러 개의 범위를 요청할 수 있습니다.

예제 가젯 둘러보기

이 문서에서는 간단한 가젯을 하나 예를 들어 OAuth 가젯이 어떤 식으로 작동하는지 보여줍니다. 예제 가젯은 현재 로그인한 사용자의 연락처를 가져와 표시합니다. OAuth 가젯이 어떤 식으로 작동하는지 보려면 다음 둘러보기를 따라 단계적으로 살펴봅니다.

OAuth 가젯은 gadgets.* API를 기반으로 해야 하며 OAuth를 지원하는 오픈소셜 컨테이너 안에서 실행됩니다. iGoogle에서 OAuth 가젯을 구현할 수 있습니다.

iGoogle에 가젯을 추가하려면 다음 단계를 수행합니다.

  1. http://www.google.com/ig로 이동합니다.
  2. 해당 페이지를 원하는 대로 만들기 버튼을 클릭하여 iGoogle 디렉토리로 이동합니다.
  3. 왼쪽 탐색 막대 아래쪽의 피드나 가젯을 추가하세요 링크를 클릭합니다.
  4. 예제 가젯의 URL(http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/oauth-contacts.xml)을 입력란에 입력한 다음 추가를 클릭합니다.
  5. iGoogle 홈으로 돌아가기 링크(왼쪽 상단)를 클릭하여 iGoogle로 돌아가면 예제 가젯이 표시됩니다.

새로 추가한 예제 가젯에는 '가젯을 원하는 대로 만들기'라고 표시된 링크가 나타납니다.이 링크에는 요청 토큰이 포함되어 있습니다. 데이터에 대한 액세스를 허가하려면 다음 단계를 따르세요.

  1. '가젯을 원하는 대로 만들기' 링크를 클릭합니다.
  2. 계정이 여러 개 있는 경우 Google 계정 페이지가 나타날 수 있는데 '제3자 서비스에서 사용자의 Google 계정에 액세스할 수 있는 권한을 요청하고 있습니다.'라는 메시지가 표시됩니다.액세스할 데이터를 보유한 계정을 선택합니다.
  3. 그러면 Google 계정 액세스 요청 페이지가 표시되며 'www.google.com 사이트에서 아래에 나열된 제품과 관련하여 Google 계정에 대한 액세스를 요청하고 있습니다.'와 같은 메세지가 표시됩니다.사이트(컨테이너)에서 액세스하려는 데이터와 관련있는 제품의 목록이 나열됩니다. 액세스 허가을 클릭합니다. 요청 토큰이 액세스 토큰과 교환되어 가젯이 지정한 서비스에서 데이터를 가져올 수 있습니다.
  4. iGoogle로 돌아갑니다. 이때 가젯에 데이터가 표시되어야 합니다. 자세한 내용은 승인 과정 구현을 참조하십시오.

이후에는 가젯을 삭제하거나 Google 계정으로 이동하여 액세스를 취소하지 않는 한 계속 가젯은 데이터에 액세스할 수 있습니다. 즉 1회만 액세스를 허가하면 됩니다.

예제 가젯은 사용자에게 승인 과정을 안내하기 위한 한 가지 접근방식을 보여줍니다. 특정 구현과 관계없이 가젯은 다음 작업을 수행해야 합니다.

  • 사용자 데이터를 가져오려고 시도합니다.
  • 가져오기에 성공하면 데이터를 표시합니다.
  • 가져오지 못하면 팝업 창에 사용자가 액세스를 허용하도록 메시지를 표시합니다.
  • 팝업 창이 닫히면 다시 한번 가져오기를 시작하여 사용자의 데이터를 가져옵니다. 가젯에 액세스 토큰이 연결되어 있으면 가젯을 실행할 때마다 자동으로 데이터를 가져옵니다.

Shindig 프로젝트에서는 팝업 창을 만들고 팝업 창이 닫혔는지 탐지하는 데 사용하는 자바스크립트 라이브러리를 제공합니다. 이 항목에 대한 자세한 내용은 승인 과정 구현.을 참조하십시오.

OAuth 가젯 구현

원하는 데이터를 가져올 때 사용할 엔드포인트와 서비스 제공업체를 정했으면 가젯을 구현할 준비가 되었습니다.

OAuth 가젯은 일반적인 가젯의 기능 외에도 다음 항목을 포함해야 합니다.

  • 서비스 제공업체 이름.
  • 엔드포인트.
  • 가젯에서 사용할 서비스와 엔드포인트에 대한 세부정보를 지정하는 가젯의 <ModulePrefs> 섹션 내 <OAuth...> 섹션.
  • 사용자가 데이터 액세스를 승인했는지 탐지하는 메커니즘. 사용자가 아직 액세스를 허용하지 않았으면, 가젯은 예를 들어 서비스 제공업체의 OAuth 인증 URL과 연결된 링크를 사용자에게 나타내서 사용자가 서비스 제공업체로 이동하는 경로를 제공해야 합니다. 이후에는 서비스 제공업체에서 사용자에게 인증 및 승인 과정을 안내합니다. 사용자가 데이터 액세스를 승인하면 가젯은 사용자의 데이터에 액세스할 수 있습니다.
  • 인증된 데이터를 가져오기 위한 올바른 OAuth 매개변수를 포함한 gadgets.* makeRequest() 함수 호출.
  • 반환 데이터의 처리 코드. 해당 가젯과 관련된 의미가 있습니다.

이 섹션에서는 OAuth 가젯의 작동 방식을 이해하도록 섹션별로 예제 가젯을 살펴보도록 하겠습니다.

예제 가젯

예제 가젯은 Google 주소록 데이터 API를 통해 현재 로그인한 사용자의 연락처를 가져오며, 엔드포인트(http://www.google.com/m8/feeds/contacts/default/full)를 사용하여 요청할 자격이 있는 사용자의 연락처를 반환하도록 서버에 지시합니다. 연락처는 JSON 형식의 ATOM XML 결과(http://www.google.com/m8/feeds/contacts/default/full?alt=json)로 반환됩니다. 자세한 내용은 Google 데이터 API와 함께 JSON 사용을 참조하십시오.

다음은 모든 요소를 갖춘 가젯으로서 자세한 내용은 다음과 같습니다.

<?xml version="1.0" encoding="UTF-8" ?> 
<Module>
  <ModulePrefs title="OAuth Contacts" scrolling="true">
    <Require feature="opensocial-0.8" />
    <Require feature="locked-domain"/> 
    <OAuth>
      <Service name="google">
        <Access url="https://www.google.com/accounts/OAuthGetAccessToken" method="GET" /> 
        <Request url="https://www.google.com/accounts/OAuthGetRequestToken?scope=http://www.google.com/m8/feeds/" method="GET" /> 
        <Authorization url="https://www.google.com/accounts/OAuthAuthorizeToken?oauth_callback=http://oauth.gmodules.com/gadgets/oauthcallback" /> 
      </Service>
    </OAuth>
  </ModulePrefs>
  <Content type="html">
  <![CDATA[ 
 
  <!-- shindig oauth popup handling code -->
  <script src="http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/popup.js"></script>

  <style>
  #main {
    margin: 0px;
    padding: 0px;
    font-size:10pt;
  }
  </style>

  <div id="main" style="display: none">
  </div>

  <div id="approval" style="display: none">
    <img src="http://gadget-doc-examples.googlecode.com/svn/trunk/images/new.gif">
    <a href="#" id="personalize">Personalize this gadget</a>
  </div>

  <div id="waiting" style="display: none">
    Please click
    <a href="#" id="approvaldone">I've approved access</a>
    once you've approved access to your data.
  </div>

  <script type="text/javascript">
    // Display UI depending on OAuth access state of the gadget (see <divs> above).
    // If user hasn't approved access to data, provide a "Personalize this gadget" link
    // that contains the oauthApprovalUrl returned from makeRequest.
    //
    // If the user has opened the popup window but hasn't yet approved access, display
    // text prompting the user to confirm that s/he approved access to data.  The user
    // may not ever need to click this link, if the gadget is able to automatically
    // detect when the user has approved access, but showing the link gives users
    // an option to fetch their data even if the automatic detection fails.
    //
    // When the user confirms access, the fetchData() function is invoked again to
    // obtain and display the user's data.
    function showOneSection(toshow) {
      var sections = [ 'main', 'approval', 'waiting' ];
      for (var i=0; i < sections.length; ++i) {
        var s = sections[i];
        var el = document.getElementById(s);
        if (s === toshow) {
          el.style.display = "block";
        } else {
          el.style.display = "none";
        }
      }
    }
      
    // Process returned JSON feed to display data.
    function showResults(result) {
      showOneSection('main');

      var titleElement = document.createElement('div');
      var nameNode = document.createTextNode(result.feed.title.$t);
      titleElement.appendChild(nameNode);
      document.getElementById("main").appendChild(titleElement);
      document.getElementById("main").appendChild(document.createElement("br"));

      list = result.feed.entry;

      for(var i = 0; i < list.length; i++) {
        entry = list[i];
        var divElement = document.createElement('div');
        divElement.setAttribute('class', 'name');
        var valueNode = document.createTextNode(entry.gd$email[0].address);
        divElement.appendChild(nameNode);
        divElement.appendChild(valueNode);
        document.getElementById("main").appendChild(divElement);
      }
    }

    // Invoke makeRequest() to fetch data from the service provider endpoint.
    // Depending on the results of makeRequest, decide which version of the UI
    // to ask showOneSection() to display. If user has approved access to his
    // or her data, display data.
    // If the user hasn't approved access yet, response.oauthApprovalUrl contains a
    // URL that includes a Google-supplied request token. This is presented in the 
    // gadget as a link that the user clicks to begin the approval process.     
    function fetchData() {
      var params = {};
      url = "http://www.google.com/m8/feeds/contacts/default/base?alt=json";
      params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
      params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.OAUTH;
      params[gadgets.io.RequestParameters.OAUTH_SERVICE_NAME] = "google";
      params[gadgets.io.RequestParameters.OAUTH_USE_TOKEN] = "always";
      params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;

      gadgets.io.makeRequest(url, function (response) { 
        if (response.oauthApprovalUrl) {
          // Create the popup handler. The onOpen function is called when the user
          // opens the popup window. The onClose function is called when the popup
          // window is closed.
          var popup = shindig.oauth.popup({
            destination: response.oauthApprovalUrl,
            windowOptions: null,
            onOpen: function() { showOneSection('waiting'); },
            onClose: function() { fetchData(); }
          });
          // Use the popup handler to attach onclick handlers to UI elements.  The
          // createOpenerOnClick() function returns an onclick handler to open the
          // popup window.  The createApprovedOnClick function returns an onclick 
          // handler that will close the popup window and attempt to fetch the user's
          // data again.
          var personalize = document.getElementById('personalize');
          personalize.onclick = popup.createOpenerOnClick();
          var approvaldone = document.getElementById('approvaldone');
          approvaldone.onclick = popup.createApprovedOnClick();
          showOneSection('approval');
        } else if (response.data) {
          showOneSection('main');
          showResults(response.data);
        } else {
          // The response.oauthError and response.oauthErrorText values may help debug
          // problems with your gadget.
          var main = document.getElementById('main');
          var err = document.createTextNode('OAuth error: ' +
            response.oauthError + ': ' + response.oauthErrorText);
          main.appendChild(err);
          showOneSection('main');
        }
      }, params);
    }
    // Call fetchData() when gadget loads.
    gadgets.util.registerOnLoadHandler(fetchData);
  </script>
  ]]> 
  </Content>
</Module>

참고: 가젯에 <Require feature="locked-domain"/> 행을 포함하여 도메인 잠금 기능을 선택하시기 바랍니다. 또한 자체popup.js 사본을 호스팅하는 것이 좋습니다.

<OAuth> 섹션

가젯에 제일 먼저 포함해야 하는 부분은 <ModulePrefs> 섹션 내 <OAuth> 섹션입니다.

<?xml version="1.0" encoding="UTF-8" ?> 
<Module>
  <ModulePrefs title="OAuth Contacts" scrolling="true">
    <Require feature="opensocial-0.8" /> 
    <Require feature="locked-domain"/> 
    <OAuth>
      <Service name="google">
        <Access url="https://www.google.com/accounts/OAuthGetAccessToken" method="GET" /> 
        <Request url="https://www.google.com/accounts/OAuthGetRequestToken?scope=http://www.google.com/m8/feeds/" method="GET" /> 
        <Authorization url="https://www.google.com/accounts/OAuthAuthorizeToken?oauth_callback=http://oauth.gmodules.com/gadgets/oauthcallback" /> 
      </Service>
    </OAuth>
  </ModulePrefs>

OAuth 섹션에서는 컨테이너에 다음과 같은 가젯의 OAuth 서비스 구성을 제공합니다.

요소설명
/ModulePrefs/OAuth/Service요소는 하나의 OAuth 서비스 구성입니다.

속성:
  • name -- 실행 시 OAuth 서비스를 참조하는 데 사용되는 서비스의 이름입니다. 매개변수는 선택사항입니다. 지정하지 않을 경우 기본값은 ""입니다. 가젯 개발자는 서비스 이름을 매개변수로 makeRequest() 함수에 전달하여 사용할 OAuth 서비스를 지정합니다.
/ModulePrefs/OAuth/Service/Request
/ModulePrefs/OAuth/Service/Access
이들 요소는 OAuth 요청 토큰 및 액세스 토큰 URL을 나타냅니다. 자세한 내용은 OAuth 상세정보 및 웹 응용프로그램에 대한 OAuth 인증을 참조하십시오. 

속성:
  • url -- 엔드포인트 URL입니다.
  • method -- 요청 시 사용할 HTTP 동사입니다. 매개변수는 선택사항입니다. 지정하지 않을 경우 기본값은 POST입니다.
/ModulePrefs/OAuth/Service/AuthorizationOAuth 인증 URL입니다. 가젯이 사용자의 데이터에 액세스하기 위한 승인을 요청해야 하는 경우 이 URL로 이동하는 팝업 창이 열립니다.

인증 URL에는 oauth_callback 쿼리 매개변수가 포함됩니다. OAuth 서비스 제공업체는 사용자가 데이터 액세스를 허용한 후에 이 URL로 리디렉션됩니다. 이때 http://oauth.gmodules.com/gadgets/oauthcallback을 oauth_callback URL로 지정합니다. oauthcallback 페이지에는 자동으로 팝업 창을 닫는 자바스크립트 짧은 코드가 포함됩니다. 가젯은 언제 팝업 창이 닫히는지 탐지하여 사용자의 데이터를 가져오려고 합니다.

승인 과정 구현

OAuth 가젯은 인증된 사용자의 데이터를 가져옵니다. 이를 위해 사용자는 이 예제의 Google Data Contacts와 같은 서비스에서 가젯과 사용자 데이터를 공유하도록 허용해야 합니다.

예를 들어 연락처 예제 가젯을 생각해 봅시다. 다음과 같은 순서로 이벤트가 발생합니다.

  1. 가젯을 실행하면 fetchData() 함수를 호출하는 gadgets.util.registerOnLoadHandler(fetchData)를 호출합니다.
  2. fetchData() 함수는 makeRequest() 함수를 호출합니다.
  3. makeRequest() 함수가 callback 매개변수를 지정합니다. 콜백 매개변수는 makeRequest() 함수에서 반환한 일반적인 값 외에 몇 가지 OAuth에 해당하는 필드가 있는 자바스크립트 개체에 전달됩니다

다음은 fetchData() 함수입니다.

function fetchData() {
  var params = {};
  url = "http://www.google.com/m8/feeds/contacts/default/base?alt=json";
  params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
  params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.OAUTH;
  params[gadgets.io.RequestParameters.OAUTH_SERVICE_NAME] = "google";
  params[gadgets.io.RequestParameters.OAUTH_USE_TOKEN] = "always";
  params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;

  gadgets.io.makeRequest(url, function (response) { 
    if (response.oauthApprovalUrl) {
      // Create the popup handler. The onOpen function is called when the user
      // opens the popup window. The onClose function is called when the popup
      // window is closed.
      var popup = shindig.oauth.popup({
        destination: response.oauthApprovalUrl,
        windowOptions: null,
        onOpen: function() { showOneSection('waiting'); },
        onClose: function() { fetchData(); }
      });
      // Use the popup handler to attach onclick handlers to UI elements.  The
      // createOpenerOnClick() function returns an onclick handler to open the
      // popup window.  The createApprovedOnClick function returns an onclick 
      // handler that will close the popup window and attempt to fetch the user's
      // data again.
      var personalize = document.getElementById('personalize');
      personalize.onclick = popup.createOpenerOnClick();
      var approvaldone = document.getElementById('approvaldone');
      approvaldone.onclick = popup.createApprovedOnClick();
      showOneSection('approval');
    } else if (response.data) {
      showOneSection('main');
      showResults(response.data);
    } else {
      // The response.oauthError and response.oauthErrorText values may help debug
      // problems with your gadget.
      var main = document.getElementById('main');
      var err = document.createTextNode('OAuth error: ' +
        response.oauthError + ': ' + response.oauthErrorText);
      main.appendChild(err);
      showOneSection('main');
    }
  }, params);
}

가젯이 callback을 처리할 때는 response.oauthApprovalUrl에 널(null)이 아닌 값이 있는지를 먼저 확인합니다. 사용자가 데이터에 대한 액세스를 아직 허가하지 않은 경우 response.oauthApprovalUrl에는 사용자가 가젯에 데이터 액세스를 허용하기 위해 방문해야 하는 URL이 표시됩니다. 이때 해당 URL의 일부는 서비스 제공업체(이 경우 Google)에서 발급한 요청 토큰입니다.

가젯은 먼저 팝업 창을 관리할 shindig.oauth.popup 개체를 만듭니다. 이 shindig.oauth.popup 개체에는 다음과 같은 몇 가지 매개변수가 포함됩니다.

var popup = shindig.oauth.popup({
  destination: response.oauthApprovalUrl,
  windowOptions: null,
  onOpen: function() { showOneSection('waiting'); },
  onClose: function() { fetchData(); }
});

destination 매개변수는 팝업 창이 열리는 URL을 지정합니다 .

windowOptions 매개변수는 브라우저에서 제공한 window.open 함수에 전달할 옵션을 지정합니다. 이 옵션을 통해 팝업 창의 크기, 위치 및 색상을 제어할 수 있습니다 브라우저가 다르면 window.open에 지원하는 매개변수도 다르므로 Internet Explorer,Firefox 등의 문서를 참조하십시오.

onOpen 함수는 사용자가 링크를 클릭하여 팝업 창을 열 때 호출됩니다. 그러면 가젯은 showOneSection('waiting')을 호출하여 사용자의 액세스 허가를 대기하는 동안 해당 메시지를 표시합니다.

onClose 함수는 팝업 창이 닫히면 호출됩니다. 가젯은 fetchData() 호출을 등록하여 팝업 창이 닫힌 후 사용자 데이터를 가져옵니다.

팝업 개체를 만든 후에는 onclick 핸들러를 팝업 창이 열리게 만드는 DOM 요소와 연결해야 합니다. 가젯은 approval <div> 내의 personalize HREF가 팝업 창을 열도록 onclick 핸들러를 설정합니다.

var personalize = document.getElementById('personalize');
personalize.onclick = popup.createOpenerOnClick();

가젯은 또한 waiting <div>의 approvaldone HREF를 popup.createApprovedOnClick() 핸들러로 구성합니다. approvaldoneHREF를 클릭하면 가젯은 팝업 창을 닫고 사용자의 데이터를 가져오려고 시도합니다. 승인을 완료했습니다 링크를 클릭하지 않아도 된다면 좋겠지만 클릭해야 한다면 onclick 핸들러를 다음과 같이 연결해야 합니다.

var approvaldone = document.getElementById('approvaldone');
approvaldone.onclick = popup.createApprovedOnClick();

가젯에 사용자가 링크를 클릭하여 팝업 창을 열도록 요청하는 approval <div>가 표시됩니다. 대부분의 브라우저에서는 팝업 차단기를 사용하여 불필요한 팝업 창이 나타나지 않도록 합니다. 팝업 차단기에서 차단되지 않도록 하려면 사용자가 버튼이나 링크를 클릭한 다음 가젯이 팝업 창을 열어야 합니다.

showOneSection('approval');

가젯은 <div>와 showOneSection() 함수를 사용하여 가젯의 승인 상태에 따른 UI를 표시합니다. 다음과 같은 3개의 <div>가 있는데 각각 가능한 3가지의 가젯 상태를 의미합니다.

  • approval -- 사용자가 아직 액세스를 허용하지 않은 경우 가젯은 approval <div>를 사용하여 요청 토큰을 포함한 '가젯을 원하는 대로 만들기' 링크와 함께 UI를 표시합니다. 사용자가 이 링크를 클릭하면 승인 과정이 시작됩니다.
  • waiting -- 사용자가 팝업 창을 열기는 했지만 액세스를 승인하지 않은 경우 가젯에 이 <div>가 표시됩니다. 가젯은 사용자가 데이터에 대한 액세스를 승인했는지 확인하도록 요청하는 메시지를 표시합니다. 사용자가 액세스를 승인했는지 가젯이 자동으로 탐지할 수 있으면 사용자가 이 링크를 클릭하지 않아도 되지만 링크를 표시하면 자동 탐색이 실패하는 경우에도 데이터를 가져오도록 사용자가 선택할 수 있습니다. 자동 탐색이 실패하면 가젯에 '데이터에 대한 액세스를 승인한 다음 액세스 승인 완료를 클릭하십시오.'라는 메시지가 표시됩니다.사용자가 클릭하면 가젯이 fetchData() 함수를 호출하여 사용자의 데이터를 가져옵니다.
  • main -- 액세스 토큰이 발급되면 가젯은 main <div>를 사용하여 가젯이 실행될 때마다 사용자의 데이터를 표시합니다. 이<div>는 오류를 표시할 때도 사용됩니다.
<div id="main" style="display: none">
  </div>

  <div id="approval" style="display: none">
    <img src="http://gadget-doc-examples.googlecode.com/svn/trunk/images/new.gif">
    <a href="#" id="personalize">Personalize this gadget</a>
  </div>

  <div id="waiting" style="display: none">
    Please click
    <a href="#" id="approvaldone">I've approved access</a>
    once you've approved access to your data.
  </div>

  <script type="text/javascript">
    function showOneSection(toshow) {
      var sections = [ 'main', 'approval', 'waiting' ];
      for (var i=0; i < sections.length; ++i) {
        var s = sections[i];
        var el = document.getElementById(s);
        if (s === toshow) {
          el.style.display = "block";
        } else {
          el.style.display = "none";
        }
      }
    }

makeRequest()에 대해 자세히 알아보기

makeRequest() 함수는 원격 콘텐츠 가져오기에 자세히 설명되어 있으며 원격 웹 콘텐츠를 가져오거나 작업하는 데 이 함수를 사용합니다. 다음 인수를 필요로 합니다.

  • String url - 콘텐츠가 있는 URL입니다.
  • Function callback - URL에서 데이터를 가져온 다음 데이터와 함께 호출하는 함수
  • Map.<gadgets.io.RequestParameters, Object> opt_params - 요청에 전달할 추가 매개변수입니다.

opt_params[gadgets.io.RequestParameters.AUTHORIZATION]을 gadgets.io.AuthorizationType.OAUTH로 설정하면 컨테이너에서 OAuth를 사용하여 요청에 지정된 리소스에 대한 액세스를 허가받아야 합니다. 이 경우 일반적으로 가젯은 사용자를 서비스 제공업체로 안내하여 액세스를 허가받도록 만들어 사용자의 콘텐츠를 가져와야 합니다.

선택 매개변수

opt_params에서 다음과 같은 OAuth 매개변수를 추가로 지정할 수 있습니다.

매개변수설명
gadgets.io.RequestParameters.OAUTH_SERVICE_NAME가젯이 XML 상세정보의 OAuth <Service> 요소를 참조하는 닉네임입니다. 서비스 이름은<ModulePrefs>의 /ModulePrefs/OAuth/ServiceXML 섹션에서도 지정할 수 있습니다. 둘 중 어디에서도 지정하지 않은 경우 기본값은 ""입니다.
gadgets.io.RequestParameters.OAUTH_TOKEN_NAME가젯에서 특정 리소스에 대한 액세스를 허용하는 OAuth 토큰을 지칭하는 닉네임입니다. 지정하지 않을 경우 기본값은 ""입니다. 가젯은 같은 서비스 제공업체의 여러 리소스에 대한 액세스 권한이 있는 경우 여러 개의 토큰 이름을 사용할 수 있습니다. 예를 들어 주소록 및 캘린더에 대한 액세스 권한이 있는 가젯은 "contacts"라는 이름의 토큰을 사용하여 주소록 토큰을 사용하거나 "calendar"의 주소록을 사용하여 캘린더 토큰을 사용할 수 있습니다.
gadgets.io.RequestParameters.OAUTH_REQUEST_TOKEN서비스 제공업체는 리소스에 대한 액세스가 사전에 승인된 요청 토큰을 가젯에 자동으로 제공할 수 있습니다. 가젯은 이 토큰을 매개변수와 함께 사용할 수 있으며 매개변수는 선택사항입니다.
gadgets.io.RequestParameters.OAUTH_REQUEST_TOKEN_SECRET사전 승인된 요청 토큰에 해당하는 비밀번호이며 매개변수는 선택사항입니다.
gadgets.io.RequestParameters.OAUTH_USE_TOKEN

이 매개변수는 "never", "if_available" 또는 "always" 중 한 값이 될 수 있습니다. OAuth 액세스 토큰이 필요하지 않은 일부 서비스 제공업체 API로서 해당 API는 OAuth 소비자 키를 통해 호출 응용프로그램을 인증한 다음 요청을 진행하도록 허가합니다. 이러한 API에 액세스하기 위해 불필요한 사용자 승인 요청을 피하려면OAUTH_USE_TOKEN을 "never"로 설정합니다.

일부 OAuth API는 사용자가 승인하지 않은 경우 제한된 데이터를 제공하고 사용자가 호출 응용프로그램에 액세스 토큰을 허용한 경우에만 추가 기능을 제공할 수 있습니다. OAuth 액세스 토큰을 승인하는 API를 사용하지만 토큰이 필요하지 않은 경우에는OAUTH_USE_TOKEN을 "if_available"로 설정합니다. 사용자가 액세스를 이미 승인한 경우 액세스 토큰이 전송됩니다. 사용자가 액세스를 승인하지 않은 경우 요청은 액세스 토큰이 없어도 처리됩니다.

대부분의 OAuth API는 액세스 토큰이 전송되는 경우에만 작동합니다. 그러므로 이러한 API를 사용하려면 먼저 사용자의 승인을 요청해야 합니다. 액세스 토큰을 사용하려면 OAUTH_USE_TOKEN을 "always"로 설정합니다. 사용 가능한 액세스 토큰이 없으면 가젯에 승인 URL이 반환됩니다.

AUTHORIZATION을 SIGNED로 설정한 경우OAUTH_USE_TOKEN 기본값은 "never"입니다.AUTHORIZATION을 OAUTH로 설정한 경우OAUTH_USE_TOKEN 기본값은 "always"입니다.

OAuth를 사용하는 경우 컨테이너가 가젯을 대신하여 OAuth 프로토콜을 실행합니다. OAuth 서비스 제공업체 참고사항에 설명된 것처럼 가젯에 iGoogle에서 사용할 소비자 키를 등록하지 않았으면 iGoogle은 기본 RSA 서명 키를 사용합니다.

Callback 매개변수

makeRequest() 콜백 매개변수는 makeRequest() 함수에서 반환한 일반적인 값 외에 몇 가지 OAuth에 해당하는 필드가 있는 자바스크립트 개체로 전달됩니다.

OAuth 필드설명
oauthApprovalUrl이 값을 지정한 경우 값은 서비스 제공업체에서 발급한 요청 토큰을 포함하는 URL입니다. 널(null)이 아닌 값을 지정하면 사용자가 외부 페이지를 방문하여 가젯의 데이터 액세스 요청을 승인해야 합니다. 사용자를 외부 페이지로 안내하는 팝업 창을 사용하는 것이 좋습니다. 사용자가 액세스를 승인하면 가젯은 makeRequest() 호출을 반복하여 데이터를 가져올 수 있습니다.
oauthError이 값이 지정되어 있으면 OAuth 관련 오류가 발생했다는 의미입니다.
oauthErrorText이 값이 지정되어 있으면 OAuth 관련 오류가 발생했다는 의미입니다. 이 값을 사용하여 가젯 개발자에게 디버깅 정보를 제공할 수 있습니다. 매개변수:
  • String url -- 콘텐츠가 위치한 URL입니다.
  • Function callback --- URL에서 데이터를 가져온 다음 데이터와 함께 호출하는 함수입니다.
  • Map.<gadgets.io.RequestParameters, Object> opt_params -- 추가 요청 매개변수 또는 프록시 요청 매개변수입니다.

OAuth에 대한 오픈소셜 확장 기능

오픈소셜 컨테이너는 OAuth 요청에 추가로 서명된 매개변수를 전달하여 OAuth 서비스 제공업체 사이트에 보내는 요청에 대한 추가 콘텍스트 정보를 제공할 수 있습니다. opensocial_owner_idopensocial_app_url 같은 추가 매개변수에 대한 설명은gadgets.io.makeRequest 문서에 자세히 설명되어 있습니다. 오픈소셜을 인식하는 서비스 제공업체는 이들 매개변수를 사용하여 추가 데이터를 사용자에게 반환할 수 있습니다. 예를 들어 서비스 제공업체는 가젯의 사용자뿐 아니라 사용자의 친구에 대한 정보를 반환할 수도 있습니다.

Google 데이터 API: 대안적 접근방식

위의 예제에서는 gadgets.* makeRequest() 메서드를 사용하여 데이터를 가져옵니다. 하지만 Google 데이터 API를 사용할 경우 OAuth 프록시와 같이 작동하는 Google 데이터 자바스크립트 라이브러리를 사용할 수 있습니다. 뒤에서 makeRequest()를 호출하므로 가젯에서의 최종 효과는 마찬가지입니다.

자세한 설명 및 예제를 보려면 Google 데이터 가젯 만들기 항목을 참조하십시오.

팝업 창 건너뛰기

OAuth 서비스 제공업체의 경우 승인 팝업 창이 표시되지 않도록 하여 가젯에 대한 사용자의 만족도를 향상시킬 수 있습니다. 사용자가 해당 사이트의 가젯을 추가하면 사용자 데이터에 대한 액세스를 받는 데 사용하는 사전 승인된 OAuth 요청 토큰을 iGoogle에 전달합니다.

승인 과정은 다음과 같습니다.

  1. 사용자가 서비스 제공업체 사이트에 로그인합니다.
  2. 서비스 제공업체 사이트에는 Google에 추가 링크가 있습니다. 서비스 제공업체는 이 링크에 일반적으로 사용하는Google에 추가 로고를 사용해야 합니다.
  3. 링크 대상은 사전 승인된 OAuth 요청 토큰을 발급할 수 있는 서비스 제공업체 사이트의 특수 URL입니다. 이 URL은 보안상의 이유로 CSRF 공격에 대비해 보호해야 합니다.
  4. 서비스 제공업체의 사전 승인 URL에서 사용자를 인증하고 사용자 데이터에 대한 액세스를 허용하는 사전 승인된 OAuth 요청 토큰을 만듭니다. 그런 다음 사전 승인 URL에서 사용자에게 iGoogle addmodule URL로의 리디렉션을 전송합니다. 리디렉션 URL에는 요청 토큰과 선택하는 경우 요청 토큰 비밀번호가 포함됩니다.
  5. iGoogle에서 사용자에게 가젯을 추가할지 확인하도록 요청합니다.
  6. 사용자가 가젯을 추가할지 확인하면 사전 승인된 요청 토큰이 OAuth 액세스 토큰과 교환되어 사용자의 데이터를 즉시 사용할 수 있습니다.

사전 승인 URL 구현

OAuth 사전 승인 URL에서는 사전 승인된 OAuth 요청 토큰을 만든 다음 사용자를 토큰을 사용하는 addmodule URL로 리디렉션해야 합니다. 사전 승인된 OAuth 토큰을 만드는 방법은 OAuth 서비스 제공업체 상세정보에 따라 다르지만 사전 승인된 토큰은 다음과 같은 특성을 가져야 합니다.

  • 액세스할 데이터를 소유한 사용자를 식별해야 합니다.
  • 단지 몇 분 동안만 사용할 수 있도록 사용 기간이 짧아야 합니다.
  • 1회용이므로 토큰을 한번 사용하면 다른 사람이 토큰을 도용하더라도 사용자 데이터에 액세스할 수 없습니다.

서비스 제공업체 사이트에서 사전 승인된 요청 토큰을 만들면 해당 사이트는 사전 승인된 요청 토큰(및 선택한 경우 토큰 비밀번호)을 요청에 포함하여 iGoogle addmodule URL로 이동하는 리디렉션을 사용자에게 전송해야 합니다. 리디렉션은 다음과 같은 형태입니다.

http://www.google.com/ig/add?moduleurl=<URL OF GADGET>&up_request_token=<REQUEST TOKEN>&up_request_token_secret=<REQUEST TOKEN SECRET>

리디렉션 URL과 마찬가지로 쿼리 매개변수는 URL 인코딩해야 합니다.

up_ 프리픽스가 붙은 매개변수는 가젯에 대한 사용자 환경설정입니다. up_rt 매개변수 값은 가젯의 rt 사용자 환경설정 값이 됩니다. iGoogle에서는 사용자 환경설정에 영·숫자, 마침표(.) 문자 및 공백 입력만 허용합니다. 요청 토큰 또는 요청 토큰 비밀번호에 기타 문자가 포함되어 있으면 iGoogle에서 자동으로 그 값을 가젯에 추가하도록 허용하기 전에 인코딩해야하는 경우도 있습니다.

사용자 환경설정 추가

사전 승인된 요청 토큰을 사용하려면 가젯을 약간 수정해야 합니다. 먼저 setprefs 기능을 요청하고 요청 토큰 및 요청 토큰 비밀번호에 대한 두 가지 새로운 사용자 환경설정을 표시하도록 가젯 상세정보를 업데이트해야 합니다.

...
<ModulePrefs title="Preapproved OAuth Gadget" scrolling="true">
  <Require feature="setprefs" />
    <OAuth>
      <Service>
        ...
      </Service>
    </OAuth>
 </ModulePrefs>
 <UserPref name="request_token" required="false" datatype="hidden"></UserPref>
 <UserPref name="request_token_secret" required="false" datatype="hidden"></UserPref>
 ...

가젯 상세정보에 이들 매개변수를 추가하고 가젯 스크립트에서 새 사용자 환경설정을 gadgets.io.makeRequest() 함수로 전달해야 합니다. 예:

params.AUTHORIZATION = "OAUTH";
var prefs = new gadgets.Prefs();
var requestToken = prefs.getString("request_token");
if (requestToken !== "") {
  // We have a preapproved request token
  params.OAUTH_REQUEST_TOKEN = requestToken;
  params.OAUTH_REQUEST_TOKEN_SECRET = prefs.getString("request_token_secret");
  // Preapproved request tokens are only good once
  prefs.set("request_token", "");
  prefs.set("request_token_secret", "");
}
gadgets.io.makeRequest(url, callback, params);
 

코드에서는 먼저 request_token 사용자 환경설정을 사용해야 하는지 여부를 확인합니다.

var prefs = new gadgets.Prefs();
var requestToken = prefs.getString("request_token");
if (requestToken !== "") {
  ...
}

request_token 사용자 환경설정이 비어 있지 않으면 가젯은 params.OAUTH_REQUEST_TOKEN 및params.OAUTH_REQUEST_TOKEN_SECRET 값을 설정하여 사전 승인된 요청 토큰을 사용하려고 시도합니다.

if (requestToken !== "") {
  // We have a preapproved request token
  params.OAUTH_REQUEST_TOKEN = requestToken;
  params.OAUTH_REQUEST_TOKEN_SECRET = prefs.getString("request_token_secret");
  // Preapproved request tokens are only good once
  prefs.set("request_token", "");
  prefs.set("request_token_secret", "");
}

사전 승인된 요청 토큰은 한번만 사용할 수 있습니다. 가젯이 환경설정을 다시 사용하지 못하도록 하려면 환경설정을makeRequest() 매개변수에 복사하여 넣은 다음 prefs.set()를 호출하여 환결설정을 삭제해야 합니다.

prefs.set("request_token", "");
prefs.set("request_token_secret", "");

마지막 단계로 매개변수를 포함한 gadgets.io.makeRequest()를 호출합니다. 사전 승인된 요청 토큰이 유효한 경우 가젯은 사용자의 승인을 얻는 팝업 창을 열지 않고도 사용자 데이터에 대한 액세스를 얻을 수 있습니다.

가젯이 사전 승인된 요청 토큰을 사용하여 데이터에 대한 액세스를 얻으리라 생각하더라도 사용자가 팝업 창을 통해 액세스를 허용하도록 계속 지원해야 합니다. 사용자가 iGoogle 디렉토리의 가젯을 추가하면 사전 승인된 요청 토큰이 없습니다.

기타 예제

다음은 시작하는 데 도움이 될 만한 몇 가지 다른 샘플 OAuth 가젯입니다.

  • MySpace 가젯. 이 가젯은 MySpace를 서비스 제공업체로 사용하며 친구 업데이트 목록을 나열합니다.
  • YouTube 가젯. 이 가젯은 Google 데이터 YouTube API를 사용하여 현재 로그인한 사용자가 업로드한 동영상 링크를 표시합니다.
  • Blogger 가젯. 이 가젯은 Google 데이터 가젯 만들기 항목에 사용한 예제입니다.

고급 OAuth 기술

Google은 이 기술에 대한 여러 가지 향상 기능에 대해 연구하고 있습니다.  그러한 향상 기능 및 OAuth에 사용 가능한 기타 고급 기술에 대한 정보는 Google에서 유지 관리하는 고급 OAuth 기술 사이트를 참조하시기 바랍니다.

Posted by wrnly

최근의 인터넷 서비스는 그 자체가 SaaS(Software as a Service)의 형태입니다. 서비스 중에서 사용자가 일부 필요한 것만 사용할 수 있게 한다는 것입니다. Facebook이나 트위터가 세상에 널리 퍼지게된 이유 중에 하나가 외부 서비스에서도 Facebook가 트위터의 일부 기능을 사용할 수 있게 한 것입니다. 외부 서비스와 연동되는 Facebook이나 트위터의 기능을 이용하기 위해 사용자가 반드시 Facebook이나 트위터에 로그인해야 하는 것이 아니라, 별도의 인증 절차를 거치면 다른 서비스에서 Facebook과 트위터의 기능을 이용할 수 있게 되는 것입니다. 이런 방식은 Facebook이나 트위터 같은 서비스 제공자뿐만 아니라 사용자와 여러 인터넷 서비스 업체 모두에 이익이 되는 생태계를 구축하는데 기여하게 될 것입니다.

이 방식에서 사용하는 인증 절차가 OAuth입니다. 이 기사에서는 OAuth의 탄생 배경과 OAuth 1.0의 인증 과정에 대해 간략하게 설명합니다.

  • OAuth의 탄생과 사용

  • OAuth는 인증을 위한 오픈 스탠더드 프로토콜로, 사용자가 Facebook이나 트위터 같은 인터넷 서비스의 기능을 다른 애플리케이션(데스크톱, 웹, 모바일 등)에서도 사용할 수 있게 한 것이다.

    OAuth의 탄생 이전에도 다른 애플리케이션에 사용자의 아이디와 암호가 노출되지 않도록 하면서 API 접근 위임(API Access Delegation)이 가능한 여러 인증 방법이 있었다. Google과 Yahoo!, AOL, Amazon 등에서는 각각의 인증 방식을 제작하여 사용했다.

    OAuth 1.0이 나온 때는 2007년이며, 이후 보안 문제를 해결한 수정 버전인 OAuth 1.0 revision A 가 2008년에 나왔다.

    OAuth의 시작은 2006년에 트위터의 개발자와 소셜 북마크 서비스인 Gnolia의 개발자가 만나 인증 방식을 논의한 때부터였다. 두 회사의 개발자들은 그때까지 API 접근 위임에 대한 표준안이 없다는 것을 알았다. 그래서 2007년 4월 인터넷에 OAuth 논의체를 만든 뒤 OAuth드래프트 제안서를 만들어 공유했다. 그 뒤에 이 활동을 지지하는 사람이 생기게 되었고, 2008년 IETF 모임(73회, 미네소타에서 개최)에서 OAuth가 IETF 표준안으로 관리되야 하는 가에 대한 논의가 있었다. 그리고 2010년에 OAuth 1.0 프로토콜 표준안이 RFC5849로 발표되었다.

    2007년에 나온 OAuth 1.0은 비공식 논의체에 의해 최초로 만들어진 것이고, 2010년 IETF OAuth 워킹그룹에 의해 이 프로토콜이 IETF 표준 프로토콜로 발표된 것이다.

    현재 나와 있는 OAuth 2.0은 드래프트 단계에 있는 것으로, IETF OAuth 워킹그룹이 주축이 되어 만든 것이다. OAuth 2.0은 OAuth 1.0과 호환되지 않지만, 인증 절차가 간략하다는 장점이 있다. 그래서 아직 최종안이 나오지 않았음에도 여러 인터넷 서비스에서 OAuth 2.0을 사용하고 있다. 다음 표는 대표적인 인터넷 서비스 기업에서 사용하는 OAuth의 버전을 정리한 것이다.

    표 1 인터넷 서비스 기업이 사용하는 OAuth 버전

    인터넷 서비스 기업

    OAuth 버전

    Facebook

    2.0

    Foursquare

    2.0

    Google

    2.0

    Microsoft (Hotmail, Messenger, Xbox)

    2.0

    LinkedIn

    2.0

    Daum(티스토리

    2.0

    NHN (오픈API)

    1.0a

    Daum(요즘, 오픈API)

    1.0a

    MySpace

    1.0a

    Netflix

    1.0a

    트위터

    1.0a

    Vimeo

    1.0a

    Yahoo!

    1.0a

  • OAuth와 로그인

  • OAuth와 로그인은 반드시 분리해서 이해해야 한다. 일상 생활을 예로 들어 OAuth와 로그인의 차이를 설명해 보겠다.

    사원증을 이용해 출입할 수 있는 회사를 생각해 보자. 그런데 외부 손님이 그 회사에 방문할 일이 있다. 회사 사원이 건물에 출입하는 것이 로그인이라면 OAuth는 방문증을 수령한 후 회사에 출입하는 것에 비유할 수 있다.

    다음과 같은 절차를 생각해 보자.

  • 나방문씨(외부 손님)가 안내 데스크에서 업무적인 목적으로 김목적씨(회사 사원)를 만나러 왔다고 말한다.
  • 안내 데스크에서는 김목적씨에게 나방문씨가 방문했다고 연락한다.
  • 김목적씨가 안내 데스크로 찾아와 나방문씨의 신원을 확인해 준다.
  • 김목적씨는 업무 목적과 인적 사항을 안내 데스크에서 기록한다.
  • 안내 데스크에서 나방문 씨에게 방문증을 발급해 준다.
  • 김목적씨와 나방문씨는 정해진 장소로 이동해 업무를 진행한다.
  • 위 과정은 방문증 발급과 사용에 빗대어 OAuth 발급 과정과 권한을 이해할 수 있도록 한 것이다. 방문증이란 사전에 정해진 곳만 다닐 수 있도록 하는 것이니, '방문증'을 가진 사람이 출입할 수 있는 곳과 '사원증'을 가진 사람이 출입할 수 있는 곳은 다르다. 역시 직접 서비스에 로그인한 사용자와 OAuth를 이용해 권한을 인증받은 사용자는 할 수 있는 일이 다르다.

    OAuth에서 'Auth'는 'Authentication'(인증)뿐만 아니라 'Authorization'(허가) 또한 포함하고 있는 것이다. 그렇기 때문에 OAuth 인증을 진행할 때 해당 서비스 제공자는 '제 3자가 어떤 정보나 서비스에 사용자의 권한으로 접근하려 하는데 허용하겠느냐'라는 안내 메시지를 보여 주는 것이다. 다음의 화면 두 개는 각각 네이버와 미투데이에 접근 권한 요청이 있음을 알려 주는 화면이다. 미투데이의 경우에는 OAuth 인증 방식을 사용하지 않지만 인증 절차에 대한 예시 정도로 생각해 주기 바란다.

    o03.png

    그림 1 네이버 OAuth 접근 권한 요청 화면

    o01.png

    그림 2 미투데이 접근 권한 요청 화면

  • OpenID와 OAuth

  • OpenID도 인증을 위한 표준 프로토콜이고 HTTP를 사용한다는 점에서는 OAuth와 같다. 그러나 OpenID와 OAuth의 목적은 다르다.

    OpenID의 주요 목적은 인증(Authentication)이지만, OAuth의 주요 목적은 허가(Authorization)이다. 즉, OpenID를 사용한다는 것은 본질적으로 로그인하는 행동과 같다. OpenID는 OpenID Provider에서 사용자의 인증 과정을 처리한다. Open ID를 사용하는 여러 서비스(Relying Party)는 OpenID Provider에게 인증을 위임하는 것이다.

    물론 OAuth에서도 인증 과정이 있다. 가령 Facebook의 OAuth를 이용한다면 Facebook의 사용자인지 인증하는 절차를 Facebook(Service Provider) 처리한다. 하지만 OAuth의 근본 목적은 해당 사용자의 담벼락(wall)에 글을 쓸 수 있는 API를 호출할 수 있는 권한이나, 친구 목록을 가져오는 API를 호출할 수 있는 권한이 있는 사용자인지 확인하는 것이다.

    OAuth를 사용자 인증을 위한 방법으로 쓸 수 있지만, OpenID와 OAuth의 근본 목적은 다르다는 것을 알아야 한다.

  • OAuth Dance, OAuth 1.0 인증 과정

  • OAuth를 이용하여 사용자를 인증을 하는 과정을 OAuth Dance라고 한다. 두 명이 춤을 추듯 정확하게 정보를 주고받는 과정을 재미있게 명명한 것이다.

    OAuth를 이해하려면 몇 가지 용어를 먼저 알아 두어야 한다. 다음 표에 OAuth의 대표 용어를 정리해 보았다.

    표 2 OAuth 1.0 대표 용어

    용어

    설명

    User

    Service Provider에 계정을 가지고 있으면서, Consumer를 이용하려는 사용자

    Service Provider

    OAuth를 사용하는 Open API를 제공하는 서비스

    Consumer

    OAuth 인증을 사용해 Service Provider의 기능을 사용하려는 애플리케이션이나 웹 서비스

    Request Token

    Consumer가 Service Provider에게 접근 권한을 인증받기 위해 사용하는 값. 인증이 완료된 후에는 Access Token으로 교환한다.

    Access Token

    인증 후 Consumer가 Service Provider의 자원에 접근하기 위한 키를 포함한 값

    다음은 OAuth 인증 과정을 그림으로 표현한 것이다.

    o02.png

    그림 3 OAuth 1.0a 인증 과정(원본 출처: http://oauth.net/core/diagram.png)

    OAuth 인증 과정을 앞에서 설명한 회사 방문 과정과 연결하면 다음 표와 간다.

    표 3 회사 방문 과정과 OAuth 인증 과정

     

    회사 방문 과정

    OAuth 인증 과정

    1.

    나방문씨가 안내 데스크에서 업무적인 목적으로 김목적씨를 만나러 왔다고 말한다.

    Request Token의 요청과 발급

    2.

    안내 데스크에서는 김목적씨에게 나방문씨가 방문했다고 연락한다.

    사용자 인증 페이지 호출

    3.

    김목적씨가 안내 데스크로 찾아와 나방문씨의 신원을 확인해 준다.

    사용자 로그인 완료

    4.

    김목적씨는 업무 목적과 인적 사항을 안내 데스크에서 기록한다.

    사용자의 권한 요청 및 수락

    5.

    안내 데스크에서 나방문 씨에게 방문증을 발급해 준다.

    Access Token 발급

    6.

    김목적씨와 나방문씨는 정해진 장소로 이동해 업무를 진행한다.

    Access Token을 이용해 서비스 정보 요청

    위의 표에 따르면, Access Token은 방문증이라고 이해할 수 있다. 이 방문증으로 사전에 허락된 공간에 출입할 수 있다. 마찬가지로 Access Token을 가지고 있는 Consumer는 사전에 호출이 허락된 Service Provider의 오픈 API를 호출할 수 있는 것이다.

  • Request Token

  • OAuth에서 Consumer가 Request Token 발급을 요청하고 Service Provider가 Request Token을 발급하는 과정은 "저 나방문입니다. 김목적씨를 만날 수 있을까요?"라고 말하는 절차에 비유할 수 있다.

    Request Token을 요청하는 Request 전문을 살펴보자. 다음은 네이버의 OAuth API로 Request Token을 요청하는 예이다.

    1
    2
    3
    4
    GET /naver.oauth?mode=req_req_token&oauth_callback=http://example.com/OAuthRequestToken.do&oauth_consumer_key=WEhGuJZWUasHg&oauth_nonce=zSs4RFI7lakpADpSsv&oauth_signature=wz9+ZO5OLUnTors7HlyaKat1Mo0=&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1330442419&oauth_version=1.0 HTTP/1.1
    Accept-Encoding: gzip, deflate
    Connection: Keep-Alive
    Host: nid.naver.com

    보기 쉽도록 위의 내용을 아래와 같이 매개변수를 기준으로 정리했다.

    1
    2
    3
    4
    5
    6
    7
    8
    GET http://nid.naver.com/naver.oauth?mode=req_req_token&
    oauth_callback=http://example.com/OAuthRequestToken.do&
    oauth_consumer_key=WEhGuJZWUasHg&
    oauth_nonce=zSs4RFI7lakpADpSsv&
    oauth_signature=wz9+ZO5OLUnTors7HlyaKat1Mo0=&
    oauth_signature_method=HMAC-SHA1&
    oauth_timestamp=1330442419&
    oauth_version=1.0 HTTP/1.1

    Request Token 발급 요청 시 사용하는 매개변수는 다음 표와 같다.

    표 4 Request Token 발급 요청 시 사용하는 매개변수

    매개변수

    설명

    oauth_callback

    Service Provider가 인증을 완료한 후 리다이렉트할 Consumer의 웹 주소. 만약 Consumer가 웹 애플리케이션이 아니라 리다이렉트할 주소가 없다면 소문자로 'oob'(Out Of Band라는 뜻)를 값으로 사용한다.

    oauth_consumer_key

    Consumer를 구별하는 키 값. Service Provider는 이 키 값으로 Consumer를 구분한다.

    oauth_nonce

    Consumer에서 임시로 생성한 임의의 문자열. oauth_timestamp의 값이 같은 요청에서는 유일한 값이어야 한다. 이는 악의적인 목적으로 계속 요청을 보내는 것을 막기 위해서이다.

    oauth_signature

    OAuth 인증 정보를 암호화하고 인코딩하여 서명 값. OAuth 인증 정보는 매개변수 중에서 oauth_signature를 제외한 나머지 매개변수와 HTTP 요청 방식을 문자열로 조합한 값이다. 암화 방식은 oauth_signature_method에 정의된다.

    oauth_signature_method

    oauth_signature를 암호화하는 방법. HMAC-SHA1, HMAC-MD5 등을 사용할 수 있다.

    oauth_timestamp

    요청을 생성한 시점의 타임스탬프. 1970년1월 1일 00시 00분 00초 이후의 시간을 초로 환산한 초 단위의 누적 시간이다.

    oauth_version

    OAuth 사용 버전. 1.0a는 1.0이라고 명시하면 된다.

  • oauth_signature 만들기

  • OAuth 1.0에서는 oauth_signature를 생성하는 것이 가장 까다로운 단계이다. 당연히 Consumer와 Service Provider가 같은 암호화(signing) 알고리즘을 이용하여 oauth_signature를 만들어야 한다.

    oauth_sinature는 다음과 같이 네 단계를 거쳐 만든다.

  • 1. 요청 매개변수를 모두 모은다.

  • oauth_signature를 제외하고 'oauth_'로 시작하는 OAuth 관련 매개변수를 모은다. POST body에서 매개변수를 사용하고 있다면 이 매개변수도 모아야 한다.

  • 2. 매개변수를 정규화(Normalize)한다.

  • 모든 매개변수를 사전순으로 정렬하고 각각의 키(key)와 값(value)에 URL 인코딩(rfc3986)을 적용한다. URL 인코딩을 실시한 결과를 <key>=<value> 형태로 나열하고 각 쌍 사이에는 &을 넣는다. 이렇게 나온 결과 전체에 또 URL 인코딩을 적용한다.

  • 3. Signature Base String을 만든다.

  • HTTP method 명(GET 또는 POST), Consumer가 호출한 HTTP URL 주소(매개변수 제외), 정규화한 매개변수를 '&'를 사용해 결합한다. 즉 '[GET|POST] + & + [URL 문자열로 매개변수는 제외] + & + [정규화한 매개변수]' 형태가 된다. 이 예제에서는 'http://nid.naver.com/naver.oauth'을 URL로 사용하고, 이 URL에 URL 인코딩을 적용한 값을 사용했다.

  • 4. 키 생성

  • 3번 과정까지 거쳐 생성한 문자열을 암호화한다. 암호화할 때 Consumer Secret Key를 사용한다. Consumer Secret Key는 Consumer가 Service Provider에 사용 등록을 할 때 발급받은 값이다. HMAC-SHA1 등의 암호화 방법을 이용하여 최종적인 oauth_signature를 생성한다.

  • 사용자 인증 페이지의 호출

  • OAuth에서 사용자 인증 페이지를 호출하는 단계는 '안내데스크에서 김목적씨에게 방문한 손님이 있으니 안내 데스크로와서 확인을 요청하는 것'에 비유할 수 있다. Request Token을 요청하면, Service Provider는 Consumer에 Request Token으로 사용할 oauth_token과 oauth_token_secret을 전달한다. Access Token을 요청할 때는 Request Token의 요청에 대한 응답 값으로 받은 oauth_token_secret을 사용한다. Consumer가 웹 애플리케이션이라면 HTTP 세션이나 쿠키 또는 DBMS 등에 oauth_token_secret를 저장해 놓아야 한다.

    oauth_token을 이용해 Service Provider가 정해 놓은 사용자 인증 페이지를 User에게 보여 주도록 한다. 네이버의 경우 OAuth용 사용자 인증 페이지의 주소는 다음과 같다.

    1
    https://nid.naver.com/naver.oauth?mode=auth_req_token

    여기에 Request Token을 요청해서 반환받은 oauth_token을 매개 변수로 전달하면 된다. 예를 들면 다음과 같은 URL이 만들어 지게 되는 것이다. 이 URL은 사용자 인증 화면을 가리킨다.

    1
    https://nid.naver.com/naver.oauth?mode=auth_req_token&oauth_token=wpsCb0Mcpf9dDDC2

    로그인 화면을 호출하는 단계까지가 '안내 데스크에서 김목적씨에게 전화하는 단계'라 보면 되겠다. 이제 김목적씨가 안내 데스크로 와서 나방문씨를 확인해야 한다. 정말 나방문씨가 맞는지 아닌지 확인하는 과정이 필요할 것이다. 이 과정이 OAuth에서는 Service Provider에서 User를 인증하는 과정이라고 볼 수 있다.

    인증이 완료되면 앞에서 말한 바와 같이 어떤 권한을 요청하는 단계에 이르게 된다. "업무 약속이 있어 오셨으니 나방문씨가 출입할 수 있게 해 주세요"와 같은 것 말이다.

    인증을 마치면 Consumer가 oauth_callback에 지정한 URL로 리다이렉트한다. 이때 Service Provider는 새로운 oauth_token과 oauth_verifier를 Consumer에 전달한다. 이 값들은 Access Token을 요청할 때 사용한다.

  • Access Token 요청하기

  • OAuth에서의 AccessToken은 나방문 씨에게 지급할 방문증과 같다.

    Access Token을 요청하는 방법은 Request Token을 요청하는 방법과 거의 같다. 다만, 사용하는 매개변수의 종류가 약간 다르고 oauth_signature를 생성할 때 사용하는 키가 다르다. Access Token 을 요청할 때에는 매개변수 oauth_callback는 없고, oauth_token와 oauth_verifer가 있다.

    Request Token 발급을 요청할 때에는 Consumer Secret Key를 사용해 oauth_token_secret를 생성했다. Access Token 발급을 요청할 때에는 Consumer Secret Key에 oauth_token_secret을 결합한 값(Consumer Secret Key + & + oauth_token_secret)을 사용해 oauth_token_secret를 생성한다. 암호화 키를 변경하여 보안을 더 강화하는 것이다.

    Access Token 발급을 요청할 때 사용하는 매개변수는 다음 표와 같다.

    표 5 Access Token 발급 요청을 위한 OAuth 매개변수

    매개변수

    설명

    oauth_consumer_key

    Consumer를 구별하는 키 값. Service Provider는 이 키 값으로 Consumer를 구분한다.

    oauth_nonce

    Consumer에서 임시로 생성한 임의의 문자열. oauth_timestamp의 값이 같은 요청에서는 유일한 값이어야 한다. 이는 악의적인 목적으로 계속 요청을 보내는 것을 막기 위해서이다.

    oauth_signature

    OAuth 인증 정보를 암호화하고 인코딩하여 서명 값. OAuth 인증 정보는 매개변수 중에서 oauth_signature를 제외한 나머지 매개변수와 HTTP 요청 방식을 문자열로 조합한 값이다. 암화 방식은 oauth_signature_method에 정의된다.

    oauth_signature_method

    oauth_signature를 암호화하는 방법. HMAC-SHA1, HMAC-MD5 등을 사용할 수 있다.

    oauth_timestamp

    요청을 생성한 시점의 타임스탬프. 1970년1월 1일 00시 00분 00초 이후의 시간을 초로 환산한 초 단위의 누적 시간이다.

    oauth_version

    OAuth 사용 버전

    oauth_verifier

    Request Token 요청 시 oauth_callback으로 전달받은 oauth_verifier 값

    oauth_token

    Request Token 요청 시 oauth_callback으로 전달받은 oauth_token 값

    위의 표에 정의한 매개변수를 상황에 맞게 정의한 다음 Access Token을 요청하면 oauth_token과 oauth_token_secret을 전달받게 된다. Service Provider에 따라 사용자의 아이디나 프로필 정보 같은 것들이 반환되기도 한다.

  • Access Token 사용하기

  • 드디어 방문증이 발급됐다. 이제 출입문을 통과하는 일만 남았다. 방문증을 가지고 출입문을 통과한다는 것은 User의 권한으로 Service Provider의 기능을 사용하는 것과 비슷하다. 다시 말해, 권한이 필요한 오픈 API를 호출할 수 있게 되는 것이다.

    가령 네이버 카페에서 게시판 목록을 가져온다고 한다면 호출해야 하는 URL은 다음과 같다.

    1
    http://openapi.naver.com/cafe/getMenuList.xml

    특정 User의 권한을 가지고 카페 게시판 목록 반환 URL을 요청해야 해당 User가 가입한 카페의 게시판 목록을 반환받을 수 있을 것이다. 이 URL을 호출할 때는 OAuth 매개변수를 함께 전달해야 한다.

    다음은 Access Token을 사용해 오픈 API를 요청하는 예이다. HTTP 헤더에 Authorization 필드를 두었고, Authorization 필드의 값 부분에 OAuth 매개변수 적는다. Access Token을 사용할 때는 GET이나 POST가 아닌 HEAD 방식을 사용한다.

    1
    2
    3
    4
    5
    6
    POST /cafe/getMenuList.xml HTTP/1.1
    Authorization: OAuth oauth_consumer_key="dpf43f3p2l4k3l03",oauth_token="nSDFh734d00sl2jdk"
    ,oauth_signature_method="HMACSHA1",oauth_timestamp="1379123202",oauth_nonce="chapoH",oauth_signature="MdpQcU8iPSUjWoN%2FUDMsK2sui9I%3D"
    Accept-Encoding: gzip, deflate
    Connection: Keep-Alive
    Host: http://openapi.naver.com

    보기 쉽도록 Authorization 필드를 아래와 같이 매개변수를 기준으로 정리했다.

    1
    2
    3
    4
    5
    6
    Authorization: OAuth oauth_consumer_key="dpf43f3p2l4k3l03",
    oauth_token="nSDFh734d00sl2jdk",
    oauth_signature_method="HMACSHA1",
    oauth_timestamp="1379123202",
    oauth_nonce="csrrkjsd0OUhja",
    oauth_signature="MdpQcU8iPGGhytrSoN%2FUDMsK2sui9I%3D"

    Access Token을 사용해 오픈 API를 호출할 때 사용하는 매개변수는 다음 표와 같다.

    표 6 Access Token을 사용해 오픈 API를 호출 할 때 필요한 OAuth 매개변수

    매개변수

    설명

    oauth_consumer_key

    Consumer를 구별하는 키 값. Service Provider는 이 키 값으로 Consumer를 구분한다.

    oauth_nonce

    Consumer에서 임시로 생성한 임의의 문자열. oauth_timestamp의 값이 같은 요청에서는 유일한 값이어야 한다. 이는 악의적인 목적으로 계속 요청을 보내는 것을 막기 위해서이다.

    oauth_signature

    OAuth 인증 정보를 암호화하고 인코딩하여 서명 값. OAuth 인증 정보는 매개변수 중에서 oauth_signature를 제외한 나머지 매개변수와 HTTP 요청 방식을 문자열로 조합한 값이다. 암화 방식은 oauth_signature_method에 정의된다.

    oauth_signature_method

    oauth_signature를 암호화하는 방법. HMAC-SHA1, HMAC-MD5 등을 사용할 수 있다.

    oauth_timestamp

    요청을 생성한 시점의 타임스탬프. 1970년1월 1일 00시 00분 00초 이후의 시간을 초로 환산한 초 단위의 누적 시간이다.

    oauth_version

    OAuth 버전

    oauth_token

    oauth_callback으로 전달받은 oauth_token

     

    주의

    Access Token을 이용해 요청할 때, Service Provider에 따라 realm이라는 매개변수를 사용해야 하는 경우도 있다. realm은 optional 매개변수인데, WWW-Authenticate HTTP 헤더 필드에서 사용하는 값이다.

  • OAuth 2.0

  • OAuth 1.0은 웹 애플리케이션이 아닌 애플리케이션에서는 사용하기 곤란하다는 단점이 있다. 또한 절차가 복잡하여 OAuth 구현 라이브러리를 제작하기 어렵고, 이런저런 복잡한 절차 때문에 Service Provider에게도 연산 부담이 발생한다.

    OAuth 2.0은 이러한 단점을 개선한 것이다. OAuth 1.0과 호환성이 없고, 아직 최종안이 발표된 것은 아니지만 여러 인터넷 서비스 기업에서 OAuth 2.0을 사용하고 있다.

    OAuth 2.0의 특징은 다음과 같다.

    • 웹 애플리케이션이 아닌 애플리케이션 지원 강화
    • 암호화가 필요 없음
      HTTPS를 사용하고 HMAC을 사용하지 않는다.
    • Siganature 단순화
      정렬과 URL 인코딩이 필요 없다.
    • Access Token 갱신
      OAuth 1.0에서 Access Token을 받으면 Access Token을 계속 사용할 수 있었다. 트위터의 경우에는 Access Token을 만료시키지 않는다. OAuth 2.0에서는 보안 강화를 위해 Access Token의 Life-time을 지정할 수 있도록 했다.

    이외에도 OAuth 2.0에서 사용하는 용어 체계는 OAuth 1.0과 완전히 다르다. 같은 목적의 다른 프로토콜이라고 이해는 것이 좋다. 하지만 아직 최종안이 나오지 않았기 때문에, 현재로서는 OAuth 2.0의 특징만 파악하는 것으로도 충분할 듯 하다.

  • OAuth로 인한 인터넷 서비스의 변화

  • OAuth는 요즘의 인터넷 생태계의 주요 요소로 자리매김하고 있다.

    신생 업체들은 고유의 인증 방식을 사용하기 보다는 Facebook이나 트위터의 인증을 이용하고 있다. 개발 비용과 운영 비용을 줄이는 효과도 있지만 Facebook이나 트위터를 통해 서비스를 홍보하는 효과를 만들 수도 있다. 그리고 Service Provider 입장에서는 핵심 기능을 더욱 공고히 하는 효과를 얻고 있다.

    표준 인증 방법 하나가 인터넷 업계에 변화를 주고 있는 것이다.

    Posted by wrnly

    현재 jsp로 만들어져잇는 홈페이지에

     

    그 홈페이지 내의 내용을 검색하는 웹위젯을 제작하려고 합니다.


    ----------------------------------------------


    웹서비스를 말씀하시는 것 인가요. 아니면

    단순히 네이버의 검색창을 자신의 사이트에 다는 것과 같은 것을말씀하시는 것인지요?

     

    웹서비스는 방식에 따라  

    CORBA, RMI, WSDL ,혹은 소켓 연결(보안문제가 있음)

    혹은 URL 클래스나 UrlConnect 을 통한 연결 , RESTfull 방식등 여러가지가 있는데요.

     

    네이버의 검색api를 이용하는 웹서비스가 아니라,

    네이버의 검색창을 내 사이트 다는 것과 같은 것을 말씀하시는 것이라면 바로 말위에 씀드린 것과는 아무

    상관없습니다.간단합니다.

     

    웹서비스는 설명도 힘들고 질문요지로 보아 검색창 다는 것을 물어보신 듯 한데요.

    그부분을 설명드릴게요.웹서비스는 여기서는 설명이 어렵습니다.

     

    <서버 측>

    1.텍스트 박스 검색버튼 , 각종 이미지로 구성된 검색페이지를 우선 만듭니다.즉 웹위젯이 되겠지요

    2.1번에서 만든  페이지,즉 웹위젯  자체를 클라이언트가 내려받을 수 있어야 하는데,

    1번 페이지 자체를 document.write 함수를 이용해서  해당 페이지에  HTML 자체가  그대로 출력하게 끔 자바스크립트로 작성해주어야 합니다 .그리고 이 자바스크립트는 웹위젯출력 부분 말고 검색페이지로 연결할 액션정보나 기타 유효성 검사도 포함하겠지요.

     

    이렇게 만들어진 스크립트를  다운받기 위해서 ,

     

    클라이언트에서는

    적당한 위치에 <script src ="위 자바스크립트를 다운받을 수 있는 url" /> 형태의  스크립트를 넣어줍니다. 그러면 서버에서 작성한 위 스크립트 자체를 다운받게 되고, 그 다운받은 스크립트가 실행되면서 위젯이 삽입되게 될 것입니다.

     

    설명하기가 좀 힘든데요.

    요지는 자바스크립트의 document.write 를 통해서 HTML 태그 자체를 현재 페이지에 출력하게 되면 결국 서버의 위젯이 현재 페이지에 출력되는 원리입니다.

     

    만약 이게 아니라, 웹서비스를 말씀하시는 것이라면 , 구체적으로 다시 질문을 해주시면

    답변을 드리도록 하겠습니다.






    Posted by wrnly