커스텀 인증

기본적으로 모든 어플리케이션은 익명의 사용자가 접속 할 수 있으며 인증 메카니즘이 없어도 됩니다. Photon 은 Photon 어플리케이션에 대해 커스텀 인증을 구현할 수 있는 옵션을 제공 하고 있습니다. Photon의 커스텀 인증은 유연합니다. 이에 대해서 완전 개인화된 솔루션 뿐만 아니라 잘 알려진 제3자 인증 프로바이더를 지원 하고 있습니다.

  • Exit Games에서 호스트 하고 있는 페이스북 인증 프로바이더.튜토리얼을 확인 해 보세요
  • 커스텀 인증 프로바이더, 내가 호스트 할 수 도 있는 것으로 구축 합니다. Git 리포지토리의 인증 프로바이더에 구현에 대한 샘플을 제공 하고 있습니다. 리포지토리를 마음껏 살펴 보시고 요청을 저희에게 보내 주세요. GitHub 에서 소스를 볼 수 있습니다.

인증 흐름

다음 단계들에는 인증 프로세스의 일반적인 흐름을 설명하고 있습니다.

Photon Cloud: Custom Authentication Flow Diagram
커스텀 인증 흐름 다이어그램

  1. 인증 프로바이더가 사용할 정보와 인증에 필요한 데이터를 Connect() 할 때 같이 Photon 서버로 클라이언트가 전달 합니다.
  2. Photon 서버는 어플리케이션에 필요한 인증 프로바이더를 얻고 다음 단계중의 하나를 처리 합니다.
    • 인증 프로바이더 환경 설정을 찾았으면 -> 인증은 단계3에서 처리됩니다.
    • 인증 프로바이더 환경 설정을 찾지 못했으면 -> 어플리케이션 설정에 따라 클라이언트는 접속이 허용 또는 거부됩니다.
  3. Photon 서버는 Connect() 에서 전달된 인증 정보를 가지고 인증 프로바이더를 호출 합니다.
    • 인증 프로바이더가 온라인의 경우 -> 인증은 단계4로 처리됩니다.
    • 인증 프로바이더가 오프라인의 경우 -> 상응하는 프로바이더 설정에 따라 클라이언트가 접속 허용 또는 거부 됩니다.
  4. 인증 프로바이더는 인증 정보를 처리하고 Photon 서버로 결과를 리턴 해 줍니다.
  5. 인증 결과에 따라서 클라이언트는 성공적으로 인증 또는 거부 되게 될 것 입니다.

Photon Cloud 셋업

Photon 어프릴케이션 대시보드에서 모든 인증 프로바이더에 대하여 설정 할 수 있습니다. 어플리케이션 상세 페이지로 가서 커스텀 인증 섹션을 오픈 합니다.

커스텀 인증에 대해서 설정 할 때 적용될 때 까지 시간이 걸릴 수 있다는 것을 기억 해 주시기 바랍니다.

인증 프로바이더 추가

커스텀 인증 프로바이더에 대한 환경설정은 쉬우며 Photon 어플리케이션 대시보드에서 수 초 내에 완료 할 수 있습니다.

Photon Cloud: Custom Authentication Creation
커스텀 인증 프로바이더 생성

스크린샷에서 보이고 있는 것 처럼 인증 URL 을 입력 할 수 있고, 인증 서비스가 온라인이 아닌 경우와 또는 다른 이유에 의해서 동작 하지 않을 경우에 클라이언트를 거부할지 결정 할 수 있습니다. 추가적으로 선택적인 키/값 쌍을 추가하여 인증 서비스에 요청 마다 쿼리 스트링 파라미터에 전송 할 수 있도록 할 수 있습니다.

모법 사례는 대시보드에서 "sensitive" 로 설정하고 정적 키/값 쌍은 클라이언트에게 "보이지 않는"것으로 설정 하는 것 입니다. 예제:
  • API 공개 키로 실제 Photon 서버 중에서 오는 요청인지 확인 합니다.
  • 커스텀 인증의 API 버전은 앞으로 바뀌게 될 사항에 대해서 더 잘 처리하기 위하여 사용 합니다.

또한 설정된 인증 프로바이더 없이도 어플리케이션에 접속하는 익명의 클라이언트를 허용할지 거부할 지를 설정 할 수 있습니다.

기본적으로 허용하는 것으로 되어 있으며 초기에는 모든 클라이언트들이 어플리케이션에 인증여부에 관계없이 접속 할 수 있다는 것을 의미 합니다. Photon 어플리케이션 대시보드 어플리케이션 상세 페이지의 인증 섹션에서 체크 할 수 있습니다.

Photon Cloud: Custom Authentication, Allow Anonymous Clients
커스텀 인증을 이용한 익명 클라이언트의 접속 허용

인증 프로바이더의 변경 또는 삭제

어플리케이션 상세 페이지에서 기존의 인증 프로바이더를 편집 할 수 있습니다. 편집 양식에서 모든 설정을 변경하거나 인증 프로바이더 전체를 삭제 할 수 있습니다.

Photon Cloud: Custom Authentication Editing
기존 인증 프로바이더에 대한 변경 및 삭제

구현

이 섹션에서는 사용자의 커스텀 인증 솔루션만을 다루며 Photon 에서 제공된 바로 사용할 수 있는 페이스북 인증을 다루지 않습니다.

이 기능에 대해서 확인 하기 위해서는 서버측과 클라이언트 측에서 해야할 몇가지 일이 있습니다. 이 섹션이 서버와 클라이언트 두 관점을 다루기 위해서 두 주요 부분으로 분리되어진 이유이기도 합니다.

클라이언트 측

클라이언트 측에서 LoadBalancing API 는 커스텀 인증을 처리할 것 입니다 - 관련된 파라미터와 타겟 커스텀 인증 서비스를 한번 설정 해주기만 하면 됩니다. 설정이 완료되었으면 연결과 연속적인 오류를 처리 할 수 있습니다.

커스텀 인증 값들은 LoadBalancingClient 의 일부 입니다.AuthValues 를 다음과 같이 생성하고 설정 합니다:

lbClient.AuthValues = new AuthenticationValues();
lbClient.AuthValues.AuthType = CustomAuthenticationType.Custom;
lbClient.AuthValues.AddAuthParameter("user", user);
lbClient.AuthValues.AddAuthParameter("pass", pass);
//lbClient.AuthValues.UserId = userId; // this is required when you set UserId directly from client and not from web service

이 스니펫에서는 간결하게 하기 위해 인증 자격에 기반한 매우 간단한 패스워드로 선택 했습니다. 이 결과 쿼리 스트링은 다음과 같습니다:?user={user}&pass={pass} 일반적으로 자격증명은 값이 쌍으로 구성되어 있으며, 첫 번째 값은 유일한 식별자(userId, username, e-mail 등) 이며 다른 하나는 "진짜의 증명" (해시된 패스워드, 키, 시크릿, 토큰 등)입니다. 보안상의 이유로 패스워드를 일반 텍스트로 전송하는 것은 권장하지 않습니다. 만약 인증이 실패하게 되면 LoadBalancingClient.DisconnectedCauseDisconnectCause.CustomAuthenticationFailed 로 설정되어 연결해제가 될 것 입니다. 이 경우에 OnOperationResponse 콜백의 OperationResponse.ReturnCode 에 따라 실패 원인을 각각 분류하여 처리 하도록 하시기 바랍니다. 예상되는 값들은 서버 파트에서 다루어 집니다.

인증 오퍼레이션

인증 오퍼레이션은 인증값이 실제로 서버에게 전송되는 것 입니다. 일반적으로 클라이언트 코드에서 직접적으로 사용되는 것이 아닌 당사의 API 에 의해 사용됩니다. 중요한 부분은: 서버로의 접속은 항상 인증 단계가 포함됩니다. 최초에 오퍼레이션은 실제의 인증 값을 암호화된 오퍼레이션으로 전송합니다. 이후 Photon 자신의 토큰을 제공 하고 있는 서버는 자동으로 암호화되어 사용되게 됩니다. LoadBalancing API는 이 작업흐름을 처리 합니다. 하지만 인증에 실패한 경우 클라이언트는 적당한 DisconnectCause 상태를 가지고 연결이 해제 됩니다.

서버측

웹서버가 인증 요청을 받은 즉시 쿼리 파라미터들이 유효한지 검사 되어야 합니다. 예를 들어, 자격증명은 데이터베이스에서 저장된 것과 비교 할 수 있습니다.

만약 수신된 파라미터들이 누락되었거나 유효하지 않는 것이면 결과는 { "ResultCode": 3}로 리턴 되어야 합니다.

검증이 끝난 후 결과는 다음과 같이 리턴 되어야 합니다:

  • 성공: { "ResultCode": 1, "UserId": <userId>}
  • 실패: { "ResultCode": 2}

고급 기능

사용자의 인증 이외에 인증 프로바이더로 부터 추가적인 정보가 리턴 될 수 있습니다. 이렇게 하기 위해서 사용자는 클라이언트와 인증자 역할을 하는 웹 서비스간에 특정한 프로토콜을 만들어야 합니다.

서버로 데이터 전송

가장 쉽고 간단한 방법은 "모두 아니면 아무것도(All or noting)" 전략 입니다: 클라이언트에게 변수의 정적 숫자를 리턴할지 하지 않을지를 선택 하세요. 하지만 클라이언트가 요청 한 것을 기반으로 "온-디멘드" 데이터를 리턴 하는 웹서비스와 같은 일부 유즈 케이스에서는 더 복잡한 접근법이 요구 됩니다. 다음의 하위 섹션에서는 클라이언트가 웹서비스로 어떻게 데이터를 전송 하는지에 대해 설명합니다. 데이터는 인증과 추가 파라미터의 인증에 필요한 자격증명이 될 수 있습니다. 추가 파라미터들은 인증 응답의 리턴으로 서버 측으로 부터 사용할 수 있는 데이터를 요청하기 위해서 사용 될 수 있습니다. 이것은 추가적인 API 호출이 없고 로그인 흐름이 간단 해지므로 매우 유용 합니다.

인증에 사용되는 디폴트 HTTP 메소드는 GET 입니다. 따라서 파라미터들은 키/값의 쌍으로 쿼리 스트링내에서 전송될 수 있습니다. 최종 URL 에는 대시보드에서 설정된 클라이언트로 부터 온 키/값의 "union"이 포함되어 있을 것 입니다. 만일의 경우에 대비하여 키는 양쪽에서 사용됩니다. 웹서버 사용여부에 따라 예측할 수 없는 행위가 야기 될 것 입니다. 모범사례의 대시보드에서 모든 "sensitive" 정적 값들이 클라이언트에게 "invisible" 로 설정되어 있는 이유 입니다. 예, API key, API 버전

아주 드문 경우지만 인증할 때 수 많은 데이터가 필요하여 부하가 크게 걸릴 수 도 있습니다. 다른 한편으로 대부분의 웹서버는 쿼리 스트링 또는 URL 에 대한 길이가 제한된 문자수를 가지고 있습니다. 이 사항 때문에 Photon 은 AuthenticationValues.AuthPostData를 명시적으로 설정하여 클라이언트에서 오는 HTTP 메소드를 POST 로 변경을 제안 하는 것 입니다. 후자는 string 또는 byte[] 타입이 될 수 있습니다. AuthenticationValues 클래스는 각 타입에 대하여 두 개의 setter 를 제공 하고 있습니다. 이것은 필요사항 또는 제약사항이 될 수 있으므로 웹 서비스에게 POST 메소드 인증 요청을 선택한 누구라도 가능하도록 해야 합니다.

다시 말하자면, 인증 파라미터를 전송하기 위해서 쿼리 스트링을 사용하던 POST 데이터를 사용하던 둘다 사용하든지 관계 없습니다. 다음 테이블에는 가능한 조합을 보여 주고 있습니다.

AuthPostData AuthGetParameters HTTP method
null * GET
empty string * GET
string (not null, not empty) * POST
byte[] (not null, can be empty) * POST

클라이언트에게 데이터 리턴

Photon 서버가 클라이언트와 웹 서비스 사이의 프록시이기 때문에 Photon 서버에의해서 처리되는 변수들에 대해서 주의 해야 합니다. Photon 서버에 의해 수신되는 HTTP 수신 응답과 같이 웹 서버는 ResultCode 와 선택적으로 Message 를 포함한 JSON 객체를 리턴 해야 합니다. 추가적으로 인증하는 동안에 웹 서비스로 부터 수신할 수 있는 목록이 있습니다.

  • UserId: 인증 자체의 파라미터로 사용 되거나 클라이언트 측에서 요구 될 수 도 있습니다. 이것은 Photon 서버에 의해 수신 될 때 클라이언트에게 항상 포워드됩니다. 만약 초기에 AuthenticationValues.UserId 값이 설정되어 있지 않으면 클라이언트로 다시 전송될 때 UserId는 무작위로 생성되어 전송됩니다. 이렇게 하면 클라이언트 내에서 UserId 의 값을 오버라이드하고 이후에 변경 될 수 없습니다.
  • Nickname: 인증 자체의 파라미터로 사용되거나 클라이언트 측에서 요구 될 수 도 있습니다. 웹 서비스로 부터 리턴 될 때 이것은 클라이언트의 별명을 오버라이드 하게 됩니다. 이 별명은 이후에 클라이언트에서 변경될 수 있습니다.
  • AuthCookie: 보안 데이터라고도 불리우는 이것은 웹 서비스에 의해서 리턴되는 JSON 객체이지만 수신된 암호화된 토큰에 임베드 되어 있을 것이므로 클라이언트 측에서 접근할 수 없을 것 입니다. 나중에 Webhook 또는 WebRPC HTTP 요청으로 전송 될 수 도 있습니다.
  • Data: JSON 객체로 클라이언트에게 리턴되어야 하는 모든 추가적인 값을 가지고 있습니다. 중첩된 배열 또는 객체들이 지원되지 않는다는 것에 주의 하세요.

ResultCode 가 필수 리턴 변수 이며 나머지 값은 다 선택적인 것들 입니다. 다음의 테이블에서 웹 서버가 리턴해 줄 수 있는 것에 대해 요약해 놓았습니다.

ResultCode Description UserId Nickname Data AuthCookie
0 인증 미완료, 데이터만 리턴됨.* x x x
1 인증 성공. ✓ (optional) ✓ (optional) ✓ (optional) ✓ (optional)
2 인증 실패. 잘못된 자격증명. x x x x
3 잘못된 파라미터. x x x x

*: OAuth 2.0 구현 및 2단계 검증에 유용하다는 것을 나타냅니다.

클라이언트로 온 데이터 읽기

다음 테이블에는 인증 응답을 해석할 때 어떻게 데이터 타입을 변환 하는지 보여 줍니다:

JavaScript / JSON C# / .Net
number (integral) long
number (floating) double
string string
boolean bool
null (not a type) null
undefined (when sent) null

다음은 응답으로 부터 리턴된 값을 어떻게 얻는지에 대한 코드 스니팻 입니다.

public override void OnOperationResponse(OperationResponse operationResponse) {
    base.OnOperationResponse(operationResponse);  // important to call, to keep state up to date
    switch (operationResponse.OperationCode) {
        case OperationCode.Authenticate:
            if (operationResponse.Parameters.ContainsKey(ParameterCode.Data)){
                var data = (Dictionary<string, object>)operationResponse.Parameters[ParameterCode.Data];
            }
            break;
        /*
            ...
        */
        default:
            break;
    }
}

문제해결

다음의 ReturnCode 값들은 인증 오퍼레이션에서 실패에 대한 값들을 보여 주고 있습니다.

  • ErrorCode.InternalServerError = -1: Photon 서버에서 수신된 데이터 해석시에 문제가 발생했다는 가능성을 말해 줍니다. 허용된 데이터 형식만을 사용하고 있는지 확인 해주세요.
  • ErrorCode.CustomAuthenticationFailed = 32755: OperationResponse.DebugMessage를 확인 해주세요. 웹 서버가 0 또는 1이 아니거나 HTTP 에러 코드를 리턴하는 원인일 수 있습니다.

대시보드에서 설정한 인증 URL 이 HTTP 오류가 리턴되는 경우에는 Photon 서버는 오버헤드를 방지 하기 위하여 잠시동안 인증 호출을 멈추게 됩니다. URL 구성 및 테스트 할 때 "백 오프"시간을 갖는 것을 고려 해 주시기 바랍니다.

모범 사례

  • 대시보드에서 정적 key/value 가 클라이언트에서 설정될 수 없도록 하세요. 쿼리 스트링 결과에 중복 키를 방지하게 해 줍니다.
  • 보안상의 이유로 패스워드를 인증 파라미터로 일반 텍스트로 전송 하지 마시기 바랍니다.
  • AuthenticationValues 를 이용하여 파라미터를 설정하여 AuthGetParameters 의 값에 직접적인 영향이 가지 않도록 해주세요. 이렇게 하면 잘못된 쿼리 스트링을 방지 할 수 있습니다.
  • 인증 프로바이더에서 리턴된 결과에는 읽을 수 있는 Message 가 포함되어 있어야 합니다. 특히 실패의 경우에 필요 합니다. 이렇게 하면 어려운 디버깅의 많은 작업을 줄일 수 있습니다.

 기술문서 TOP으로 돌아가기