[원본] A Primer for OpenID with PHP | dev.aol.com

 

by Jack Herrington
September 21 2007

 

OpenID는 상당히 멋진 기술이지만 여러분에게는 생소할것입니다. OpenID는 웹을 사용하는 사람들에게 그들의 정보를 한곳에 등록하고 OpenID를 지원하는 어느 사이트에서도 사용가능하게 해주는 오픈소스 프로토콜입니다. OpenID를 사용하게 된다면 방문하려는 사이트마다 아이디와 비밀번호등을 만들고 일일이 기억해야 하는 불편이 사라지게 됩니다. 또한 웹 사이트는 복잡한 사용자 관리 프로세스를 구축 할 필요없이 인증된 사용자를 구분할 수 있게 됩니다. OpenID를 지원하는 서비스들은 계속해서 증가하고 있지만 OpenID가 얼마나 유용하고 멋진 기술인가에 비해서는 더딘 편이라 하겠습니다. 이 글이 OpenID가 널리 보급되는데 도움이 되었으면 합니다.

OpenID의 근간을 이루는 개념은 매우 단순합니다. 웹사용자가 OpenID를 제공하는 사이트에 ID를 등록하면 OpenID를 지원하는 다른 모든 웹사이트들에서 사용할 수 있게 하겠다는 것입니다.

우선 사용자는 OpenID를 제공하는 사이트에 계정을 생성합니다. 이런 사이트에는 Verisign이나 AOL이 있습니다. AOL과 AOL의 메신저(AIM)을 사용하시는분들은 해당 계정을 이미 OpenID로 사용가능 합니다. 자신의 OpenID를 갖게 되었다면 OpenID를 지원하는 다른 웹사이트에 로그인 할 수 있습니다.(역자주, 비단 웹사이트 뿐만아니라 웹상에서 구동되는 작은 어플리케이션에서도 사용가능합니다. OpenID를 제공하는 사이트를 "OpenID provider"라고 하고 OpenID로 로그인할 수 있게끔 지원하는 사이트를 "OpenID consumer web-site", "OpenID consumer web-application"이라고 한다네요. 중요한것은 provider - consumer개념인 듯 합니다.) 즉, 웹 어플리케이션(consumer)은 사용자의 OpenID를 입력받아 OpenID를 제공한 사이트(provider)에게 인증을 요청하게 됩니다.) OpenID를 지원하는 웹 어플리케이션(사이트)를 모아놓은 디렉토리 사이트도 있습니다.

이 글에 나와있는 코드를 보면 알 수 있겠지만 OpenID를 지원하는 일은 아주 쉽습니다. 여러분은 이미 나와있는 라이브러리(추가비용없이 대부분의 언어에 사용가능한 라이브러리가 있습니다.)를 사용하거나 직접 작성할 수도 있습니다. 물론 여러분이 직접 작성하는것이 OpenID 프로토콜을 이해하는데 많은 도움이 되겠지만 연습삼아 해보기로 하고 실질적으로는 배포되는 라이브러리를 사용하는 것이 쉬울겁니다.

OpenID는 이를 지원하는 사이트나 이를 사용하는 사람들 모두에게 큰 이점을 가져다 줍니다. 사용자는 하나의 OpenID를 가지고 많은 서비스를 이용할 수 있습니다. 특히나 여러군데의 사이트를 이용하는 분들은 특정 사이트의 ID와 비밀번호를 잊어버리는 경우가 종종 있기 때문입니다. 사용자들이 OpenID를 사용하기 때문에 OpenID를 지원하는 사이트는 사용자계정을 따로 관리할 필요가 없게되며 OpenID를 사용하는 많은 사용자들을 잠재적인 고객으로 확보 할 수 있습니다.

OpenID를 지원하기 위해서 OpenID를 제공해야하지는 않습니다. 특별한 소프트웨어나 서비스를 필요로 하지도 않습니다. 단지 HTTP 요청을 할수 있는 프로그래밍 언어만 필요할 뿐입니다. (대부분의 웹프로그래밍 언어는 이것이 가능합니다.)

Getting an OpenID (OpenID계정을 만들어 봅시다)

OpenID를 지원하게 끔하기 위해서 우선 OpenID를 얻어야 할 것입니다. 다행히도 공짜로 OpenID를 제공하는 곳이 많이 있습니다. 이 글에서 사용할 OpenID는 pip.verisignlabs.com에서 얻었습니다. signon.com이나 다른 OpenID를 제공하는 사이트에서 얻더라도 무방합니다. OpenID는 실질적으로 URL입니다. 다음의 URL이 이 글에서 사용할 OpenID입니다.

  1. http://jherr.pip.verisignlabs.com

이 URL은 실제로도 동작합니다. 여타 다른 URL처럼 HTML페이지가 들어있습니다. 이 HTML안에는 OpenID를 제공한 사이트에 대한 링크가 들어있으며 그 링크를 따라가게되면 사용자정보를 확인할 수 있습니다.

UNIX를 사용중이라면 cURL을 이용하여 OpenID URL의 HTML을 볼 수 있을것이고 브라우저를 통해서 소스보기로 HTML을 확인 할 수 있을 것입니다. 아래는 cURL을 이용하여 출력한 결과입니다.

  1. % curl "http://jherr.pip.verisignlabs.com"
    <html>
    <head>
    <link rel="openid.server" href="http://pip.verisignlabs.com/server" />
    <meta http-equiv="X-XRDS-Location"
    content="http://pip.verisignlabs.com/user/jherr/yadisxrds" />
    <title>Identity Endpoint For jherr</title>
    </head>  <body>
    <p>This is an identity endpoint for jherr</p>
    <p>For more information, please visit
    <a href="http://pip.verisignlabs.com">http://pip.verisignlabs.com</a>
    </p></body></html>
    %

중요한 부분은 rel속성에 openid.server값을 가지고있는 <link>태그입니다. 이것은 OpenID를 지원하는 사이트로 하여금 OpenID의 인증을 수행할 수 있는 (OpenID를 제공한 사이트의)주소를 알 수 있게 합니다.

여기에서 살펴봐야할 두가지 중요한 점은

  1. rel속성에 openid.server값을 가지는 <link>태그를 포함하는 어떤 페이지라도 OpenID URL로 사용할 수 있다는것입니다. 따라서 당신의 블로그의 첫페이지를 OpenID로도 사용할 수 있습니다.
  2. OpenID는 온라인상에서 사용자정보를 관리하기 위한 프레임워크이며 특정 회사가 제공하는 단하나의 서비스가 아닙니다. 많은 회사나 조직에서 OpenID를 제공할 수 있으며 이미 공짜로 인증과정을 처리하고 제공하는 곳도 많습니다.

(역 자주, 만약 당신이 일반 사용자이고 당신의 블로그 주소를 OpenID로 사용하고 싶다면 당신의 블로그에 위와 같은 <link>태그를 집어넣으면 됩니다. 예를들어 http://blog.naver.com/username 에 위와같은 <link>태그를 넣어두면 당신의 블로그 주소는 그대로 OpenID가 됩니다. 물론 href에 들어갈 'OpenID를 제공한 사이트'의 주소는 다를것입니다.)

이제까지 OpenID를 사용하는 일반사용자의 입장에서 살펴본 핵심개념들입니다. 이제 좀더 자세히 이해하기 위해서 OpenID를 지원하는 사이트는 어떻게 구축하는지, OpenID를 제공하는 사이트는 어떻게 만드는지 살펴보겠습니다.

Building a Consumer (OpenID를 지원하는 사이트를 구성하려면)

다음은 PHP로 구축된, OpenID를 지원하는 사이트의 흐름도 입니다.

왼쪽에서 오른쪽으로 가는 화살표는 사용자가 경험하게 되는 페이지들의 흐름입니다. 아래쪽의 구름모양은 사용자 모르게 처리하는 것들입니다.

왼쪽 끝에 있는 Index.php는 사용자가 처음 접하는 로그인페이지입니다. 여기에는 OpenID를 입력할 수 있는 텍스트 필드가 있고 사용자가 Submit을 클릭하면 Forword.php로 이동하게 됩니다. Forward.php와 Complete.php는 점선으로 그려져있는데 사용자에게 실질적으로는 보이지 않는다는 의미입니다. (역자주, redirect시키는 페이지 이므로 브라우저에 표시할 내용이 없습니다.)

Forward.php는 사용자가 입력한 OpenID URL로 cURL을 이용하여 openid.server의 URL을 찾아냅니다. 결국 OpenID를 제공한 사이트의 URL에 OpenID와 추가적인 파라미터를 함께 보내줍니다.

사용자는 OpenID를 제공한 사이트로 이동하게 되고 비밀번호나 혈액샘플, 망막스캔등 어떠한 방식으로든 로그인하게 됩니다. 다음으로 OpenID를 제공한 사이트는 사용자가 방문한 원래의 사이트--여기서는 Complete.php의 URL이 해당됩니다--로 OpenID를 되돌려 줍니다. 이때 몇몇 추가적인 파라미터도 함께 보내줍니다.

Complete.php는 되돌아온 OpenID가 정확하게 인증된것인지 또는 다른 스푸핑 사이트에서 온것이 아닌지 OpenID를 제공한 사이트에 cURL을 이용하여 확인작업을 합니다. 확인이 완료되면 이제 사용자는 방문한 사이트에 "로그인" 되었으며 사이트가 제공하는 서비스를 "로그인"된 사용자로서 이용할 수 있게 됩니다.

Complete.php에서는 OpenID를 제공한 사이트로 부터의 응답을 재차 확인하지 않아도 됩니다. 처음에 사용자를 OpenID를 제공한 사이트로 포워딩 시킬 때 비밀키를 함께 보내고 되돌아온 응답에대한 서명을 체크할 수 있습니다. 그러나 이 글에서는 이해하기 쉽도록 이부분에 대한 언급은 하지 않겠습니다.

복잡하고 어렵게 보이겠지만 사실은 그렇지 않습니다. OpenID를 이용한 로그인 과정을 브라우저를 통해서 살펴보겠습니다.

아주 간단합니다. OpenID를 입력할 수 있는 텍스트 필드와 Submit버튼 뿐입니다. PHP가 아니더라도 상관 없습니다.

Submit버튼을 클릭하면 Forward.php로 이동하게 됩니다.

사용자는 일반적으로 이 페이지를 볼 수 없습니다. PHP에서 바로 OpenID를 제공한 사이트로 포워딩 시켜버리면 되기 때문입니다. 그러나 이 글에서는 어느 URL로 보내지는지 직접 확인해 보기위해서 출력했을 뿐입니다.

OpenID를 제공한 사이트로 이동하는 URL의 파라미터를 살펴봅시다. openid.identity는 사용자가 입력한 OpenID입니다. openid.mode=checkid_setup은 요청한 OpenID가 맞는지 확인하고 로그인을 시도할 것을 의미합니다. openid.return_to는 성공적으로 로그인이 되었을때 되돌아올 URL입니다.

사용자가 OpenID를 제공한 사이트로 성공적으로 포워딩 되었다고 가정했을때 그 다음은 OpenID를 제공한 사이트에 있는 페이지입니다.

여기서는 로그인한 세션을 얼마나 지속시킬것인지 등을 설정 할 수 있습니다. (역자주, 비밀번호를 입력한다던가 하는 부분이 화면상에서는 보이지 않는듯 합니다.) 이 예제에서는 그다지 중요하지 않습니다. OK를 클릭하게 되면 사용자는 원래 방문한 사이트의 Complete.php로 보내집니다.

성공적으로 로그인 되었음을 보여주는 이 페이지는 언뜻보기엔 상당히 간단해 보입니다. 그러나 실제로는 스푸핑 되지 않았음을 확인하기 위해서 OpenID를 제공한 사이트에 "인증"모드로 마지막으로 한번더 다녀왔습니다.

이제 좀더 상세하게 페이지들의 흐름을 실제로 동작하는 PHP코드를 통해서 사용자에게 어떻게 보여지는지 살펴보겠습니다.

The Consumer Code (OpenID를 지원하는 사이트에서의 코드)

처음은 로그인 페이지부터 시작합니다.

  1. Listing 1. Index.php
    <html><head><title>OpenID Login</title></head><body>
    <form action="forward.php" method="post">
    OpenID: <input type="text" name="url" /><br/>
    <input type="submit" />
    </form>
    </body></html>

Index.php는 표준 HTML페이지로 하나의 텍스트 필드와 Submit버튼을 가지며 Forward.php로 데이타를 보내주는 폼으로 이루어져 있습니다. 다음은 Forward.php입니다.

  1. Listing 2. Forward.php
  2. <?php
    ob_start();
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $_REQUEST['url'] );
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_exec($ch);
    curl_close($ch);
    $idhtml = ob_get_clean();
  3. preg_match( "<link rel=\"openid.server\" href=\"(.*?)\" />", $idhtml, $found );
    $url = $found[1];
  4. $return_to = "http://myhost.com/oidumb/complete.php";
  5. $url .= "?openid.mode=checkid_setup";
    $url .= "&openid.identity=".urlencode( $_REQUEST['url'] );
    $url .= "&openid.return_to=".urlencode( $return_to );
    ?>
    <html>
    <body>
    <a href="<?php echo($url);?>"><?php echo($url);?></a>
    </body>
    </html> 

이번엔 조금 복잡해 보입니다. 사용자가 입력한 OpenID URL에 해당하는 HTML을 가져오기 위해서 PHP에 내장되어있는 cURL라이브러리를 사용했습니다. 가져온 HTML로부터 정규식을 이용하여 openid.server에 해당하는 값을 추출해 냅니다.

OpenID를 제공한 사이트의 URL으로 checkid_setup하기위해서 추가적인 파라미터를 포함하여 사용자를 포워딩 시킵니다. 여기서는 URL을 직접확인하기 위해서 링크로 보여주었지만 실제로는 Response Header의 Location값으로 $url을 보냅니다.

마지막으로 OpenID를 제공한 사이트에서 사용자가 성공적으로 로그인 되었을 때 추가적인 파라미터와 함께 되돌아 오게 되는 Complete.php입니다.

  1. Listing 3. Complete.php
    <?php
    ob_start();
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $_GET['openid_identity'] );
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_exec($ch);
    curl_close($ch);
    $idhtml = ob_get_clean();
  2. preg_match( "<link rel=\"openid.server\" href=\"(.*?)\" />", $idhtml, $found );
    $url = $found[1];
  3. $url .= "?openid.mode=check_authentication";
    $url .= "&openid.assoc_handle=".urlencode( $_GET['openid_assoc_handle'] );
    $url .= "&openid.sig=".urlencode( $_GET['openid_sig'] );
    $url .= "&openid.signed=".urlencode( $_GET['openid_signed'] );
    $url .= "&openid.response_nonce=".urlencode( $_GET['openid_response_nonce'] );
    $url .= "&openid.identity=".urlencode( $_GET['openid_identity'] );
    $url .= "&openid.return_to=".urlencode( $_GET['openid_return_to'] );
    $url .= "&openid.invalidate_handle=123456";
  4. ob_start();
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url );
  5. curl_exec($ch);
    curl_close($ch);
    $ca_resp = ob_get_clean();
  6. $authentic = false;
    if ( preg_match( '/is_valid:true/', $ca_resp ) )
      $authentic = true;
    ?>
    <html><body>
    <?php if( $authentic ) { ?>
    OpenID: <?php echo( $_GET['openid_identity'] ) ?><br/>
    Yay! You are signed in!
    <?php } else { ?>
    Your OpenID could not be verified.
    <?php } ?>
    </body>
    </html> 

소스코드의 위쪽부분은 Forward.php와 유사합니다. 사용자의 OpenID로부터 OpenID를 제공한 사이트의 URL을 알아낸 다음 openid.mode=authenticate를 포함하여 OpenID 규약에 명시된 다른 파라미터와 함께 URL을 생성합니다.

생성한 URL은 cURL을 이용하여 OpenID를 제공한 사이트로부터 인증 결과를 가져오는데 사용됩니다. 결과는 $ca_resp에 저장됩니다. 결과에 is_valid:true가 있다면 우리는 이 Complete.php가 OpenID를 제공한 사이트로부터 불려졌음을 확인한 것이며 이 OpenID가 인증되었음을 알 수 있습니다.

이제 우리가 만든 OpenID를 지원하는 예제 사이트는 이 OpenID를 세션변수에 저장해 두고 사용할 수 있습니다.

이것으로 우리는 OpenID 식의 "hello word" 예제를 살펴보았습니다. 이 예제를 실제로 사용하는데에는 무리가 있을 것입니다. 정규식을 너무 제한적으로 만들었고 에러체크 등을 하지 않았습니다. 그러나 중요한 것은 간단하게나마 OpenID가 작동하는 방식을 살펴보고 어떤것이 OpenID를 지원하는 사이트에서 하는일이고 OpenID를 제공하는 사이트에서 하는일인지 알게되는 것입니다. OpenID의 정의에 대해 대충으로라도 알게 되었을 것입니다.

현업에서는 OpenID를 제공하거나 지원하기 위해서는 여러분 스스로가 선택한 언어로 작성된 OpenID라이브러리를 사용하게 될것입니다. 이 글의 나머지부분에서는 이에대해 이야기 할까 합니다.

다음으로 넘어가기 전에 몇가지 요약해 봅시다.

  1. OpenID는 서비스가 아니라 OpenID를 지원하는 사이트가 OpenID를 제공하는 사이트에게 OpenID가 유효한가를 확인하는 프로토콜입니다.
  2. 개인적으로 OpenID를 사용하기위해 직접 OpenID를 제공하는 사이트를 만들 수 있으며 이미 OpenID를 제공하는 사이트는 많습니다.
  3. 사용자계정을 직접적으로 관리하지않고 단지 사용자를 확인하기 위해서라면 OpenID는 정말 좋은 선택이 될 수 있습니다.
  4. 사용자를 확인하기 위해서 OpenID를 지원하는 사이트에서 OpenID를 제공한 사이트로, 다시 OpenID를 지원하는 사이트로 이동합니다. (역자주, 페이지의 흐름이 그렇다는 말 같습니다.)
  5. HTTP request를 할 수 있는 어떤 프로그래밍언어로든 OpenID를 지원하는 사이트를 만들 수 있습니다.

이제 PHP로 구현된 라이브러리를 살펴봅시다.

Installing the OpenID Consumer Library (OpenID를 지원하는 사이트를 위한 라이브러리 설치하기)

PHP로 된 몇가지 OpenID 라이브러리가 있습니다만 여기서는 JanRain에서 나온 라이브러리를 살펴보겠습니다. OpenID Enabled site에 링크되어있습니다. 최신버전을 다운로드 하여 Apache서버의 Document디렉토리에 복사합니다. (역자주, 글쓴이가 사용한 라이브러리의 정확한 버전을 알 수 없었습니다. 최신버전과는 경로나 파일명이 다를 수 있습니다.)

다음으로 README파일에 나와있는데로 Examples/detect.php를 실행시킵니다. 저의 Mac OS X에는 PHP5가 설치되어있습니다. cURL라이브러리를 사용하는데 필요한 GMP, BCMath나 PEAR DB함께 설치되어야 할 수 있습니다. 또한 XML을 처리할 수 있는 XML_DOM라이브러리도 필요합니다. README파일에 모두 명시되어있고 detect.php를 실행시켜보면 알 수 있습니다.

README파일에는 이 OpenID라이브러리를 PEAR모듈의 형태로 설치하는것에 대해 언급하고 있지만 굳이 그렇게 하지 않아도 됩니다. 제일먼저 해야할 것은 examples/consumer/index.php를 열어보는 것입니다.

OpenID를 입력하면 OpenID를 제공한 사이트로 이동하게되고 로그인을 합니다. 그후엔 다시 예제로 돌아오게됩니다.

OpenID로 로그인되었을 뿐만아니라 e-mail주소와 성명, 닉네임등도 받아왔습니다. 잘 되는군요!

소스코드를 조금만 살펴본다면 이 라이브러리를 이용하여 OpenID를 지원하는 사이트를 만들 수 있을 것입니다. 사실 이 라이브러리가 위에서 우리가 작성한 코드와 비교해서 별 차이가 없어 보이지만 좀더 안정적이고 많은 에러상황에 대처할수 있는 코드들이 포함된 훌륭한 라이브러리 입니다.

이제 마지막으로 OpenID PHP라이브러리를 이용하여 OpenID를 제공하는 사이트에 대해 살펴봅시다.

An OpenID Provider (OpenID를 제공하는 사이트)

OpenID를 제공하는 사이트를 구축하기 위해서 제일 처음 해야하는 설정화면입니다. 사용자 정보를 저장하기 위해서 파일시스템을 사용하거나 SQL서버를 사용할 수 있습니다. Setup.php가 설정페이지입니다.

설정을 끝냈다면 Config.php에 사용할 수 있는 소스코드가 출력됩니다.

After that you take the contents of this page and copy them into Config.php in the examples/server directory. From there you go to Server.php, which gives you some of the basic details of the provider. Most importantly, what to use as the <link> in your own pages to have this provider support your OpenIDs.

출력된 소스코드를 복사하여 examples/server/Config.php에 붙여넣기 합니다.

From here I can build my own OpenID with this provider by adding /userpage/user=<username> to the end of the provider URL. This returns an identity page.

That’s the same kind of identity page that other services, like the Verisign one that I used at the start of this article, return for OpenID services. This page is shown as HTML in Listing 4.

  1. Listing 4. The user page returned from the provider
    <html>
    <head>
      <link rel="openid2.provider openid.server" href="http://localhost/openid/examples/server/server.php/userXrds?user=jherr"/>
      <meta http-equiv="X-XRDS-Location" content="http://localhost/openid/examples/server/server.php" />
    </head>
    <body>
      This is the identity page for users of this server.
    </body>
    </html> 

Because I’ve installed this on localhost the OpenID provider that I installed isn’t going to do much good on the Web. From here I need to install this on my Web site, get it hooked into my database, and use it from there.

The consumer and provider examples provided here serve only as templates on which you can base your own work. You could, for example, use the OpenID consumer example to add the ability to log in using an OpenID URL as an account to your online services. Or you could use the provider example to provide OpenIDs to all of the users on your service for free.

Where to Go Next

비록 이 글에서 OpenID가 무엇이고 어떠한 것들을 할 수 있는지 이야기 했지만 모든 형태의 웹사이트에 적용하는것은 추천하지 않습니다. 특별한 규칙 없이는 은행권과 같은 사용자정보와 인증에 민감한 사이트에는 적합하지 않습니다. 따라서 전자상거래나 금융권 사이트에는 적용하지 않는것이 좋을 것입니다. 그러나 웹 상에는 그렇지 않은 사이트가 훨씬 더 많습니다.

OpenID directory에는 OpenID를 적용한 블로그나 토론게시판, 사람들끼리 어울리기위한 사이트, 위키나 심지어 지역모임을 위한 것들까지 수많은 사이트들이 목록화 되어 있습니다. 웹은 본질적으로 많은 사용자를 기반으로 하고있습니다. 각각의 사용자를 구분하고 각 사용자의 연속성을 보장해주어야 합니다. 특정 형태의 사이트에서는 이러한 사용자 인증이 강력하게 필요한 경우가 있지만 대부분은 그렇지 않습니다.FaceBookWells Fargo을 비교해본다면 아실 수 있을겁니다. (역자주, me2DAY국민은행을 비교해본다면?)

OpenID에 대해 좀더 알고싶으신분은 OpenID.net을 방문해 보세요. OpenID에 대한 소개와 OpenID 규약, OpenID를 지원하는 사이트 및 OpenID를 제공하는 사이트를 만들기 위한 여러 프로그래밍언어로 작성된 라이브러리 목록을 제공합니다. 또한 OpenID 프로토콜이 어떻게 작동하는지 사용자 인증을 위해서 HTTP request를 어떻게 사용하면 되는지 단계별로 설명하고 있는 OpenID book을 온라인으로 볼 수 있습니다.

OpenID는 여러 회사나 웹사이트, 조직들 에게 많은 가능성을 가져다 줄 수 있는 사용자 인증 프레임워크 입니다. 좋은 예로 AOL은 OpenID를 지원하기 위해서 Open Authentication API (OpenAuth)서비스를 구축하였습니다. OpenID를 지원하는 가장 손쉬운 방법중에 하나는 AOL이 제공하는 OpenAuth를 사용하는 것입니다. 그러면 AIM과 AOL사용자들을 함께 흡수 할 수 있을 것입니다. 마지막으로 하고싶은 말은 OpenID의 전망은 아주 밝다는 것입니다. OpenID는 웹 서비스를 보다 쉽게 할것이고 이는 사이트와 사용자 모두에게 이득이 될것입니다.

 

[원본] A Recipe for OpenID-Enabling Your Site - 본 번역판은 커뮤니티내 공유용도로 재배포를 허용할 권한은 없습니다. :)

 

내사이트 오픈아이디 요리법

Prepared by Joseph Smarr at Plaxo on July 18, 2007.

이것은 기존에 이미 회원기반을 보유하고 있는 웹사이트에 오픈아이디 (OpenID) 인증을 적용하기 위한 단계별 튜토리얼 가이드 이다. 이것은 새로운 사용자들이 그들이 이미 보유하고 있는 오픈아이디를 가지고 당신 사이트에 가입하여 계정을 만들도록 하는 방법을 설명할 것이다. (역주: 향후 1~2 년 내에 많은 국내 포탈들이 일괄로 오픈아이디를 보급하게 될 것이며, 이 경우, 포탈 사용자들이 쉽게 당신 사이트의 회원이 될 수 있습니다.)  또한, 사이트의 기존 회원들이 그들의 오픈아이디(들)을 그들 계정에 연결시키고 그 오픈아이디로 로그인 할 수 있는 쉬운 방법도 설명할 것이다. 나는 이 가이드를 Internet Identity Workshop 등에서 동료 오픈아이디 개발자들에게 말하면서 만들게 되었으며, 이것으로  Plaxo 의 OpenID 지원 을 구현했다. 나는 또한 참고를 위해서 Plaxo 의 구현에 대한  상세한 스크린샷 을 포스팅 했다. 나는 이 가이드를 Best-practices 로서 따라하기에 명확하고 완결되도록 의도했지만, 의문점이나 어떤 피드백이 있다면   로 메일을 보내거나 Plaxo's blog 에 코멘트를 남겨주길 바란다. 이 가이드는 다소 길어보이지만, 바라건데 별 생각없이 끝까지 따라가는 것 만으로도 구현이 될 것이다! :)

개략

나는 당신의 웹사이트에 대해 다음과 같은 것이 있음을 가정한다:

  • 각 회원별 레코드들을 가진 회원 데이타베이스

    • 각 회원은 유일한 내부 회원 식별키를 가지고 있다
    • 회원들은 사용자명(또는 이메일주소)과 비밀번호를 이용해서 로그인 한다.
  • 새로운 사용자들을 위한 가입 등록 절차와 기본적인 프로필 정보 수집 절차.
  • 사용자 인증을 위한 로그인 페이지

    • 내부적으로 당신은 사용자명(또는 이메일주소)과 비밀번호로 인증을 한후, 회원 식별키를 찾아 사이트 내에서 사용한다.

     

  • 사용자들이 계정을 관리할 수 있는 설정 페이지

만약 당신의 사이트가 이와 같지 않더라도, 여전히 아래 사항들을 따라갈 수 있다. 그러나 몇몇 섹션은 당신에게 해당사항이 아닐 수도 있다.

당신의 사이트에 추가하게될 대략적인 사항들은 다음과 같다:

  1. OpenID 를 당신사이트의 내부 사용자 식별키로 매핑하기 위한 데이타베이스 새 테이블 하나

    • 그것은 다-대-일 관계이다. (각 사용자 계정에는 여러개의 OpenID 들을 가질수 있습니다만, 하나의 OpenID 에 대해서는 오직 한 사용자에 의해서만 제시될 수 있습니다.)
    • 이 테이블은 OpenID 로 사용자들을 찾기위한 전역 레지스트리가 될것입니다, 따라서 일반적으로 당신은 모든 당신의 사용자를 담는 하나의 공유 테이블로 만들어야 합니다.
  2. 신규 사용자를 위한 가입 페이지 에 약간의 OpenID 관련 사용자 인터페이스

    • 신규 사용자들은 그들의 오픈아이디 를 입력하고, 그들의 오픈아이디 인증서비스와 인증을 한후, 당신의 가입 절차로 당신 사이트와 공유하기 위해 선택한 프로필 정보들을 가지고 인증된체로 돌아온다.
  3. 기존 사용자들을 위한 로그인 페이지에 약간의 OpenID 관련 사용자 인터페이스

    • 본인들 계정에 오픈아이디 를 연결한 사용자들은 그들의 OpenID 를 입력할 것이며, 그들의 오픈아이디 인증서비스와 인증을 한후, 인증된 체로 당신의 로그인페이지로 돌아온다. 당신은 그들의 오픈아이디를 그들의 사이트내 사용자 식별키로 매핑할 수 있고, 따라서 그들이 마치 기존의 사용자명(또는 이메일)과 비밀번호로 로그인한 것처럼 로그인 시킨다.
  4. 사용자들이 계정에 연결된 오픈아이디들을 나열,추가,삭제할 수 있는 설정 페이지

당신이 구현할 것들을 요약하면 다음과 같다:

  1. 하나의 오픈아이디 데이타베이스 테이블

    • 컬럼: (openid_url, user_id). openid_url 는 텍스트 문자열, user_id 은 현재 당신이 내부 사용자 키로 사용하는 것.
    • openid_url 에 PK (유일함, OpenID 로 사용자들을 검색하기 위해)
    • user_id 에 색인 (특정 사용자 계정에 연결된 모든 OpenID 들을 나열하기 위해)
  2. 하나의 웹페이지/CGI , 사용자가 입력한 오픈아이디 를 검색한후 그들의 오픈아이디 인증서비스로 보낸다 (redirect)

    • 입력된 오픈아이디가 이미 당신 사이트의 기존 사용자 소유인지 검색한다.
    • (오픈아이디 라이브러리로) 오픈아이디 인증서비스로 보내어 사용자가 인증할 수 있도록 한다 (세부 사항은 아래에)
  3. 하나의 웹페이지/CGI, 사용자의 오픈아이디 인증서비스로 부터의 응답을 처리한다.

    • (오픈아이디 라이브러리로) 응답을 검증한다.
    • 새 사용자들의 경우, 당신의 가입 절차로 보내며 오픈아이디 인증서비스로 부터 보내진 등록정보들로 등록 정보들을 미리 채운다. 또한 당신은 당신의 가입절차를 약간 수정해서 그 사용자들에게는 비밀번호 등록을 하지 않도록 해야할 것이다 (왜냐하면 그들은 이미 그들의 오픈아이디로 인증을 할 것이므로).
    • 기존 사용자들의 경우, (오픈아이디 인증을 처음한 아이디라면) 그들의 계정에 인증된 오픈아이디를 연결해둘 필요가 있으며, 해당되는 사용자키를 찾아서 그들의 계정으로 로그인 시킨다.

     

  4. 하나의 웹페이지/CGI, 사용자 계정에 연결된 오픈아이디들을 관리한다.

    • 현재 로그인한 사용자에게 연결된 모든 오픈아이디들을 구해서 나열할 수 있다.
    • 사용자에게 오픈아이디를 추가로 연결할 수 있게 한다. (위에 언급한 절차를 이용한다)
    • 기존의 오픈아이디를 연결을 제거할 수 있게 한다.
  5. 사용자 삭제 코드에 코드를 추가 삽입하여, 계정 삭제시 연결된 모든 오픈아이디들을 연결 제거 한다.

바로 시작하기 위해서 다음 리소스들이 필요할 것이다:

  • 당신의 프로그래밍 언어로 된 오픈아이디 컨슈머 라이브러리. Plaxo 의 서버는 C++ 로 되있다, 그래서 우리는 libopkele 을 이용했다 (이런 훌륭한 오픈소스 라이브러리를 제공한 Michael 과  Klever 팀원들에게 감사한다!), 그러나 다른 언어로된 라이브러리들 도 많이 있다.
  • 몇가지 표준 오픈아이디 이미지들도 있어서, 사용자 인터페이스에 이용한다. 예를 들면 small icon 과 로고들 (small, normal, PDF)
  • 테스트를 하기 위한 오픈아이디 인증 서비스들. 몇가지 예를 들면, 한글로는 myID.net, idtail.com, 영문으로는 MyOpenID.com, ClaimID 등이 있다. 또한 당신이 만약  AOL/AIM 스크린명을 가지고 있다면 http://openid.aol.com/SCREENAME 을 오픈아이디로 쓸 수도 있다. 만일 Daum 블로그 계정을 가지고 있다면, 다음 블로그 주소도 오픈아이디로 쓸 수 있다 (먼저 openid.daum.net 에서 설정하기 바란다.)

오픈아이디 컨슈머 지원을 구현하면 다음과 같은 잇점을 즉시 누릴수 있다:

  • 이미 오픈아이디를 가진 120 만 (국내 10 만 ~ 100 만, 포탈 오픈아이디 제공 예상) 사용자들이 당신의 사이트에 전보다 훨씬 쉽고 빠르게 가입할 수 있다, 그 이유는 사용자들이 새로운 로그인 아이디와 비밀번호를 만들고 기억할 필요가 없어질 것이기 때문이며, 또한 가입 정보를 자동으로 미리 채울 수 있기 때문이다.
  • 당신은 사용자들의 오픈아이디들을 모으기 시작할 수 있고, 따라서 점점더 많은 오픈아이디 지원 서비스들이 늘어감에 따라 당신의 사용자들은 쉽게 당신의 사이트와 연계한 그 서비스들의 장점을 이용할 수 있게 된다.
  • 또한, 당신은 온라인 아이덴티티 분야의 유망한 오픈 표준을 지원함으로써 당신의 사용자들에 대한 공헌와 사려깊은 리더쉽을 과시할 수 있을 것이다.

추가로, 오픈아이디 지원이 확산됨에 따라서, 미래에는 다음과 같은 추가적인 잇점들이 당신을 기다리고 있다:

  • 당신의 사용자 계정을 다른 사이트의 그 사용자 계정과 자동적으로 연결할 수 있어서 매쉬업들을 위한 정보를 공유할 수 있고, 여러 사이트에 같은 정보를 반복적으로 입력해야 하는 사용자들의 번거로움과 불편과 짜증을 제거할 수 있다.
  • 사용자들이 다른 사이트에서의 그들의 정보 변경을 통지받을 수 있어서, 당신의 사이트에 항상 그들의 최신 정보를 유지할 수 있다.
  • 다른 사이트로 부터 믿을 만한 사실들을 서명된 체로 받을 수 있으며, 이중에는 연령 검증, 확인된 이메일 주소, 회원여부 확인 등 이외에도 더 있다. (한국에는 실명 인증 확인 등도 해당된다)

구현 상세

  1. 오픈아이디 컨슈머 라이브러리를 설치한다

    • 이미 대부분의 프로그래밍 언어로 구현된  오픈아이디 라이브러리들 이 있어서 거의 대부분의 어려운 작업들은 다 처리할 것이다. JanRain 개발팀이 그중 많은 부분을 작성했으며 오픈아이디에 관해서는 엄청 똑똑하고 박식하기 때문에, 만약 좀더 도움이 필요하다면 그들이 좋은 정보원이 된다.
    • 라이브러리에 따라서는, 오픈아이디 인증 사이트와의 연관정보를 저장하기 위한 영구적인 저장소 (persistent store, 파일 또는 DBMS) 를 필요로 할 것이다. 본질적으로 이것은 인증서버/처리기 문자열을 하나의 연관 문자열로의 매핑을 저장하는 것 뿐이다. 당신은 최소한 해당 세션 (오픈아이디 인증을 검증하기 위한) 동안만 연관정보를 저장하면 되지만, 이상적으로는 더 오래동안 그 값을 저장함으로써 매번 그 오픈아이디 인증서비스로 보낼 때 마다 연관을 다시 수립하지 않아도 된다 (그렇게 함을써 훨씬 빠른 처리가 이루어 진다). 당신은 메모리 캐시, 데이타베이스, 이외에도 당신이 이용할 수 있는 다른 어떤 저장소도 이용할 수 있다.
  2. 오픈아이디 데이타베이스 테이블을 하나 만든다

    • 다음과 같은 스키마를 이용한다 (이것은 MySQL 에서 작동하지만, 만약 다른 데이타베이스 또는 다른 내부 사용키를 사용하는 경우에도 약간만 변경하면 된다):

      create table user_openids (
      openid_url varchar(255) not null,
      primary key (openid_url),
      user_id int not null,
      index (user_id)
      );
    • 하나의 전역 테이블로 유지해야 당신의 모든 사용자를 OpenID 로 검색할 수 있다 (심지어 당신의 사용자들이 여러 데이타베이스로 분할되어 있는 경우에도).
    • 오픈아이디 URL 들은 대표형식 (canonicalized ) 으로 저장해야 튼튼한 검색이 된다 (그래야, 만약 사용자들이 그들의 오픈아이디를 매번 약간씩 다르게 입력하더라도 그들의 계정에 매핑할 수 있게 된다). 대부분의 오픈아이디 라이브러리들은 대표화 함수를 제공할 것이지만, 요약해 보면 'http://' 가 빠진 경우에 추가해야 하고, 프로토콜과 서버도메인의 문자만 모두 소문자로 변환한다 (그러나, URL 의 나머지 부분은 아니다.), 그래서 예를 들면 "WWW.AOL.COM/myOpenID" 는 "http://www.aol.com/myOpenID" 로 저장되어야만 한다.  또한 URL 의 끝나는 '/' 들은 모두 제거해야 할 수도 있다. (보통, 호스트 바로 뒤의 '/' 는 오히려 붙인다.)
    • 보통 데이타베이스 접근 코드 레이어가 있는 경우, 당신은 아래의 함수들을 당신의 애플리케이션들에 제공해야 한다 (각각에 대해 구현 SQL 들을 대충 제시해 놓았다). 다시 상기시키지만, 오픈아이디를 인자로 받는 모든 함수들은 데이타베이스에서 검색하기 전에 반드시 대표화를 시켜야만 한다.

      • GetUserId(openid_url)
        select user_id from user_openids where openid_url = openid_url
      • GetOpenIDsByUser(user_id)
        select openid_url from user_openids where user_id = user_id
      • AttachOpenID(openid_url, user_id)
        insert into user_openids values (openid_url, user_id)
      • DetachOpenID(openid_url, user_id)
        delete from user_openids where openid_url = openid_url and user_id = user_id
      • DetachOpenIDsByUser(user_id)
        delete from user_openids where user_id = user_id

     

  3. 당신의 가입페이지에 오픈아이디 UI 를 추가한다. (참고: 권장표준스타일가이드)

    • 당신의 가입페이지에 오픈아이디 사용자들이 오픈아이디로 가입할 수 있는 부분을 추가하라. UI 의 목표는 오픈아이디 사용자들이 쉽게 당신 사이트의 오픈아이디 지원을 인지하도록 하지만, 오픈아이디가 없는 사용자들도 혼선없이 정상적인 가입을 수행하도록 하는 것이어야 한다. 당신은 가입페이지에 오픈아이디 입력란을 직접 배치할 수도 있고 따로 오픈아이디를 입력하는 오픈아이디 페이지를 두고 링크만 줄 수도 있다.
    • 오픈아이디 입력란은 어디에 두던간에, 커뮤니티 표준의 이름과 스타일을 따라야 한다:

      • 오픈아이디 입력 텍스트 필드의 ID 와 name 속성에는 "openid_identifier" ("openid_url" 은 1.0 국내에서는 지양)  (이것은 플러그인등의 프로그램이 서로 다른 사이트들간에도 쉽게 오픈아이디 입력란은 인식하고 자동화 처리가 가능하게 하는, 단순하지만 강력한 관습입니다. 꼭 지키는 것이 네트웤효과에 편승할 수 있는 방법입니다.)
      • 오픈아이디 입력 텍스트 필등의 배경에는 표준 small OpenID logo 를 다음의 CSS 를 이용해서  깔아줍니다:

        background: #FFFFFF url('/images/openid-icon-small.gif') no-repeat scroll 0pt 50%;
        padding-left: 18px;

       

    • 당신의 사이트에 오픈아이디가 무엇이며 어떻게 사용할 수 있는지에 대한 간략한 설명을 제공하는 것도 좋은 생각이다 (왜냐하면 호기심에 차서 쭉 둘러보는 사용자들이 아마도 꽤 있을 것이기 때문이다).
    • 오픈아이디 입력란은 포함하는,  이제 구현하게 될 오픈아이디 로그인 CGI 로의 submit 폼을 하나 만들어라.
    • 오픈아이디 인증서비스에 오픈아이디를 제공하고 인증하는 도중에, 당신은 사용자를 약간 다른 가입페이지로 다시 돌려보낼 필요가 있다. 첫째로, 사용자가 등록하려고 하는 오픈아이디를, 권장하건데 사용자가 일관되게 식별할 수 있도록, 오픈아이디 로고를 앞에 달아서 보여주어야 한다. (아래의 샘플 화면을 참고하라). 둘째로,  당신은 절대로 사용자에게 사이트 전용 비밀번호를 요구해서는 안된다, 왜냐하면 사용자들은 오픈아이디로 인증도중일 것이기 때문이다. 따라서, 비밀번호 입력란은 가려야 하며, 당신의 가입 로직이 이것을 허용하도록 한다 (만일 당신 코드가 이것을 필수로 한다면, 임의로 자동 생성된 비밀번호를 채워넣고, 사용자에게는 보이지 않는 방법도 있겠다). [주: 사이트 전용 비밀번호는 이후에 따로 계정 설정 페이지 등에서 입력받는 것도 좋겠지만, 여기서 중요한 점은 오픈아이디 사용자들에게 주는 핵심 가치는 그들이 더이상 그들이 사용하는 모든 사이트에 각각의 비밀번호/인증서를 따로 따로 유지할 필요가 없게 하는 것임을 명심해야 한다.]
    • Plaxso 가입 절차에 어떻게 오픈아이디를 추가했는지를 보여주는 스샷들이다:
      Plaxo registration page with OpenID link Plaxo OpenID page Returning to Plaxo registration with a verified OpenID Plaxo registration is pre-filled with simple-registration data from the OpenID provider

     

  4. 당신의 로그인 페이지에 오픈아이디 UI 를 추가한다

    • 오픈아이디 사용자가 자신의 오픈아이디를 이용하여 로그인 할 수 있는 섹션을 당신의 로그인 페이지에 추가하라. 이것은 오픈아이디와 자신의 계정을 연결한 당신 사이트의 기존 사용자와 새로운 사용자 모두에게 작동하는 것이며, (위에서 본 것과 같은 과정을 이용하여) 이들은 자신의 오픈아이디를 이용하여 로그인 할 수 있을 것이다. 가입페이지에서와 같이, UI는 오픈아이디 사용자에게 지나친 혼동을 주지 않고 나머지 사용자들에게도 혼동을 주지 않도록 균형을 맞추는 것을 목표로 해야 한다. 위에서 본 가입페이지에 적시되어 있는 것처럼 오픈아이디 (로그인)박스에 이름을 붙이고 스타일을 입혀라. 그리고 위와 같이, 오픈아이디 입력란을 감싸고 있는 폼은 당신이 만들고자 하는 로그인 CGI로 전송되어야 한다.
    • 메인 로그인 페이지에 더하여, 홈페이지 어디에나 로그인 UI를 둘 수도 있을 것이다. 전통적인 로그인 옵션을 제공하는 자리에는 어디라도 오픈아이디를 이용하여 로그인 할 수 있는 옵션을 두어야 한다.
    • Plaxo의 로그인 페이지에 어떻게 오픈아이디를 추가했는지를 보여주는 스크린샷을 보자:
      Plaxo signin page with OpenID option Plaxo homepage signin UI with OpenID option Plaxo homepage signin UI with OpenID option selected

     

  5. 새로운 오픈아이디 로그인 페이지 / CGI 를 만든다.

    • 당신의 CGI는 두 개의 기본적인 입력(쿼리) 파라미터를 받아야 한다:

      • openid_identifier (또는 1.0 스펙은 openid_url ): 사용자가 입력한 오픈아이디 (가입, 로그인, attaching 등을 위한)
      • action_type: 사용자가 수행하고자 하는 작업. 가능한 값들은 login, complete, attach, list 와 delete 등 일 것이다. (만약 당신이 레일즈나 비슷한 시스템을 사용하고 있다면, 이것들은 컨트롤러의 메쏘드가 될 수도 있으며, 따라서 URL 그 자체의 부분일 수 있다.)
    • 로그인 액션 구현하기 (여기로 가입페이지와 로그인 flow에 당신이 추가한 UI가 모두 submit 할 것이다.)

      1. 사용자가 입력한 openid_url을 위에서 기술한 GetUserId 함수를 이용하여 찾는다.
      2. 그 오픈아이디가 이미 당신의 시스템에 attach되어 있다면, 그 사용자가 현재 당신의 사이트에 로그인되어 있는지 확인하라.

        1. 사용자가 로그 인해 있지 않다면, 기존 사용자로 로그인을 시도하는 중인 것이므로, 오픈아이디 인증서비스로 리다이렉트 해야 한다. 이때 (사용자가 새로운 계정을 생성하려하는 것이 아니므로) 오픈아이디 인증서비스에 등록 정보를 요청하지 않도록 플래그를 셋팅한다.
        2. 사용자가 로그인한 상태이고 오픈아이디가 그 사용자의 것이라면 (즉, 오픈아이디가 현재 로그인되어 있는 사용자의 user_id와 매핑되어 있는 경우), 아무것도 할 필요가 없다. (이 사용자는 로그인되어 있고 이미 오픈아이디도 attach되어 있으므로, 오퍼레이션을 수행하지 않는다.) 이 케이스는 경계 케이스가 된다.
        3. 사용자가 로그인한 상태이지만 오픈아이디가 다른 사용자의 것이라면, 이 오픈아이디는 다른 사용자가 소유한 것이라는 에러 메시지를 출력해야 한다. 이때 사용자에게 로그아웃 후, 재시도할 수 있는 옵션을 제공할 수 있다. 이 케이스는 경계 케이스가 된다.
      3. 그 오픈아이디가 당신의 데이터베이스에 없다면 사용자가 새 계정을 생성하려는 것이므로, 오픈아이디 인증서비스로 리다이렉트 해야 하며, 등록 정보를 요청해야한다.
      4. 오픈아이디 인증서비스가 당신의 서비스로 리다이렉트를 통해서 인증 결과를 전달할 때, 서비스는 오픈아이디를 기억해야 할 것이나, 오픈아이디 인증서비스는 오픈아이디를 리턴하지 않을 수도 있다. 따라서 오픈아이디를 세션에 저장해야 한다, 세션이 아니라면 당신의 데이터베이스에 저장할 수도 있으나, 그 데이터베이스는 영속적이고 사용자의 위변조로부터 보호되는 곳(사용자가 위변조할 수 있는 쿠키같은 것이 아닌 곳)이어야 한다.
        (사용자가 입력한 오픈아이디를 저장해야 하는 이유는, 사용자가 자신의 오픈아이디를 보이는 것과는 다르게 타 오픈아이디 인증서비스로 위임(delegate)할 수 있기 때문이다. 예를 들어, 내가 jsmarr.myopenid.com와 같은 다른 오픈아이디로 위임된 URL인 오픈아이디 josephsmarr.com를 사용해서 계정을 생성하려고 한다면, 오픈아이디 인증서비스가 당신의 서비스로 리턴해서 인증을 완료할 때, 서비스는 내가 계정 생성을 위해 사용한 오픈아이디가 jsmarr.myopenid.com가 아니라 josephsmarr.com라는 것을 알아야 한다. 다행히 대부분의 OpenID library는 이것을 처리하게 되겠지만, 당장은 원래 제시된 오픈아이디를 세션에 저장해야 한다. 이 문제는 오픈아이디 2.0 스펙에서 해결될 것이다.)
      5. 오픈아이디 인증서비스가 사용자 인증을 완료한 뒤 리턴할 return_to URL을 생성해라. return_to URL은 당신이 만든 오픈아이디 로그인 CGI의 complete 액션이 될 것이다.
      6. 위에서 사용자가 새로운 계정을 생성하는 것이라고 판단된다면, 오픈아이디 인증서비스에 요청할 등록 정보를 정해야 한다. 대부분의 오픈아이디 인증서비스는 sreg(simple-registration extension) 를 지원한다. sreg란 당신의 서비스에서 필수 또는 선택적으로 사용할 수 있는 일반적인 등록 필드의 목록인데, 이름(full name), 이메일(e-mail), 별명(nickname), 성별(gender), 생년월일(data of birth), 우편번호(postal code), 국가(country), 언어(language), 표준시간대(time zone) 필드를 가진다. 만약 당신이 요청한 sreg 필드에 대해서 사용자가 정보 제공에 동의한다면, 그 정보들을 계정 생성 과정에 미리 채울 수 있으므로, 계정 생성 절차에서 사용자의 불편함을 줄일 수 있다. 만약 당신이 사용하는 오픈아이디 라이브러리가 sreg 파라미터 요청을 기본 지원하지 않는다면, 라이브러리가 sreg 요청에 필요한 일반화된 방법을 포함하고 있는지, 아니면 최악의 경우 오픈아이디 인증서비스로 리다이렉트 요청을 하기 전에 리다이렉트 URL에 당신이 직접 sreg파라미터들을 추가해야하는지 확인해야 한다.
      7. 당신이 사용하는 오픈아이디 라이브러리의 checkid_setup를 호출하여, 사용자의 오픈아이디 인증서비스로 리다이렉트하는 URL을 생성하라. 이때 사용자가 입력한 (대표형식으로 변환된) 오픈아이디와 위에서 생성한 return_to URL을 함께 전달해야 한다. 이와 함께 당신의 사이트에서 필요로 한다면, 전달 받기를 원하는 sreg 필드도 함께 전달하라. 라이브러리에 따라서는 이 함수에서 발생하는 에러를 처리하도록 해야한다. 에러 없이 정상 동작한다면, 이 함수의 결과값은 리다이렉트용 URL이 된다.
      8. 위에서 만들어진 URL로 CGI가 리다이렉트하도록 해라. 원칙상 CGI는 서버측 리다렉트 응답(역주: javascript와 같은 클라이언트측 리다이렉트가 아니라, HTTP protocol의 3xx 응답)을 통해서 리다이렉트되도록 해야한다.
      9. 사용자는 오픈아이디 인증서비스로 리다이렉트 된다. 사용자는 (아직 오픈아이디 인증서비스에 로그인하지 않았다면) 오픈아이디 인증서비스에 로그인하고, 당신의 웹사이트를 신뢰하는지 여부를 결정해야하며, 당신의 웹사이트에서 sreg 정보를 요청했다면 전달할 sreg 값을 입력해야 한다. 이 모든 과정이 완료되면, 당신이 로그인 과정을 완료하기위해 complete 액션을 수행할 수 있도록, 오픈아이디 인증서비스는 당신이 전달한 return_to URL로 사용자를 리다이렉트한다.


        Plaxo에서 (myopenid.com인 경우) 오픈아이디 인증서비스에 로그인하고, sreg 정보를 전달하는 스크린샷이다:
        OpenID provider signin page OpenID provider registration info page
    • complete액션 구현하기 (IDP에 로그인 된 사용자가 redirect되는 페이지 이다.)

      1. IDP가 당신이 제공한 return_to URL로 redirect해 줄때에 여러 추가적인 파라미터를 넘겨줄 것이다. 이런 파라미터들은 당신이 사용자를 신뢰 하는데 도움을 줄 수 있는 정보들을 담고 있다.
        사용하는 라이브러리에 따라 다르겠지만 사용자 검증 함수에 사용하기 위해서 이러한 파라미터들을 모아 둬야 할 필요가 있을것이다.
      2. 세션에서 사용자가 맨처음 입력한 OpenID를 얻어온다. (IDP로 redirect시키기 전에 저장해 뒀다.)
      3. id_res모드로 IDP로 부터 건네 받은 사용자 인증 정보가 정확한지 재차 확인한다. 필요하다면 사용자가 처음 입력한 OpenID도 파라미터와 함께 보낸다. 이 함수는 지금까지의 모든것들이 valid한지 체크할 것이다. 만약 IDP로부터 에러코드를 돌려받는다면 사용자에게 적절한 에러메시지를 보여주기 바란다. 에러코드가 아니라면 이제 당신은 사용자가 입력한 OpenID를 인증된 OpenID로 확인한 것이다.
      4. 부가적으로: OpenID확인작업이 성공적으로 끝난 후에 사용자의 OpenID를 사이트 쿠키에 심어 놓고 싶을 수 있다. 이렇게 하여 사용자가 다음번에 당신의 사이트를 방문하는 경우 OpenID입력란에 사용자의 OpenID를 미리 채워둘 수 있기 때문이다. 여기서 주의해야 할 점은 사용자가 명시적으로 로그아웃을 하는 경우에는 반드시 심어놓았던 쿠키를 지워야 한다는 것이다.
      5. 인증된 OpenID를 GetUserId함수를 이용하여 다시한번 살펴보자. 만약 당신의 DB에서 해당 OpenID를 찾을 수 없다면 이 사용자가 현재 당신의 사이트에 로그인 돼어 있는지 확인하여 이미 존재하는(로그인 한) 계정에 추가하기 바란다. 로그인 되어 있지 않다면 이 OpenID를 이용하여 새로운 계정을 등록하는 절차를 밟아야 할것이다. 우선 계정 생성코드에서 사용할 수 있도록 인증된 OpenID를 세션에 저장한다.(사용자가 처음 입력한 OpenID와 같은 세션변수를 사용하면 안된다. 사용자가 입력한 OpenID와 IDP가 인증해 준 OpenID는 다를 수 있다.)
        그다음 IDP로부터 넘겨받은 간단한 등록 데이타와 함께 사용자를 회원가입 페이지로 redirect시킨다. 이때 IDP로부터 넘겨받은 데이타를 당신의 사이트에서 일반적으로 필요로하는 사이트에 맞게 매핑시켜주어야 할 것이다.

        • 위에서 설명한바와 같이, 사용자 등록 페이지에서는 계정 정보에 오픈아이디를 명확하게 표시해야 하며, 사용자는 자신의 오픈아이디로 로그인 할 것이므로, 당신 사이트의 비밀번호를 요구하지 말아야 한다. 추가적으로, 오픈아이디 인증서비스에서 제공한 모든 등록 정보를 미리 채워둬야 한다. 등록 페이지에서 추가적인(역주: 오픈아이디 인증서비스를 통해서 전달된 등록 정보가 아닌 것) 등록 정보를 요구하거나, 필수 또는 선택적인 필드에 대한 현재의 정책을 그대로 유지하는 것은 아무런 문제가 없다. (오픈아이디 사용은 당신 사이트에서 등록 과정을 가속화시키며, 당신이 요구하는 정보에 대해서 변경을 요구하거나 당신 사이트의 일반적인 행동에 변경을 요구하지는 않는다.) 마지막으로, 사용자가 당신의 사이트에 이미 계정을 가진 사용자인 경우, 그 계정에 오픈아이디를 부여(attach)하는 링크를 달아라. 이 링크는 이미 계정을 가진 사용자가 로그인하지 않은 상태에서 등록되지 않은 오픈아이디를 입력한 경우를 처리해야한다. [이 경우는 일반적인 경우는 아니므로, 자신의 오픈아이디로 당신의 사이트를 처음 사용하는 모든 사용자에게 "계정이 있으시면 로그인 하십시오. 아니면 신규 계정을 발급받으시겠습니까?"라고 묻는 것 보다는, 등록 과정의 시작부분에 작은 링크를 다는 것이 더 좋다.]
        • 사용자가 등록 과정을 완료하고 신규 계정 생성이 완료되면, AttachOpenID 함수를 호출해서 새로 생성한 계정에 인증된 오픈아이디를 부여하라. [사용자 테이블과 오픈아이디 테이블이 서로 다른 데이터베이스에 있고 동일 트랜잭션으로 두 테이블을 접근할 수 없다면, 가끔씩 오픈아이디 부여 실패로 이 계정이 결코 사용될 수 없게 되는 경우가 있을 수 있다. 이것을 100% 방지하기는 힘들지만, 드문 경우이고 사용자는 언제든 계정 생성을 다시 할 수 있으므로, 대부분의 경우 이러한 레이스 컨디션을 무시하고 잘 동작할 것이라 기대해도 무방하다.]
      6. 인증된 오픈아이디가 이미 어떤 계정에 부여된 것이면, 사용자가 예전 방법으로 로그인했을 때와 같이 사용자를 로그인 시키면 된다. (로그인시 사용한 오픈아이디가 부여된 계정이 현재 로그인되어 있는 계정과 다르다면, 로그아웃 처리를 하고 제시된 오픈아이디가 부여된 계정으로 로그인 처리를 해라. 이미 사용자가 그 오픈아이디를 소유한 것이 증명되었으므로, 해당 오픈아이디로 로그인 처리를 하면 된다.)

       

    • attach액션 구현하기 (이미 존재하는 사용자 계정에 OpenID를 추가)

      1. (이 액션은 사용자가 이미 로그인 되어 있으며 새로운 OpenID를 인증받은 경우에 complete액션의 한 부분으로서 호출 된다. 따라서 이 액션이 호출되기 전에 사용자가 로그인 돼어있어야 한다.)
      2. 로그인된 사용자의 계정에 AttachOpenID함수를 이용하여 인증된 OpenID를 추가한다.
      3. 이제 사용자의 계정에 OpenID가 추가되었으며 앞으로 이 OpenID로 로그인이 가능하다는 것을 확인할 수 있는 메시지를 보여준다. 또는 사용자의 계정에 추가된 다른 OpenID리스트를 보여줄 수도 있을 것이다.

        Plaxo의 attach 결과 페이지 스크린샷:
        Attaching an OpenID to an existing Plaxo account

       

    • list액션 구현하기 (로그인 한 사용자의 계정에 연결된 OpenID를 보여준다.)

      1. 로그인된 사용자여야 한다. (필요하다면 로그인 페이지 이후에 redirect된다)
      2. GetOpenIDsByUser함수를 호출하여 로그인된 사용자의 계정에 연결된 OpenID들을 가져온다.
      3. 가져온 OpenID들을 그것을 삭제할 수 있는 링크와 함께 보여준다. 이 링크는 다음의 delete액션에 openid_url파라미터로 보내서 삭제할 수 있도록 한다.
      4. 다른 OpenID를 추가할 수 있는 링크나 입력란을 제공하도록 한다. 이 링크는 사용자로 하여금 login액션, attach액션을 통과하여 다시 list페이지로 돌아오게 한다. (이역시 로그인 된 사용자를 대상으로 한다)
      5. 만약 당신의 사이트에 환경설정 할 수 있는 페이지가 있다면 "내 OpenID 관리하기"라는 식으로 이 list페이지로 접근할 수 있는 링크를 제공해야 할 것이다.

        Plaxo의 환경설정 페이지와 list페이지 스크린샷.
        Listing your attached OpenIDs on Plaxo Link to manage OpenIDs in Plaxo 3.0 settings Link to manage OpenIDs in Plaxo 2.0 settings

       

    • delete액션 구현하기 (사용자 계정에서 OpenID를 삭제한다.)

      1. 로그인된 사용자여야 한다. (필요하다면 로그인 페이지 이후에 redirect된다)
      2. 부가적으로: 사용자가 삭제하려고 하는것이 당신의 사이트에 로그인 할 수 있는(OpenID나 기타 다른 인증방법에 의한 ID를 포함한 - 역자주) 마지막 자격증명인지 확인하라. 만약 사용자가 당신의 사이트에 로그인 하기위한 암호를 설정하지 않았거나 계정에 연결된 마지막 OpenID인 경우에 이것을 삭제해 버린다면 그 사용자 계정은 영원히 잠겨버리게 되는 것이다. 이런 상황을 복구할 수 있는(비밀번호 찾기 등... - 역자주) 뾰족한 방법이 없다면 다음과 같은 에러메시지를 보여주는것이 좋을 것이다. "귀하의 계정에 연결된 마지막 OpenID입니다. 이 OpenID를 삭제하면 더이상 로그인 할 수 없으므로 우선 다른 OpenID를 등록하거나 비밀번호를 등록해 주십시오."
      3. 계속하여 진행하자면, openid_url 파라미터로 넘어온 값으로 DetachOpenID함수를 호출하여 로그인 된 사용자의 계정에 연결된 OpenID를 삭제한다. 파라미터로 넘어온 OpenID가 사용자의 계정에 연결된 OpenID가 아니라면 그냥 에러를 보여주거나 아무 작업도 하지 않아도 될 것이다.
      4. OpenID가 삭제되었으며 더이상 이 OpenID로 사이트에 로그인 할 수 없다는 메시지를 보여준다. 만약 사용자가 이 OpenID를 다시 사용자의 계정에 연결시키고자 한다면 사용자는 다시 인증 프로세스를 거쳐야 할 것이다. OpenID가 삭제되었음을 사용자가 확인할 수 있도록 list액션으로 redirect시켜도 된다.

        Plaxo에서 OpenID를 삭제하였을 때의 스크린샷:
        Confirming that a user wants to detach an OpenID from their Plaxo account Confirmation of a detached OpenID

       

    • 사용자 계정을 삭제할때 계정에 연결된 OpenID를 삭제하는 루틴을 추가하라.

      1. 만약 당신의 사이트에 사용자가 그들의 계정을 삭제(회원탈퇴 - 역자주)하는 것이 가능하다면 해당 계정과 연결된 OpenID를 모두 삭제해 주어야 한다. 왜냐하면 사용자가 다른 계정에 OpenID를 연결시키고 싶어 할 수 있기 때문이다. 계정삭제 루틴에서 DetachOpenIDsByUser함수를 호출하거나 이 함수를 트리거로 등록해두면 될것이다.

       

...and you're done!

여기까지 왔다면 축하한다. 이제 당신의 웹사이트에 오픈아이디를 적용하기 위한 모든 수단을 갖추게 된 것이다. 위의 과정들은 철저하고 완전하지만, 구현에 있어서 아래의 best-practices를 기억해 두는 것이 도움이 된다.

 

  • 페이지에서 사용자의 오픈아이디를 보여줄 때 마다 오픈아이디임을 인지할 수 있도록 작은 오픈아이디 아이콘을 앞에다 두어라. 예로, 위의 가입페이지 스크린샷을 보라. (당신사이트의 유져 인터페이스가 오픈아이디들의 목록을 보여주고 있다는 것이 명백한 목록 페이지는 가능한 예외라 할 수 있겠으나, (오픈아이디 아이콘을 보여준다고 해도) 손해볼 것은 없다!
  • 일반적으로, 사용자들의 오픈아이디를 공개적으로 혹은 다른 사용자들에게 표시하기 전에 (옵트-인 방식의) 동의를 구해야 한다. 사용자는 어쩌면 자신의 오픈아이디를 공개적인 식별자로 공유하기를 원할 수도 있겠지만, 기본적으로 개인적인 signing in 방법으로 사용하기를 원하고 그들의 공개 프로필의 한 속성이 되기를 원하지 않는다고 가정해야 한다.
  • 오픈아이디 스펙 2.0(곧 완료될 예정이다; 대부분의 사이트는 현재 1.1 버젼을 사용하고 있지만 걱정하지 말라, 오픈아이디 2.0 서버에 맞추기 위해 아무 것도 바꿀 필요가 없다.)로 시작한다면, 사용자들은 joseph.smarr와 같은 i-names 역시 오픈아이디로 이용하여 sign-in할 수 있게 될 것이다. 당신이 이를 구현함에 있어 transparent하기를 바라지만, 앞으로 사용자의 i-names를 공개적으로 표시하기를 계획하고 있다면, = 이나 @로 시작하는 일반적인 별명으로 등록하는 것을 제한하기 시작할 좋을 때이다, 왜냐하면 이런 별명들은 인증된 i-names와 혼동될 수 있기 때문이다. 이미 많은 사이트들은 이런 문자들로 시작하는 닉네임을 불허하고 있지만, 한번 볼 필요가 있다. (i-names와 관계없이 이런 문자들을 제한하고는 있으나, i-names와 관련되어 있음을 알 필요가 있다는 뜻-역자주)
  • 오픈아이디는 이미 널리 채택되고 있지만, 웹과 같은 규모에서 사용자 중심의 아이덴티티를 제공할 때의 문제점은 여전히 해결이 진행 중인 것임을 기억하라, 그러니 어떻게 돌아가는 지에 대해 질문이나 피드백이 있으면 말하라! openid.net 과 OpenIDEnabled.com 같은 사이트에 기여하거나, 코멘트을 남기고 블로그에 글을 쓰거나, 혹은 대화에 참여할 수 있는 뭐라도 하라. 웹 상에서의 아이덴티티에 대해 열정적이라면, 당신의 사이트에 오픈아이디 지원을 제공하는 것은 훌륭한 출발점이다. (오픈아이디) 커뮤니티에 지속적인 공헌자가 되는 것은 투자를 지속시키고 사용자로써 우리가 원하는 대로의 웹을 모두 가질 수 있음을 확실하게 하는 데 도움이 될 것이다.

 

 

OpenID 가 국내에서 실용화, 대중화 되기 위해서는 국내 실정에 맞는 몇가지 과제를 해결해야 합니다. 그중에서도, 실명제가 가장 큰 과제중 하나입니다.

당장 일 방문객 30 만 이상의 국내 대부분의 주요 사이트에서는 '제한적 본인확인제' 를 수행해야 합니다. 결국, 대중적인 사이트에 오픈아이디가 '쉽게' 적용되려면 어떤 식으로든 해결책이 마련되야 하는 것이지요. (물론, 최근에 인터넷 실명제 반대운동도 있습니다만, 정책이 변경되기 까지는, 서비스를 해야지요 ㅎㅎ; )

물론, 현재 제한적 본인 확인제 사이트라도, 오픈아이디 로그인을 허용하는 것이 불가능 한 것은 아닙니다. 오픈아이디를 기존 사이트에 적용할 때 개념상 확실히 구분해야 할 점은 아이디 인증과, 회원 계정의 분리라는 점입니다. 오픈아이디는 아이디와 그 아이디의 인증 기능만을 떼어내어 사용자가 선택한 인증기관에 위임한 것입니다. 따라서, 기존 사이트의 회원계정을 그대로 유지한채, 로그인 방법만 하나더 지원하는 것으로 쉽게 적용할 수 있습니다.

여기서 분명히 할 점은, 오픈아이디는 특정 아이디에 대한 소유권 증명만을 보장하는 것이지, 그 이후에 각 사이트에서 필요한 신뢰에 대해서는 다루지 않습니다. 어찌 보면 기능이 부족한 것으로 볼 수 도 있겠지만, 특정 사이트에서 필요한 신뢰 수준이라는 것은, 사이트별, 국가별 정책에 많이 의존하기 때문에, 오히려 이부분을 사이트에서 로그인후 처리로 맡기어 확장성을 보장한 것으로 볼 수 도 있습니다. 즉, 우리 사이트에서는 프로그램을 통한 로그인을 막고자 한다면, 소위 그림 퀴즈 맞추기 (Captcha test) 같은 것을 요구 해도 되고, 필요하다면, 오픈아이디 로그인 후에, 실명인증을 요구해서 해당 아이디와 함께 기록해 둘 수도 있는 것이지요.

정리 드리면, 당장이라도 모든 오픈아이디 적용 사이트 (RP) 들은 실명제를 적용하는데 아무런 문제가 될 것이 없습니다.

 

다만, 이 방식으로 많은 오픈아이디 RP 들이 개별적으로 본인 확인을 하는 경우에, 사용자 측과 사이트 측에서 많은 비용과 번거로움이 수반됩니다. 일단, 사용자는 지금도 마찬가지이지만, 각 본인확인 사이트 마다 반복해서 본인확인 절차를 수행해야 합니다. 또한, 사이트 입장에서도 본인확인 구축 비용과 처리 비용이 들어갑니다. 당연하게, 많은 RP 들에서 IDP 에서 한번만 본인확인을 해주는 것을 제안했습니다. 즉, 사용자는 자신의 오픈아이디에 한번만 본인확인을 해두면, 본인확인이 필요한 RP 들에 로그인시에는 해당 확인 사실만 전달되므로 매번 확인하지 않으며, 또한, 주민번호를 각 사이트 마다 입력하지 않아도 되므로 안전합니다. 사이트 입장에서도, 관리의 부담이 따르는 주민번호를 아예 입력받지 않기 때문에 그 관리책임에서 자유로울 수 있습니다.

 

이번에, myID 를 서비스하는 오픈마루의 또다른 서비스인 레몬펜이 조인스 총선 섹션에 적용되었습니다. 조인스는 아시다 시피, 제한적 본인확인제 의무 사이트입니다. 따라서, 레몬펜 댓글도 조인스에서 남기시려면 본인확인이 필요합니다. 그래서, 우선 실험적으로, myID 에서 본인확인을 하고, 그 사실만 레몬펜에 알려주어, 레몬펜이 본인확인 의무 사이트에 적용시 활용하도록 해보았습니다. 잠시, 사용자 절차 화면을 소개 드립니다.

 

login.PNG

먼저, 이미 로그인 되어 있다 하더라도, 아직 본인 확인이 안된 사용자가 본인확인 요청 사이트 접근시 다시 로그인을 하게됩니다. 이때, 레몬펜의 기존 기본적인 SREG 항목이외에도 추가적인 정보요청이 발생한 것이므로, myID 는 사용자에게 사이트 인증 승인을 요청을 다시 하게됩니다. 이때, 본인확인 필드가 추가됩니다.

 

strust.PNG

 

 

사용자는 본인의 myID 에서 최초 한번만 myID 와 연계된 신용정보기관을 통해 본인확인을 수행하게 됩니다. 이후로, 오픈마루 서비스에서 본인확인이 필요할 때는 일사천리~입니다. 물론, 본인확인시 입력한 실명과 주민번호는 RP 에는 전송되지 않으며, 본인확인 여부만 전달됩니다. 

 

일단, myID 와 레몬펜 모두 오픈마루의 서비스 이기 때문에 정책상의 문제는 없습니다. 그리고, 기술적으로도 OpenID 1.1 프로토콜을 확장해서 적용했으며, 2.0 프로토콜에 대해서도 고려했습니다. 오픈아이디 커뮤니티에서 이 프로토콜에 대한 피드백을 수렴하여, 국내 표준으로 제안드리고자 합니다. 일단, 레몬펜을 비롯한 오픈마루의 RP 들은 이 프로토콜을 따르게 되므로, 다른 IDP 라도 이 프로토콜 상의 본인인증 요청을 처리해 주시면 적용 가능합니다. 물론, 모든 IDP 의 답변이 신뢰되는 것은 아니겠지만, 그것은 이후의 문제로 남기겠습니다.

 

 

최근 국내에 오픈아이디가 주목을 끌고 있습니다. 해외에서도 한국의 오픈아이디 열풍(?)에 관심이 많더군요. 그런데 최근 국내의 오픈아이디 서비스지원 양상이 다소 걱정되는 부분이 있습니다. 오픈아이디 지원에 긍정적인 커뮤니티들에서 뜨거운 이슈중의 하나는 업체들이 Consumer 보다는 Provider 를 우선 하려는 움직임들 입니다. 물론, Provider 를 먼저 적용하는 것이 기존 회원기반을 많이 가진 중.대형 포탈들로서는 본인들 회원기반의 영향력을 확대하려는 의도로 충분히 이해가 갑니다. 하지만, 문제가 되는 부분은 Consumer, 즉 외부 오픈아이디의 로그인을 부분적으로라도 전혀 지원하지 않으며, 고려도 별로 하지 않는 부분입니다. 

 흔히 이러한 정책을 비판의 대상이긴 하지만, 업체의 이익을 위해서는 '영리한' 선택으로 이해되고 있는 것 같습니다. 하지만, 조금만 깊게 생각해보면 오히려 더 큰 이익을 얻을 수 있는 기회를 포기하는 매우 어리석은 판단이라고 생각합니다. 실례로 미국의 AOL 은 6 천만 회원에게 OpenID 를 일시에 발급해 주면서, 동시에 외부 오픈아이디들의 로그인을 지원하는 Consumer 이기도 합니다. 그리고, 오픈마루의 경우에도 전체 서비스를 외부오픈아이디 제한이 없는 Consumer 로 하며, 특히, Provider 인 myid.net 조차도 동시에 Consumer 입니다. AOL 이 과연 착한척하려고 이러한 정책을 취할까요? 아닙니다. 오히려 Consumer 를 동시에 하는 것이 AOL 에 더 큰 이익이 되기 때문입니다.

 어떠한 이익이 되는지, 좀더 구체적인 시나리오를 가지고 설명해 보겠습니다. 앞으로 오픈아이가 활성화 되면 국내에서 흔하게 발견될 만한 상황입니다. 대략 10 위안에 드는 국내 중견 포탈 A 사를 예를 들어 봅니다. A 는 다른 포탈들과 마찬가지로, 100 개의 제휴 CP 들로 부터 컨텐츠와 서비스를 제공받아서 재가공하여 서비스합니다. 약간의 도식을 도입해 보면,  A <- {CP1..CP100}, 이들 CP 들 중에는 상당수가 자체 회원기반도 가지고 있습니다. 이경우 포탈 A 와 CPk 의 계정간의 연계 서비스 모델이 흔히 나오게 됩니다. 이를 테면, 교육 CP 에 가입하면서 사용한 활동상태/ 구매컨텐츠등이 포탈 A 의 페이지에 통합되는 흔한 패턴들이 보입니다. 이를 위하여 흔희 취하는 정책이 포탈 A 의 계정을 ID 를 CP 에서 기억하는 단방향 연결 방식입니다.

 보통 이러한 중견 포탈 A 는 오픈아이디를 같은 목적으로 활용하기 위해 기존 A 계정들에 대해서 일괄로 오픈아이디를 할당하여 Provider 를 서비스하면서 CP 들에게 consumer  로서 계정 연계를 드라이브 하려고 합니다. 물론, 이방향은 매우 자연스러운 생각입니다.

하지만 안타까운 것은 여기에서 그치고 마는 점입니다. 흔히 우선순위와 리소스제한으로 변명하지만, 사실은 Consumer 를 병행하는 것이 별로 이익이 안되며 오히려 손해가 날것 이라는 막연한 판단이 작용합니다. 거기에, 비 현실적인 욕심까지 붙습니다. "우리도 언젠가는 회원수 최대의 국내 1 위 포탈이 되어서 우리아이디로 모든 서비스를 쓰게 할거야" 라는 욕심이지요. 회사가 이익을 위한 욕심은 당연하지만, 잘못된 판단일 경우에 문제가 됩니다.


  1. 사실: 오픈아이디 기반에서, 아이디와 계정은 다릅니다.

    • 사실, 이 사실에 대한 확실한 이해가 기존의 관습적인 판단을 잘못된 것으로 보는 가장 결정적인 부분입니다. 기존에는 회원에게만 아이디가 부여되었습니다. 즉, 회원이 아니면 전혀 식별되지 않는 익명사용자였습니다. 하지만, 오픈아이디에서는 비회원(서비스에 계정이 없는 사람) 이라도 '식별가능한', '신분확인이 되는' 방문객이라는 새로운 사용자 패턴이 존재합니다. 이사람들은 처음 방문자이지만 식별이 되며, 이후 다시 방문시 재 식별됩니다. 이때 계정이라 함은, 반복적인 사용자에 대한 정보들로 규정한다면, 구지 명시적인 과정, 특히, 서비스 전용 아이디를 추가 발급하는 과정이 없이도, 계정이 생성될 수 있는 것입니다. 오히려, 회원이 더 쉽고 빠르게 늘어날 수 있는 것이지요. 그 핵심은 아이디와 계정이 다르다는 것입니다.
  2. 포탈 A 는 사용자를 늘리고, 사용량을 늘리는 것이 이익입니다.

    • 당연한 말이지요, 다만, 기존에는 사용자를 늘린다는 것이, 아이디 발급을 늘리는 것과 같았습니다. 하지만, Consumer 를 하게 되면, 구지 새로운 아이디를 만들지 않고도, 사용자가 이미 보유한 아이디로도 포탈 A 의 계정을 쉽게 만들 수 있습니다. 오히려, 실 사용자로 신뢰가 쌓일때 명시적인 계정을 부여함으로써 충성사용자 비율을 늘릴 수 있습니다. (물론, 허 사용자 수도 대외 지표용으로 의미가 있겠지만, 일종의 사기지요.)
    • 만일 포탈  A 가 Provider 만 고집한다면, 기껏 현재 회원 100 만 정도에 만족하는 것이고, 언젠가 1000 만이 될 날만 기다리는 것이 겠죠? 하지만  신규 아이디발급에 얶매이지 말고, Consumer 를 지원해서 엄청난 외부 사용자 기반 (AOL 6000 만, 국내 주요 포탈들 전체 회원기반)들의 유입을 열어준다면, 잠재적인 계정 증가로 훨씬 빨리 이어질 수 있습니다.
    • 결국, Consumer 를 지원하는 것이 오히려, 원하던 바데로 사용자, 회원을 늘리게 되는 것이지요.
  3. 포탈 A 와 CP 들간의 계정 연계가 점점 가속화 됩니다.

    1. 두 서비스간의 계정 연계에서 가장 큰 걸림돌은 항상 아이디 연동이었습니다. 기존에는 각자 내부 아이디만 고집했기 때문에, A 포탈의 아이디 a 가 CP 의 아이디 c 와 같다고 연계하거나, CP 에서 A 포탈의 계정 a 를 인식해 주는 것입니다. 흔희 중대형 포탈들은 시장에서 우월한 위치에 있기때문에 본인들이 편한 후자의 방식으로 결정합니다. 하지만, 이경우, CP 들은 여러 중대형 포탈에 납품(?) 하는 입장으로서 여러개의 아이디 시스템들을 인식/지원해 줘야하는 고통과 비용이 따릅니다. 물론, 회사이익 관점에서는 설득력 없는 사실일 뿐이구요. 
    2. 중요한 점은 Consumer 병행이 포탈 A 의 CP 연동 전략에 이익이 됩니다.
      그 이유는 이미 사용자가 오픈아이디라는 전서비스에 유일한 식별자를 보유하고 있기 때문에, Consumer 가 되어 이것을 인식해 준다면, 이 식별자를 통해서 포탈 A 와 CP 의 계정이 같은 아이디로 된 양쪽계정이 자연스럽게 연결됩니다. 미래에는 그 사용자가 이미 CP 에 계정이 있더라도 포탈 A 의 회원이 되면서 즉시 연결이 됩니다. 하지만, 포탈 A 가 자신만의 아이디를 고집한다면, 포탈 A 의 새로운 사용자는 반드시 먼저 포탈 A 에서 아이디를 발급받은 후에라야, CP 에 계정을 만들고 연계하게 되므로 양 서비스의 연계 속도가 떨어집니다.
    3. 확률적으로 보면  포탈 A 의 비회원이라도 이미 외부 대형 포탈의 회원으로 오픈아이디를 보유하고 있고, 또, CP 가 그 대형포탈과 이미 연계되어 있을 가능성이 크기 때문에, 포탈 A 는 사용자가 제시한 아이디로 인정하고 계정을 만든다면, 즉시 CP 의 그 사람 기존계정과 연계가 이루어 지는 것입니다. 게다가 덤으로, 어쩌면, CP 입장으로 상대하게 될지도 모르는 그 대형 포탈의 계정과도 연계가 된는 덤까지 얻는 것이지요.

위에서 저는 중대형 포탈이라도, 언젠가 독점하겠다는 헛된 욕심을 버리고, 오히려 외부 회원기반을 끌어드리는 Consumer 전략을 취하는 것이 훨씬 회원수를 늘릴 수 있다는 논리를 소개 드렸습니다. 물론, 여기에 큰 가정은, 앞으로 기존 대형 서비스들의 회원기반이 오픈아이디 보유자로 전환될 것이라는 점입니다. 이 부분은 이미, 다음을 시작으로 네이버의 적극 검토, 그리고 예상하건데 야후와 구글까지도 움직임이 있고 예상되고 있습니다.

회원기반이 좀 되는 중대형 포탈 관계자 분들 서비스의 회원기반을 더욱 늘리는 방법은, 내부 회원 아이디만 고집하는 것이 아니라, 외부의 회원기반을 끌어 안는 것입니다. Consumer 지원을 적극적으로 권장합니다.


- Kay -

권장표준스타일가이드

August 26th, 2008

OpenID 적용 사이트 (RP, Relying Party, Consumer) 의 사용자 인터페이스 권장 표준 스타일입니다.

OpenID 적용 사이트 권장/표준 스타일 가이드

오픈아이디의 강점은, 표준을 통해 사용자 중심 원칙을 확보하는 데 있습니다. 하지만, 결국, 표준을 업체들이 얼마나 준수해 주느냐에 따라 실제 사용자 경험상의 일관성이 구현된다고 생각합니다.
현재 스펙상의 프로토콜 표준은  따르지 않을 경우, 작동이 안되기 때문에 거의 지켜진다고 봅니다. 하지만, 지원서비스나 제공업체가 같이 지키면 좋을 Best Practice 같은 것은 그 가치를 알고 신경써서 지키지 않으면 쉽게 문제점이 드러나지 않는 것들, 결국, 사용자의 불편이나 불이익으로만 드러나는 것들이 있을 수 있습니다.
오픈마루에서는 내부서비스들의 인증 기반이 모두 오픈아이디이기때문에 이부분에 대해서 간단하지만 내부적으로 정리된 것이 좀 있어서 공유드리고, 함께 발전시켰으면 합니다.
여기 소개드리는 BP 는 거의 스펙 http://openid.net/specs.bml 에서 발췌된 것들입니다.

  • OpenID ID 입력폼 / 인증창

    • 스펙상 강제 사항은 아니지만, 사용자 경험상 매우 중요한 부분입니다.
    • 표준 스타일을 지킬 경우, 자동화된 툴의 혜택을 입을 수 있습니다.

    • 권장 UI: http://wiki.openid.net/OpenID_Login_Box

      1. <input type="text" name="openid_identifier" class="openid_login" />

        input.openid_login {
           background: url(http://openid.net/login-bg.gif) no-repeat;
           background-color: #fff;
           background-position: 0 50%;
           color: #000;
           padding-left: 18px;
        }
    • OpenID ID 입력콘트롤 표준 이름 (input name)

      • 'openid_identifier' (1.1 에서는 'openid_url' 이지만 현재 대부분 2.0 이름이 표준처럼 사용됩니다.)
      • 브라우저 자동 완성 등 automation 지원을 받을 수 있습니다.
      • myID.net jointsignup 이나, myopenid.com affiliate program 등을 활용하려면 필수입니다.
    • ID Canonicalization - 입력된 아이디의 정규화

      • 'http://' 등 문맥에 따라서 생략가능한 부분을 완성시켜 주어야 합니다.
      • 마지막으로 모든 서버쪽 redirection 을 따라간 최종 URL 을 claimed ID (제시 ID, 대표 ID) 로 사용합니다.
    • (보안) 전통적인 ID 와 password 를 함께 쓰는 폼을 지양합니다.

      • 특히, 기존 인증기반이 있는 서비스의 경우에, 로칼아이디와 오픈아이디를 한 입력란에 받는 UI 는 위험한 패턴입니다.
      • 오픈아이디 본질상, ID 입력과 인증(password 입력등) 이 분리되는 것을 사용자에게 학습시켜야 합니다.
      • 이러한 UI 는 피싱사이트로 오해받을 수 있습니다.
      • 서비스는 기존 서비스전용 ID 로그인과 OpenID 로그인을 함께 지원할 수 있으며, 이경우 아래와 같이 분리된 폼을 제공합니다.

      • goodlogin(1).PNG
    • (보안) 인증제공자의 페이지는 반드시 URL 이 확인되도록 해야 합니다.

      • IDP 인증폼의 URL 은 반드시 사용자에게 보여지도록 해야 합니다.
      • iframe, 약식-새창, layer 등으로 인증 URL 이 감추어 지면 안됩니다.
      • 이러한 UI 녁시 피싱사이트로 오해받을 수 있습니다.

       

    • 블로그 댓글 등에 표시할 때

      • 오픈아이디 로그인 폼과, 익명 폼을 분리합니다. 특히, 아이디/비번의 아이디를 혼용하지 않습니다.

        • openidcomment.PNG
      • 글쓴이 아이덴티티 표시할 때, 인증된 오픈아이디와 익명 글쓴이를 명확히 구분합니다.

        • 특히, 오픈아이디 로고는 반드시 인증된 오픈아이디 앞에만 달도록 합니다. (if and only if)
        • badcomment.PNG
<< 이전 글