로그인 플로 직접 빌드

네이티브 데스크톱 앱(예: Windows 8)의 웹 보기나 완전히 서버 측 코드를 사용하는 로그인 플로처럼 Facebook SDK를 사용하지 않는 웹 또는 데스크톱 앱용 브라우저 기반 로그인의 경우 브라우저 리디렉션을 사용하여 직접 로그인 플로를 빌드할 수 있습니다. 이 가이드에서는 로그인 플로의 각 단계를 설명하고 Facebook SDK를 사용하지 않고 각 단계를 구현하는 방법을 보여드립니다.

데스크톱 앱에서 Facebook 로그인을 사용하려면 로그인 절차를 실행할 수 있는 웹 브라우저('웹 보기'라고도 함)를 앱 내에 포함(embed)할 수 있어야 합니다.

로그인 상태 확인

Facebook SDK를 사용하는 앱은 누군가가 내장된 기능을 사용하여 이미 로그인했는지 확인할 수 있습니다. 그 외에 다른 모든 앱은 사용자가 로그인하는 시점을 저장하는 수단을 직접 구현해야 하고, 이 지표가 없는 경우에는 사용자가 로그아웃했다고 가정하고 처리해야 합니다. 사용자가 로그아웃한 경우 적절한 타이밍에 앱에서 로그인 대화 상자로 리디렉션해야 합니다(예: 로그인 버튼을 클릭한 경우).

사용자 로그인 유도

사용자가 앱에 로그인하지 않았거나 Facebook에 로그인하지 않은 경우 로그인 대화 상자를 사용하여 앱과 Facebook에 모두 로그인하도록 메시지를 표시할 수 있습니다. Facebook에 로그인하지 않은 경우 먼저 Facebook에 로그인하도록 메시지를 표시한 다음, 앱에 로그인하도록 합니다. 이는 자동으로 탐지되므로 이 동작을 활성화하기 위해 추가 작업을 할 필요가 없습니다.


로그인 대화 상자 호출 및 리디렉션 URL 설정

앱이 엔드포인트로의 리디렉션을 시작하면 로그인 대화 상자가 표시됩니다.

https://www.facebook.com/v21.0/dialog/oauth?
  client_id={app-id}
  &redirect_uri={redirect-uri}
  &state={state-param}

이 엔드포인트에는 다음과 같은 필수 매개변수가 있습니다.

  • client_id. 앱 대시보드에서 발견되는 앱의 ID입니다.
  • redirect_uri. 사용자가 다시 로그인하도록 리디렉션할 URL입니다. 이 URL은 로그인 대화 상자의 응답을 캡처합니다. 데스크톱 앱의 웹 보기에서 로그인 대화 상자를 사용할 경우 https://www.facebook.com/connect/login_success.html로 설정해야 합니다. 앱 대시보드에서 앱에 이 URL이 설정되어 있는지 확인할 수 있습니다. 앱 대시보드의 왼쪽 탐색 메뉴에 있는 제품에서 Facebook 로그인을 클릭한 다음, 설정을 클릭합니다. 클라이언트 OAuth 설정 섹션에서 유효한 OAuth 리디렉션 URI를 인증합니다.
  • state. 요청과 콜백 사이의 상태를 유지하기 위해 앱에서 생성한 문자열 값입니다. 이 매개변수는 사이트 간 요청 위조를 방지하는 데 사용해야 하며 리디렉션 URI에서 변경 없이 그대로 다시 전달됩니다.

예를 들어 다음과 같은 로그인 요청이 있을 경우:

https://www.facebook.com/v21.0/dialog/oauth?
  client_id={app-id}
  &redirect_uri={"https://www.domain.com/login"}
  &state={"{st=state123abc,ds=123456789}"}

다음 요청으로 리디렉션 URI가 호출됩니다.

https://www.domain.com/login?state="{st=state123abc,ds=123456789}"
    

또한 다음과 같은 선택적 매개변수를 보유합니다.

  • response_type. 앱으로 다시 리디렉션할 때 포함된 응답 데이터가 URL 매개변수인지 프래그먼트인지 결정합니다. 앱에서 사용할 유형을 선택하려면 ID 확인 섹션을 참조하세요. 다음 중 하나일 수 있습니다.
    • code. 응답 데이터는 URL 매개변수로 포함되어 있으며, code 매개변수(각 로그인 요청에 고유한 암호화된 문자열)를 포함합니다. 이 매개변수가 지정되지 않은 경우의 기본 동작입니다. 이는 서버가 토큰을 처리할 때 가장 유용합니다.
    • token. 응답 데이터는 URL 프래그먼트로 포함되어 있으며, 액세스 토큰을 포함합니다. 데스크톱 앱은 response_type에 이 설정을 사용해야 합니다. 이는 클라이언트가 토큰을 처리할 때 가장 유용합니다.
    • code%20token. 응답 데이터는 URL 프래그먼트로 포함되어 있으며, 액세스 토큰과 code 매개변수를 모두 포함합니다.
    • granted_scopes. 사용자가 로그인 시점에 앱에 부여한 모든 권한의 쉼표로 구분한 리스트를 반환합니다. 다른 response_type 값과 결합할 수 있습니다. token과 결합하면 응답 데이터가 URL 프래그먼트로 포함됩니다. 그 외의 경우에는 URL 매개변수로 포함됩니다.
  • scope. 앱 사용자에게 요청할 권한의 쉼표 또는 공백으로 구분한 리스트입니다.
Windows 8 앱의 경우

Windows 앱을 위한 로그인을 빌드할 경우 패키지 보안 식별자redirect_uri로 사용할 수 있습니다. WebAuthenticationBroker.AuthenticateAsync를 호출하여 로그인 대화 상자를 트리거하고 로그인 대화 상자 엔드포인트를 requestUri로 사용합니다. JavaScript의 예는 다음과 같습니다.

var requestUri = new Windows.Foundation.Uri(
  "https://www.facebook.com/v21.0/dialog/oauth?
    client_id={app-id}
    &display=popup
    &response_type=token
    &redirect_uri=ms-app://{package-security-identifier}");

Windows.Security.Authentication.Web.WebAuthenticationBroker.authenticateAsync(
  options,
  requestUri)
  .done(function (result) {
    // Handle the response from the Login Dialog
  }
);

성공 시 액세스 토큰을 포함하여 앱에 제어 플로를 반환하고 실패 시 오류를 반환합니다.

로그인 대화 상자 응답 처리

로그인 플로의 이 시점에서 사용자에게 로그인 대화 상자가 표시되고 로그인을 취소할지. 앱에 데이터 액세스를 허용할지 선택할 수 있습니다.

앱 사용자가 로그인 대화 상자에서 확인을 선택하면 공개 프로필, 친구 리스트 및 앱에서 요청한 추가 권한에 액세스를 허용하게 됩니다.

어느 쪽을 선택하든 브라우저가 앱으로 돌아가고 사용자가 연결했는지 취소했는지 나타내는 응답 데이터가 포함됩니다. 앱이 위와 같이 리디렉션 메서드를 사용할 경우 앱이 반환하는 redirect_uri가 (선택된 response_type에 따라) URL 매개변수 또는 프래그먼트와 함께 첨부되며, 이를 캡처해야 합니다.

웹 앱에서는 여러 가지 조합으로 코드 언어를 사용할 수 있기 때문에 이 가이드에서는 구체적인 예를 제시하지 않습니다. 그러나 대부분의 최신 언어는 다음과 같이 URL 파싱이 가능합니다.

클라이언트 측 JavaScript는 URL 프래그먼트(예: jQuery BBQ)를 캡처할 수 있지만 URL 매개변수는 클라이언트 측과 서버 측 코드(예: PHP의 $_GET, jQuery BBQ의 jQuery.deparam, Node.js의 querystring.parse 또는 Python의 urlparse)에서 모두 캡처할 수 있습니다. Microsoft는 '온라인 제공자'(이 경우 Facebook)에 연결하는 Windows 8 앱용 가이드와 샘플 코드를 제공합니다.

데스크톱 앱을 사용하여 로그인하는 경우 Facebook은 위에서 언급한 redirect_uri로 사용자를 리디렉션하고 URI 프래그먼트에 액세스 토큰과 다른 메타데이터(예: 토큰 만료 시간)를 배치합니다.

https://www.facebook.com/connect/login_success.html#
    access_token=ACCESS_TOKEN...

앱은 이 리디렉션을 탐지한 다음, 개발자가 사용하는 OS와 개발 프레임워크에서 제공하는 메커니즘으로 URI에서 액세스 토큰을 읽어야 합니다. 그러면 액세스 토큰 검사 단계로 바로 건너뛸 수 있습니다.


취소된 로그인

앱 사용자가 로그인 대화 상자를 수락하지 않고 취소를 클릭하면 다음으로 리디렉션됩니다.

YOUR_REDIRECT_URI?
 error_reason=user_denied
 &error=access_denied
 &error_description=Permissions+error.

사용자가 로그인을 거부한 경우 앱에서 취해야 할 조치에 대한 자세한 내용은 누락된 권한 처리를 참조하세요.

ID 확인

이 리디렉션 플로에는 로그인 대화 상자에서 브라우저가 앱의 URL로 리디렉션되는 과정이 포함되므로 트래픽이 위조된 프래그먼트 또는 매개변수로 이 URL에 직접 액세스할 수 있습니다. 앱에서 이를 유효한 매개변수라고 판단한 경우 앱에서 위조된 데이터가 잠재적인 악의적 목적으로 사용될 수 있습니다. 따라서 앱은 액세스 토큰을 생성하기 전에 앱 사용자가 응답 데이터를 보낸 사람과 동일 인물인지 확인해야 합니다. ID는 위에서 수신한 response_type에 따라 다양한 방식으로 확인할 수 있습니다.

  • code를 수신하면 엔드포인트를 사용하여 액세스 토큰과 교환해야 합니다. 호출에는 앱 시크릿 코드가 포함되므로 서버 간 호출이어야 합니다. (앱 시크릿 코드는 절대 클라이언트 코드에 들어가서는 안 됩니다.)
  • token을 수신한 후 인증해야 합니다. 토큰을 생성할 대상 사용자와 대상 앱을 표시하도록 검사 엔드포인트로 API 호출을 보내야 합니다. 이 API 호출은 앱 액세스 토큰을 사용해야 하므로 절대 클라이언트에서 이 호출을 보내지 마세요. 대신 앱 시크릿 코드를 안전하게 저장할 수 있는 서버에서 이 호출을 보내세요.
  • codetoken을 모두 수신했을 때는 두 단계를 모두 실행해야 합니다.

또한 자체 state 매개변수를 생성하고 이를 로그인 요청에 사용하여 CSRF 보호를 제공할 수 있습니다.

액세스 토큰을 위한 코드 교환

액세스 토큰을 받으려면 다음 OAuth 엔드포인트로 HTTP GET 요청을 보내세요.

GET https://graph.facebook.com/v21.0/oauth/access_token?
   client_id={app-id}
   &redirect_uri={redirect-uri}
   &client_secret={app-secret}
   &code={code-parameter}

이 엔드포인트에는 몇 가지 필수 매개변수가 있습니다.

  • client_id. 앱 ID입니다.
  • redirect_uri. 이 인수는 필수이며 OAuth 로그인 절차를 시작할 때 사용하는 원본 request_uri와 동일해야 합니다.
  • client_secret. 고유한 앱 시크릿 코드이며, 앱 대시보드에 표시됩니다. 클라이언트 측 코드나 역컴파일이 가능한 바이너리에 이 앱 시크릿 코드를 절대 포함하지 마세요. 앱 시크릿 코드는 앱과 모든 앱 사용자를 보호하는 보안 핵심이므로 철저히 기밀로 유지하는 것이 극히 중요합니다.
  • code. 위의 로그인 대화 상자 리디렉션에서 수신한 매개변수입니다.

참고: v2.3부터 이 엔드포인트는 적절한 JSON 응답을 반환합니다. 호출 시 버전을 지정하지 않으면 가장 오래된 가용 버전이 기본으로 설정됩니다.

응답

이 엔드포인트에서 받은 응답은 다음과 같이 JSON 형식으로 반환됩니다(성공 시).

{
  "access_token": {access-token}, 
  "token_type": {type},
  "expires_in":  {seconds-til-expiration}
}

성공하지 않은 경우 설명이 포함된 오류 메시지를 수신하게 됩니다.

액세스 토큰 검사

앱이 code 또는 token을 로그인 대화 상자의 response_type으로 사용하는지 여부와 관계없이 액세스 토큰을 수신합니다. 그래프 API 엔드포인트를 사용하여 이러한 토큰에 대한 자동 검사를 수행할 수 있습니다.

GET graph.facebook.com/debug_token?
     input_token={token-to-inspect}
     &access_token={app-token-or-admin-token}

이 엔드포인트는 다음과 같은 매개변수를 사용합니다.

  • input_token. 검사해야 할 토큰입니다.
  • access_token. 앱 개발자의 액세스 토큰 또는 앱 액세스 토큰입니다.

API 호출에 대한 응답은 검사된 토큰에 대한 데이터를 포함하는 JSON 배열입니다. 예를 들면 다음과 같습니다.

{
    "data": {
        "app_id": 138483919580948, 
        "type": "USER",
        "application": "Social Cafe", 
        "expires_at": 1352419328, 
        "is_valid": true, 
        "issued_at": 1347235328, 
        "metadata": {
            "sso": "iphone-safari"
        }, 
        "scopes": [
            "email", 
            "publish_actions"
        ], 
        "user_id": "1207059"
    }
}

app_iduser_id 필드를 통해 앱에서 사용자와 앱에 유효한 액세스 토큰을 확인할 수 있습니다. 기타 필드에 대한 전체 설명은 액세스 토큰에 대한 정보 가져오기 가이드를 참조하세요.

권한 확인

/me/permissions 에지는 특정 사용자가 부여하거나 거부한 권한의 리스트를 검색하기 위해 호출할 수 있습니다. 앱은 이를 사용하여 요청된 권한 중 특정 사용자에게 사용할 수 없는 권한을 확인할 수 있습니다.

거부된 권한 다시 요청

Facebook 로그인은 사용자가 앱과 권한을 공유하는 것을 거부할 수 있는 기능을 제공합니다. 로그인 대화 상자의 화면은 다음과 같습니다.

public_profile 권한은 항상 필요하고 비활성화할 수 없으므로 회색으로 표시됩니다.

그러나 이 예에서 사용자가 user_likes(좋아요)를 선택 취소하는 경우 /me/permissions에서 부여된 권한을 확인하면 다음과 같은 결과가 생성됩니다.

{
  "data":
    [
      {
        "permission":"public_profile",
        "status":"granted"
      },
      {
        "permission":"user_likes",
        "status":"declined"
      }
    ]
}

user_likes 권한이 부여되지 않고 거부되었습니다.

거부된 앱 권한을 다시 요청할 수 있습니다. 사용자가 권한을 부여해야 하는 이유에 대한 설명이 포함된 화면을 사용자에게 표시하고 다시 요청해야 합니다. 하지만 이전처럼 로그인 대화 상자를 호출할 경우 해당 권한을 요청하지 않습니다.

사용자가 거부했던 권한이므로 개발자가 거부된 권한을 다시 요청한다는 점을 대화 상자에 명시적으로 알리지 않는 한 로그인 대화 상자에서 해당 권한을 다시 요청하지 않습니다.

이렇게 하려면 auth_type=rerequest 매개변수를 로그인 대화 상자 URL에 추가하면 됩니다.

https://www.facebook.com/v21.0/dialog/oauth?
    client_id={app-id}
    &redirect_uri={redirect-uri}
    &auth_type=rerequest
    scope=email
   

이 방법으로 로그인 대화 상자에서 거부된 권한을 다시 요청합니다.

액세스 토큰 및 로그인 상태 저장

로그인 플로의 이 단계에 도달하면 사용자가 인증을 받고 로그인한 상태가 됩니다. 앱은 사용자 대신 API 호출을 보낼 준비가 되었습니다. 이 작업을 수행하기 전에 사용자의 액세스 토큰과 로그인 상태를 저장해야 합니다.

액세스 토큰 저장

앱에서 이전 단계의 액세스 토큰을 수신한 후에는 API 호출 시 앱의 모든 부분에서 이 토큰을 사용할 수 있도록 저장해야 합니다. 이와 관련된 특정 프로세스는 없으나 일반적으로 웹 앱을 빌드하고 있는 경우 특정 사용자의 해당 브라우저 세션을 식별하기 위한 세션 변수로 토큰을 추가하는 것이 좋습니다. 네이티브 데스크톱 또는 모바일 앱을 빌드하려면 앱에 제공되는 데이터스토어를 사용해야 합니다. 또한 앱은 user_id와 함께 데이터베이스에 토큰을 저장하여 식별해야 합니다.

액세스 토큰 문서의 액세스 토큰 크기에 대한 내용을 확인하세요.

로그인 상태 추적

마찬가지로 앱은 사용자의 로그인 상태를 저장해야 합니다. 그러면 로그인 대화 상자에 추가 호출을 보내지 않아도 됩니다. 어떤 절차를 선택하든 로그인 상태 확인을 수정하여 이를 반영해야 합니다.

사용자 로그아웃 유도

어떤 로그인 상태 지표를 추가했든 이를 취소하여 사용자의 로그아웃을 유도할 수 있습니다. 예를 들어 사용자가 로그인되었음을 나타내는 세션을 삭제합니다. 또한 저장된 액세스 토큰도 삭제해야 합니다.

사용자를 로그아웃시키는 것은 로그인 권한을 취소하는 것(이전에 부여된 인증 삭제)과는 다릅니다. 이 작업은 별도로 실행할 수 있습니다. 따라서 로그아웃한 사용자가 자동으로 로그인 대화 상자로 이동하지 않도록 앱을 빌드하세요.

사용자가 앱 제거 시 탐지

사용자는 앱 자체와 상호작용하지 않고도 Facebook.com에서 앱을 제거할 수 있습니다. Facebook에서는 앱이 이를 감지하는 데 도움이 되도록 앱 삭제가 발생할 때마다 핑으로 보내는 승인 취소 콜백 URL을 제공할 수 있도록 합니다.

앱 대시보드를 통해 승인 취소 콜백을 활성화할 수 있습니다.

사용자 데이터 삭제 요청에 응답

사용자는 Facebook에서 수신한 자신의 모든 정보를 삭제하도록 앱에 요청할 수 있습니다. 이러한 요청에 대한 응답은 데이터 삭제 요청 콜백을 참조하세요.