20. Deprecated - iFun Authenticator

Attention

본 문서에서 설명하는 iFun Authenticator 를 이용한 인증 검증 기능은 Deprecated 되어 제거될 예정입니다. 외부 서비스 지원 Part 1: 인증 검증 에서 설명하는 각 플랫폼별 인증 검증 기능을 사용하시기 바랍니다.

Facebook, Google Plus 등의 외부 플랫폼을 이용한다면 유저 인증을 수행하기 위해서는 Client-side, Server-side 두 단계 인증 구현이 필요합니다. 게임 클라이언트에서 해당 플랫폼의 SDK를 이용하여 인증을 수행하고, 인증 사실을 식별 할 수 있는 키를 게임 서버로 전송 후 게임 서버에서 키의 유효성 검사를 수행하는 것입니다.

대부분의 플랫폼은 클라이언트 측 인증만 제공할뿐 서버 측 인증은 제공하지 않습니다. 그 때문에 연동하는 플랫폼이 늘어날 수록 서버 개발자에게는 큰 부담이 됩니다. 아이펀 엔진은 주요 플랫폼과의 Server-side 인증 기능과 친구목록, 닉네임 등을 불러오는 기능을 제공합니다.

20.1. iFun Authenticator

아이펀 엔진은 인증을 전담하는 agent 로서 iFun Authenticator 라는 프로그램을 사용합니다. 게임 서버는 iFun Authenticator 에 인증 검증 요청을 전달하고, iFun Authenticator 가 실제 플랫폼별 검증 과정을 거치게 됩니다.

Note

아이펀 엔진이 별도의 인증 agent 를 사용하는 것은 게임 서버에 영향을 주지 않고 새로운 인증의 추가나 변경을 가능하게 하기 위해서입니다.

또한 agent 를 이용하면 게임 서버가 아닌 다른 서버 역시 agent 의 REST API 를 통해 인증 관련된 서비스를 이용할 수 있어 편리합니다.

20.1.1. 지원 플랫폼

다음과 같은 외부 플랫폼 인증을 지원합니다. (지원 가능한 외부 플랫폼은 향후 지속적으로 추가될 예정입니다.)

  • Facebook
  • Twitter
  • Google+
  • Nexon Toy

20.1.2. 설치 방법

Tip

게임 서버 측 인증 검증 설정 파라미터use_authenticatorfalse 로 설정하면 게임 서버는 모든 인증 검증 요청을 통과하는 것으로 가정하는 테스트 모드로 동작합니다. 실제인증이 필요없는 개발 초기단계에 유용한 설정이며, 이 경우에는 iFun Authenticator 를 설치할 필요가 없습니다.

20.1.2.1. Ubuntu 인 경우

$ sudo apt-get update
$ sudo apt-get install funapi-authenticator1

20.1.2.2. CentOS 인 경우

$ sudo yum install funapi-authenticator1

20.1.3. 실행 방법

20.1.3.1. Ubuntu 14.04 혹은 Centos 6 인 경우

/etc/default/funapi-authenticator 파일을 열어, enabled=1 로 수정합니다.

그리고 다음 명령을 실행합니다.

$ sudo service funapi-authenticator start

20.1.3.2. Ubuntu 16.04 혹은 CentOS 7 인 경우

다음 명령을 실행합니다.

$ sudo systemctl enable funapi-authenticator
$ sudo systemctl start funapi-authenticator

20.1.4. 동작 확인

20.1.4.1. Ubuntu 14.04 혹은 Centos 6 인 경우

$ sudo service funapi-authenticator status

20.1.4.2. Ubuntu 16.04 혹은 CentOS 7 인 경우

$ sudo systemctl status funapi-authenticator

20.1.4.3. Log 파일

/var/log/funapi/funapi-authenticator/ 에 로그를 생성합니다.

20.1.5. iFun Authenticator 설정 방법 (MANIFEST.json)

Note

이 항목은 iFun Authenticator 자체의 설정에 대한 내용입니다. iFun Authenticator 를 이용하는 게임 서버의 설정은 게임 서버 측 인증 검증 설정 파라미터 을 참고하세요.

iFun Authenticator 역시 아이펀 엔진으로 작성된 프로그램입니다. 따라서 iFun Authenticator 역시 MANIFEST.json 을 통해 설정값을 바꿀 수 있습니다. iFun Authenticator 의 MANIFEST.json 은 /usr/share/funapi-authenticator/default/manifests/MANIFEST.json 에 있습니다.

다음과 같은 설정 값을 지정할 수 있습니다.

  • tcp_listen_port: 아이펀 엔진 게임 서버가 iFun Authenticator 와 통신하는 TCP port 번호를 지정합니다. (type=uint16, default=12800)
  • http_listen_port: REST API 로 iFun Authenticator 와 통신하기 위한 HTTP port 번호를 지정합니다. (type=uint16, default=12801)
  • bypass: 인증 검증을 무조건 통과시킬지 여부입니다. iFun Authenticator 를 테스트 모드로 동작시킵니다. 아이펀 엔진 게임 서버에서 use_authenticator=false 로 지정한 것과 같은 효과를 냅니다. (type=bool, default=false)
  • ip_address_table_path: iFun Authenticator 에 요청을 보낼 수 있는 서버의 IP 주소를 나열한 테이블 파일의 경로를 지정합니다. /usr/share/funapi-authenticator/default/resources/ 로부터의 상대 경로로 지정해야됩니다. (type=string, default=”acl/ip_address_table”)

Tip

에이전트를 업데이트하게 되면 기존 MANIFEST.json 은 덮어씌여지게 됩니다. 이를 방지하기 위해서는 임시로 MANIFEST.json 오버라이드하기 에 언급된대로 override 파일을 사용할 수 있습니다.

/etc/funapi-authenticator/MANIFEST.override.json:

{
  "override": {
    "FunapiAuthenticatorServer": {
      "tcp_listen_port": 8070,
      "http_listen_port": 8080,
      ...
    },
    ...
  }
}

20.2. 인증 검증

아이펀 엔진이 제공하는 함수를 이용하는 방법과(이 경우 TCP 로 통신하게 됨) 독립적으로 RESTful API를 이용하는 방법이 있습니다.

20.2.1. 아이펀 엔진에서 함수를 호출하는 방식

아이펀 엔진은 플랫폼 종류에 상관없이 동일한 인증 요청 인터페이스를 제공합니다. 인증 요청은 동기와 비동기 방식 모두 제공되며 다음과 같습니다.

1
2
3
4
5
void Authenticate(const AccountAuthenticationRequest &request,
                  const AuthenticationResponseHandler &handler);

bool AuthenticateSync(const AccountAuthenticationRequest &request,
                      AccountAuthenticationResponse *response);
1
2
3
4
5
public static void Authenticate(Authentication.AccountAuthRequest request,
                                    Authentication.AuthResponseHandler handler);

public static bool AuthenticateSync(Authentication.AccountAuthRequest request,
                                        out Authentication.AccountAuthResponse response);

AccountAuthenticationRequest 객체를 생성하기 위해서는 다음과 같은 인자가 필요합니다.

1
2
3
AccountAuthenticationRequest(const string &service_provider,
                             const string &local_account,
                             const AuthenticationKey &key);
1
2
3
public AccountAuthRequest(string service_provider,
                          string local_account,
                          string auth_key);

각 인자에 대한 설명은 다음과 같습니다.

  • service_provider: 서비스 제공자를 지정하며 다음 인자 중 하나를 사용할 수 있습니다.
    • Facebook: Facebook 서비스
    • GooglePlus: Google+ 서비스
    • NexonToy: Nexon Toy 서비스
  • local_account: 사용자 계정을 판별할 수 있는 고유 식별자를 입력합니다. Facebook의 경우 uuid가 고유식별자가 될 수 있습니다.
  • key: 인증 정보를 담는 객체입니다. 플랫폼 별로 제공되는 다음 함수를 통해 생성할 수 있습니다.
1
2
3
4
5
6
7
8
9
AuthenticationKey MakeFacebookAuthenticationKey(const string &facebook_access_token)

AuthenticationKey MakeGooglePlusAuthenticationKey(const string &google_client_id,
                                                  const string &google_access_token)

AuthenticationKey MakeNexonToyAuthenticationKey(int64_t svc_id,
                                                const string &client_id,
                                                const string &np_sn,
                                                const string &np_token)
1
2
3
4
5
6
7
8
9
public static string MakeFacebookAuthKey(string facebook_access_token);

public static string MakeGooglePlusAuthKey(string google_client_id,
                                              string google_access_token);

public static string MakeNexonToyAuthKey(long svc_id,
                                             string client_id,
                                             string np_sn,
                                             string np_token);

Tip

보다 자세한 내용은 API 문서 를 참고하세요.

20.2.1.1. 예제: Facebook 인증 검증

Facebook 인증을 위해서 게임 클라이언트는 Facebook 인증 서버에 접속해 Facebook ID 와 패스워드를 입력하고, “access token” 이라는 것을 발급 받습니다. 이 access token 을 게임 클라이언트가 게임 서버로 전송하면, 게임 서버는 다음과 같은 방식으로 이 access token 이 유효한지 확인할 수 있습니다.

20.2.1.1.1. 동기 방식

아래처럼 AuthenticateSync() 을 사용합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void example(const string &fb_uid, const string &fb_access_token) {
  AuthenticationKey auth_key = MakeFacebookAuthenticationKey(access_token);

  // 아래는 인증 요청 정보를 만드는 것입니다.
  // 첫번째 인자는 인증 플랫폼 종류를 뜻합니다.
  AccountAuthenticationRequest req("Facebook", fb_uid, auth_key);
  AccountAuthenticationResponse rep;

  if (not AuthenticateSync(req, &rep)) {
    LOG(ERROR) << "authentication system error";
    return;
  }

  // 오류는 발생하지 않았지만, 인증 결과가 실패한 경우입니다.
  // 클라이언트가 가짜로 access token 을 만들어 보내는 경우 등이 포함됩니다.
  if (not rep.success) {
    LOG(INFO) << "login failed. code(" << rep.reason_code << "),"
              << "description(" << rep.reason_description << ")";
    return;
  }

  LOG(INFO) << "login success";
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 클라이언트로부터 Facebook uid 와 access_token 을 전송 받았다고 가정하겠습니다.
public void Example(string fb_uid, string fb_access_token)
{
  string auth_key =
      Authentication.MakeFacebookAuthKey (fb_access_token);

  // 아래는 인증 요청 정보를 만드는 것입니다.
  // 첫번째 인자는 인증 플랫폼 종류를 뜻합니다.
  Authentication.AccountAuthRequest req =
      new Authentication.AccountAuthRequest (
          "Facebook", fb_uid, auth_key);
  Authentication.AccountAuthResponse rep;

  if (!Authentication.AuthenticateSync (req, out rep))
  {
    Log.Error ("authentication system error");
    return;
  }

  if (!rep.Success)
  {
    Log.Info ("login failed. code({0}), description({1})",
              rep.ReasonCode, rep.ReasonDescription);
    return;
  }

  Log.Info ("login success");
}
20.2.1.1.2. 비동기 방식

아래처럼 Authenticate() 을 사용합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void OnLogin(
    const string &fb_uid,
    const AccountAuthenticationRequest &request,
    const AccountAuthenticationResponse &response,
    const bool &error) {
  // 인증 서버에서 오류가 발생한 경우입니다.
  if (error) {
    LOG(ERROR) << "authentication system error";
    return;
  }

  // 오류는 발생하지 않았지만, 인증 결과가 실패한 경우입니다.
  // 클라이언트가 가짜로 access token 을 만들어 보내는 경우 등이 포함됩니다.
  if (not response.success) {
    LOG(INFO) << "login failed. code(" << response.reason_code << "),"
              << "description(" << response.reason_description << ")";
    return;
  }

  LOG(INFO) << "login success: " << fb_uid;
}


void example(const string &fb_uid, const string &fb_access_token) {
  AuthenticationKey auth_key = MakeFacebookAuthenticationKey(access_token);

  // 인증 종류에 상관없이 아이펀 엔진은 단일한 인증 요청 인터페이스를 이용합니다.
  // 아래는 인증 요청 정보를 만드는 것입니다.
  AccountAuthenticationRequest req("Facebook", fb_uid, auth_key);

  AuthenticationResponseHandler callback = bind(&OnLogin, fb_uid, _1, _2, _3);

  Authenticate(request, callback);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public void OnLogin(
    string fb_uid,
    Authentication.AccountAuthRequest request,
    Authentication.AccountAuthResponse response,
    bool error)
{
  if (error)
  {
    Log.Error ("authentication system error");
    return;
  }

  if (!response.Success)
  {
    Log.Info ("login failed. code({0}), description({1})",
              response.ReasonCode, response.ReasonDescription);
    return;
  }

  Log.Info ("login success");
}

public void Example(string fb_uid, string fb_access_token)
{
  string auth_key =
      Authentication.MakeFacebookAuthKey (fb_access_token);

  // 인증 종류에 상관없이 아이펀 엔진은 단일한 인증 요청 인터페이스를 이용합니다.
  // 아래는 인증 요청 정보를 만드는 것입니다.
  Authentication.AccountAuthRequest req = new
      Authentication.AccountAuthRequest ("Facebook", fb_uid, auth_key);

  Authentication.Authenticate (
      req,
      (Authentication.AccountAuthRequest request,
       Authentication.AccountAuthResponse response,
       bool error) => {
    OnLogin(fb_uid, request, response, error);
  });

  // 아니면 아래처럼 delegate를 이용하여 콜백 핸들러를 등록할 수도 있습니다.
  // Authentication.AuthResponseHandler handler = (
  //     Authentication.AccountAuthRequest request,
  //     Authentication.AccountAuthResponse response,
  //     bool error) =>
  // {
  //   ...
  // };
  // Authentication.Authenticate (req, handler);
}

20.2.2. REST API 를 이용하는 방식

아이펀 엔진을 이용하지 않고 iFun Authenticator 에게 직접 REST API 를 요청할 수 있습니다. 아래 명세에 따라 각 parameter 들을 JSON format 으로 HTTP POST 의 body 에 담아 요청을 하면 됩니다.

20.2.2.1. Test 인증

Test 인증에서는 모든 id 값이 인증에 성공합니다

POST /v1/authentication/test
Request JSON Object:
 
  • player_id (string) – player_id
Response JSON Object:
 
  • result (integer) –
    • 0: 인증 성공
    • 1: 인증 실패
    • 2: 파라미터 오류
    • 그 외: 기타 오류
  • description (string) – 오류 설명

20.2.2.2. Facebook 플랫폼 인증

POST /v1/authentication/facebook
Request JSON Object:
 
  • player_id (string) – Facebook uid
  • access_token (string) – Facebook access token
Response JSON Object:
 
  • result (integer) –
    • 0: 인증 성공
    • 1: 인증 실패
    • 2: 파라미터 오류
    • 그 외: 기타 오류
  • description (string) – 오류 설명
20.2.2.2.1. 예제: Facebook 인증 검증
$ curl -X POST --data '{"player_id": "123...456", "access_token": "CAAC....tDZD"}' \
       http://localhost:12801/v1/authentication/facebook
{"result": 0, "description": ""}

20.2.2.3. IP 기준 인증

POST /v1/authentication/ipaddress
Request JSON Object:
 
  • player_id (string) – ip 인증에서는 어떠한 id 값도 인증에 성공합니다.
  • ip (string) – IP address
Response JSON Object:
 
  • result (integer) –
    • 0: 인증 성공
    • 1: 인증 실패
    • 2: 파라미터 오류
    • 그 외: 기타 오류
  • description (string) – 오류 설명

20.3. 친구 리스트 추출

아이펀 엔진이 제공하는 함수를 이용하는 방법과(이 경우 TCP 로 통신하게 됨) 독립적으로 RESTful API를 이용하는 방법이 있습니다.

20.3.1. 아이펀 엔진에서 함수 호출하는 방식

플랫폼 종류에 상관없이 아이펀 엔진은 단일한 친구 리스트 요청 인터페이스를 이용합니다. 다음 두 함수를 활용합니다. 각각 비동기, 동기 함수입니다.

void fun::GetPersonalInfo(const AccountPersonalInfoRequest &request,
                          const PersonalInfoResponseHandler &handler)

bool fun::GetPersonalInfoSync(const AccountPersonalInfoRequest &request,
                              AccountPersonalInfoResponse *response)

이 때 플랫폼 종류별로 AccountPersonalInfoRequest 을 생성하는 방식만 달라집니다. 이를 위해 플랫폼별로 다음의 유틸리티 함수가 제공됩니다.

AuthenticationKey MakeFacebookAuthenticationKey(const string &facebook_access_token)

AuthenticationKey MakeGooglePlusAuthenticationKey(const string &google_client_id,
                                                  const string &google_access_token)

AuthenticationKey MakeNexonToyAuthenticationKey(int64_t svc_id,
                                                const string &client_id,
                                                const string &np_sn,
                                                const string &np_token)

Tip

보다 자세한 내용은 API 문서 를 참고하세요.

20.3.1.1. 예제: Facebook 친구 추출

20.3.1.1.1. 동기 방식

아래처럼 GetPersonInfoSync() 을 사용합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void example(const string &fb_uid, const string &fb_access_token) {
  AuthenticationKey auth_key = MakeFacebookAuthenticationKey(access_token);

  // 사용자 정보 요청 메시지를 만듭니다.
  // 첫번째 인자는 외부 인증 종류를 의미합니다.
  AccountPersonalInfoRequest req("Facebook", fb_uid, auth_key);
  AccountPersonalInfoResponse rep;

  if (not GetPersonalInfoSync(req, &rep)) {
    LOG(ERROR) << "authentication system error";
    return;
  }

  // 오류는 발생하지 않았지만, 요청이 실패한 경우입니다.
  // 클라이언트가 가짜로 access token 을 만들어 보내는 경우 등이 포함됩니다.
  if (not rep.success) {
    LOG(INFO) << "request failed. code(" << rep.reason_code << "),"
              << "description(" << rep.reason_description << ")";
    return;
  }

  for (int i = 0; i < rep.friends.size(); ++i) {
    LOG(INFO) << "friend : " << rep.friends[i].id();
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public void Example(string fb_uid, string fb_access_token)
{
  string auth_key =
      Authentication.MakeFacebookAuthKey (fb_access_token);

  // 사용자 정보 요청 메시지를 만듭니다.
  // 첫번째 인자는 외부 인증 종류를 의미합니다.
  Authentication.AccountPersonalInfoRequest req =
      new Authentication.AccountPersonalInfoRequest (
          "Facebook", fb_uid, auth_key);

  Authentication.AccountPersonalInfoResponse rep;

  if (!Authentication.GetPersonalInfoSync(req, out rep))
  {
    Log.Error ("authentication system error");
    return;
  }

  // 오류는 발생하지 않았지만, 요청이 실패한 경우입니다.
  // 클라이언트가 가짜로 access token 을 만들어 보내는 경우 등이 포함됩니다.
  if (!rep.Success) {
    Log.Info ("login failed. code({0}), description({1})",
              rep.ReasonCode, rep.ReasonDescription);
    return;
  }

  foreach (PlayerAccount account in rep.Friends)
  {
    Log.Info (account.Id);
  }
}
20.3.1.1.2. 비동기 방식

위의 예제에서 GetPersonInfoSync() 대신 GetPersonInfo() 을 사용합니다.

20.3.2. REST API 를 이용하는 방식

아이펀 엔진을 이용하지 않고 iFun Authenticator 에게 직접 REST API 를 요청할 수 있습니다. 아래 명세에 따라 각 parameter 들을 JSON format 으로 HTTP POST 의 body 에 담아 요청을 하면 됩니다.

20.3.2.1. Test 인증

POST /v1/personalinfo/test
Request JSON Object:
 
  • player_id (string) – id, test 인증에서는 어떠한 id 값도 인증에 성공합니다.
Response JSON Object:
 
  • result (integer) –
    • 0: 성공
    • 1: 인증 실패
    • 2: 파라미터 오류
    • 그 외: 기타 오류
  • description (string) – 오류 설명
  • friends (string[]) – 친구 목록

20.3.2.2. Facebook 플랫폼

POST /v1/personalinfo/facebook
Request JSON Object:
 
  • player_id (string) – Facebook uid
  • access_token (string) – Facebook access token
Response JSON Object:
 
  • result (integer) –
    • 0: 성공
    • 1: 인증 실패
    • 2: 파라미터 오류
    • 그 외: 기타 오류
  • description (string) – 오류 설명
  • friends (string[]) – 친구 목록
20.3.2.2.1. 예제: Facebook 친구목록 받아오기
$ curl -X POST --data '{"player_id": "123...456", "access_token": "CAAC....tDZD"}' \
       http://localhost:12801/v1/personalinfo/facebook
{"result": 0, "description": "", "friends": ["xx...x", "xx...x", ...,"xx...x"]}

20.4. 게임 서버 측 인증 검증 설정 파라미터

Note

이 설정 파라미터는 iFun Authenticator 를 사용하는 아이펀 엔진 게임 서버의 값입니다. iFun Authenticator 자체의 설정 파라미터는 iFun Authenticator 설정 방법 (MANIFEST.json) 를 참고하세요.

  • use_authenticator: iFun Authenticator agent 와의 통신을 활성화시킬지 여부. 만일 false 이면 모든 검증 과정을 bypass 하고 성공으로 간주함. (type=bool, default=false)
  • remote_authenticator_ip_address: iFun Authenticator 가 돌고 있는 원격 호스트의 IP 주소. (type=string, default=”0.0.0.0”)
  • remote_authenticator_port: iFun Authenticator 가 돌고 있는 원격 호스트의 포트 번호. (type=uint64, default=0)