カスタム認証

デフォルトではアプリケーションには認証メカニズムがなく、匿名ユーザーの接続が許可されます。 Photonアプリケーションにはカスタム認証を実装するオプションがあります。

Photonでのカスタム認証は非常に柔軟性が高く、サードパーティーの認証プロバイダや完全にカスタマイズされたソリューションに対応しています。

  • Exit GamesがホスティングするFacebook認証プロバイダ。 チュートリアルを参照してください
  • ユーザーが独自に構築し、ホスティングしているカスタム認証プロバイダ 弊社はGitレポジトリで認証プロバイダの実装例を提供しています。 ぜひレポジトリをフォークし、プルリクエストを送信してください。 GitHubでソースを確認してください。

目次

認証フロー

以下に、認証プロセスの一般的なフローを記載します。

Photon Cloud: Custom Authentication Flow Diagram
カスタム認証フロー図

  1. クライアントは、使用する認証プロバイダについての情報や必要な認証データをConnect()を使用してPhoton Serverに渡します。
  2. Photon Serverは、必要な認証プロバイダをアプリケーションに取得し、以下の手順のいずれかへと進みます。
    • 認証プロバイダ設定を検出された場合 -> 認証は手順3に進みます。
    • 認証プロバイダ設定が検出されない場合 -> アプリケーションの設定に応じて、クライアントは接続を許可されるか、または拒否されます
  3. Photon ServerはConnect()で渡された認証情報で、認証プロバイダを呼び出します。
    • 認証プロバイダがオンラインの場合 -> 認証は手順4に進みます。
    • 認証プロバイダがオフラインの場合 -> 該当するプロバイダの設定に応じて、クライアントは接続を許可されるか、または拒否されます。
  4. 認証プロバイダが認証情報を処理し、Photon Serverに結果を返します。
  5. 認証の結果に応じて、クライアントは正常に認証されるか、または拒否されます。

Photon Cloudにセットアップ

Photonアプリケーションのダッシュボードから、すべての認証プロバイダをセットアップできます。 アプリケーションの詳細ページに進み、カスタム認証セクションを開きます。

カスタム認証を設定する場合には、変更が反映されるまでにしばらく時間がかかる点に留意してください。

認証プロバイダを追加

認証プロバイダの設定は容易で、Photonアプリケーションのダッシュボードから数秒間で実行できます。

Photon Cloud: Custom Authentication Creation
カスタム認証プロバイダの作成

スクリーンショットで表示されているとおり、認証サービスがオンラインでない場合や、その他の何らかの理由で作動していない場合にクライアントを拒否する必要があるか、認証URLを入力して決定することができます。 また、各リクエストの認証サービスにクエリ文字列パラメータとして、送信するキー/値のセットを任意で追加できます。

ベストプラクティスは、クライアントに「不可視」で「機密」かつ静的なキー/値のセットをダッシュボードから設定することです。 例:
  • リクエストが、実際にいずれかのPhoton Serverから来ていることを確認するAPIパブリックキー
  • 今後の変更をさらに適切に処理するための、カスタム認証のAPIバージョン。

また、設定された認証プロバイダに関係なく、アプリケーションに接続しようとする匿名のクライアントを許可または拒否することもできます。 デフォルトではこの機能は有効化されているため、認証されているかどうかに関わらず、内部的にはすべてのクライアントがアプリケーションに接続することができます。Photonアプリケーションのダッシュボード内のアプリケーションの詳細ページ、認証セクションで確認してください。

Photon Cloud: Custom Authentication, Allow Anonymous Clients
カスタム認証を使用して、匿名のクライアントを許可

認証プロバイダをアップデートまたは削除

また、アプリケーションの詳細のページから、既存の認証プロバイダを選択して編集することができます。 編集フォームから、すべての設定を更新するか、または認証プロバイダを完全に削除することができます。

Photon Cloud: Custom Authentication Editing
既存のカスタム認証プロバイダをアップデートまたは削除

実装

Photon CloudでFacebook認証を使用する場合には、この部分は割愛してください。

クライアント側

クライアント側ではLoadBalancing APIでカスタム認証を処理します。関連するパラメータと対象のカスタム認証サービスの設定は、1回のみ必要です。 セットアップが完了すると、接続してその後のエラーが処理されます。

単純化するため、このスニペットでは非常に基本的なパスワードベースの認証証明書を選択しました。 結果的に、クエリ文字列は以下のとおりとなります:?user={user}&pass={pass}。 一般的に、これらの証明書は値のセットです。最初の値は固有の識別子(ユーザーID、ユーザー名、Eメールなど)で、もう1つの値は「信頼性の証明」(ハッシュされたパスワード、キー、秘密、トークンなど)です。

セキュリティ上の理由から、プレーンテキストのパスワードを送信しないでください。

認証オペレーション

認証オペレーションによって、認証値が実際にサーバーに送信されます。 これは通常、クライアントコードで直接使用されるのではなく、APIによって使用されます。 留意すべき点は:サーバーへの接続には、常に認証ステップが含まれる点です。 まず、オペレーションは暗号化されたオペレーションとして実際の認証値を送信します。 後に発生するサーバー切替では、Photonは暗号化され、かつ自動的に使用される独自のトークンを提供します。

サーバー側

Webサーバーが認証リクエストを受信した場合、クエリパラメータを確認し有効化する必要があります。 たとえば、現在の証明書とデータベース内に保存された既存の証明書を比較できます。 受信したパラメータが見つからない場合や無効の場合、返される結果は{ "ResultCode": 3}となります。

有効化が完了すると、以下が返されます:

  • Success: { "ResultCode": 1, "UserId": <userId>}
  • Failure: { "ResultCode": 2}

高度な機能

ユーザー認証以外にも、認証プロバイダーから補足情報を返すことができます。 この設定をおこなうには、ユーザーは「認証者」の役割を担うWebサービスとクライアント間にプロトコルのようなものを設定する必要があります。

サーバーにデータを送信

もっとも簡単かつ簡潔なのは、「全か無か」という方式です: クライアントに変数の静的な数を返すかどうか、選択してください。 一部のユースケースでは、クライアントのリクエストへの「オンデマンド」ベースでWebサービスがデータを返す、さらに複雑なアプローチが必要になります。 このサブセクションでは、クライアントからWebサービスにデータを送信する方法を説明します。 このデータは、認証に必要な証明書や補足のパラメータです。 補足のパラメータは、認証レスポンスで返されるサーバー側から利用可能になるデータをリクエストするのに使用されます。 これは非常に有用で、余分なAPIコールが不要となりログインワークフローが単純化されます。

認証に使用されるデフォルトのHTTPメソッドはGETです。 このため、パラメータはクエリ文字列内でキー/値のセットとして送信することができます。 最終的なURLには、クライアントやダッシュボードで設定されたキー/値のセットの「共用体」が含まれます。 同じキーが両方の場所で使用されいてる場合、ダッシュボードの値のみが送信されます。 ベストプラクティスは、クライアントに「不可視」で「機密」かつ静的なキー/値のセットをダッシュボードから設定することです(たとえばAPIキー、APIバージョンなど)。 また、ダッシュボードのキー/値はクライアントをアップデートせずに、即時に変更することが可能です。

まれに、認証が多くのデータを必要とする場合があります。 一方、ほとんどのWebサーバにはクエリ文字列で使用される文字数の上限や、URLの長さの閾値があります。 このため、Photonではクライアントから明示的に AuthenticationValues.AuthPostDataフィールドに値を設定してHTTPメソッドをPOSTに変更できるようにしました。

後者には、string型またはbyte[]型を設定することが可能です。 AuthenticationValuesクラスは、型ごとにそれぞれ2つのセッターを提供します。

これが要件や制約となる場合があるため、WebサービスからPOSTメソッドとして認証要求を受信したいユーザー向けにPOSTメソッドオプションも提供されています。

つまり、認証パラメータを送信する際にはクエリ文字またはPOSTデータ、もしくはその両方を自由に使用できます。 下表に、設定可能な組み合わせを示します。

AuthPostData AuthGetParameters HTTPメソッド
null * GET
空の文字列 * GET
文字列(nullではない、空ではない) * POST
バイト[] (nullではない、空も可能) * POST

クライアントにデータを返送

Photon ServerはクライアントとWebサービス間のプロキシなので、Photon Serverによって処理できる変数に留意してください。

Photon Serverが受信するすべてのHTTP受信レスポンスと同様に、WebサーバはResultCodeと任意のMessageを含むJSONオブジェクトを返す必要があります。 また、Photon Serverが認証時にWebサービスから受信可能なものを以下に記載します:

  • UserId: これは、認証自体のパラメータとして使用することができますが、クライアント側から要求することも可能です。Photon Serverが受信すると必ずクライアントに転送されます。 AuthenticationValues​​.UserIdが最初に設定されていない場合は、ランダムに生成されたUserIdがクライアントに返送されます。 これによってクライアントの UserIdの値が上書きされ、その後変更できなくなります。

  • Nickname: これは、認証自体のパラメータとして使用することができますが、クライアント側から要求することも可能です。 これがWebサービスから返されると、クライアント内の Nicknameの値が上書きされます。 Nicknameは、その後もクライアント側からアップデート可能です。

  • AuthCookie: セキュアデータとも呼ばれます。Webサービスによって返されるJSONオブジェクトですが、受信した暗号化トークンに埋め込まれるので、クライアント側からアクセスすることはできません。 WebhookまたはWebRPC HTTPリクエストとともに、後で送信することが可能です。
  • Data: クライアントに返すべきその他の値が含まれているJSONオブジェクト。 ネストされた配列やオブジェクトはサポートされません。

ResultCodeは唯一必須となっている戻り変数で、他の変数は任意です。 以下の表に、Webサーバが返すことが可能なものを示します。

ResultCode 説明 UserId Nickname AuthCookie Data
0 認証が不完全、データのみが返されました。* x x x
1 認証が成功。 ✓ (optional) ✓ (optional) ✓ (optional) ✓ (optional)
2 認証が失敗。証明書が誤っています。 x x x x
3 無効なパラメータ。 x x x x

*: インスタンスまたは2段階の検証にOAuth 2.0を実装するのに有用です。

クライアントからデータを読み込み

以下は、レスポンスから返された値を取得する方法を示すコードスニペットです:

データ型の変換

このセクションでは、Photonクラウドとウェブサービスの間で交換されるデータ型のみが説明されています。クライアントとPhotonサーバ間のデータ型の詳細はPhotonページのシリアル化を参照してください。

Photon Cloud -> ウェブサービス

C# / .Net (Photonが対応するタイプ) JavaScript / JSON
byte number
short
int
long
double
bool bool
string string
byte array string (Base64 encoded)
array (対応されているタイプの[], 長さ < short.MaxValue) array
Hashtable (対応されているタイプの, カウント < short.MaxValue, Photon実装が望ましい) object
Dictionary (対応されているタイプのキーや値, カウント < short.MaxValue) object
null null

サンプルリクエストデータ(タイプは連結されます)

Photonクラウドから送信:

ウェブサーバによって読み込み:

ウェブサービス - >Photon Cloud

各JavaScript/JSONタイプをC#/.Netの同等のものに照らし合わせる表:

JavaScript / JSON C# / .Net
object Dictionary<string, object>
array object[]
number double
string string
boolean bool
null (タイプではない) null
未定義(送信時) null

サンプルのレスポンスデータ(タイプは連結されています)

ウェブサーバーから送信:

Photon Cloudから読み込み:

トラブルシューティング

以下のReturnCodeの値は、それぞれの認証オペレーションが失敗したことを示します。

  • ErrorCode.InternalServerError = -1: これはおそらく、Photon Serverが受信したデータを解析する際に起きた問題が原因です。 許可されたデータ型を使用しているか、留意してください。
  • ErrorCode.CustomAuthenticationFailed = 32755: OperationResponse.DebugMessageを確認してください。 考えられる原因として、Webサーバーに到達できない、0または1以外のResultCodeが返された、返されたレスポンスがHTTPエラーコードを示している、などがあります。

ダッシュボードで設定した認証URLがHTTPエラーを返した場合、Photon Serverはオーバーヘッドを回避するために少しの間、認証コールを一時停止します。

URLを設定またはテストする際、この「バックオフ」時間を考慮してください。

ベストプラクティス

  • ダッシュボードから、クライアント側から設定するべきではない静的なキー/値のセットを設定します。 これは、結果のクエリ文字列内の重複キーを防ぎます。
  • セキュリティ上の理由から、認証パラメータとしてプレーンテキストのパスワードは送信しないでください。
  • Photonダッシュボードからクエリ文字列パラメータを設定するよう推奨されています。 これによって、リクエスト元を確認できます。
  • AuthenticationValuesメソッドを使用してパラメータを設定し、AuthGetParametersの値を直接変更しないでください。  これによって、クエリ文字列の変形が防止されます。
  • 特に失敗した場合、認証プロバイダから返される結果には読みやすい Messageを含める必要があります。 これによって、デバッグの手間を大幅に減少できます。

ユースケース例:古いクライアントバージョンをブロック

カスタム認証を使用して、古いバージョン(または予期せぬバージョン)を使用しているクライアントから受信した接続を拒否することができます。この場合、特定のエラーを返してユーザーにアップデートを依頼することが可能です。

これを実現するには、カスタム認証リクエスト内で該当のバージョンを送信する必要があります。クエリ文字列パラメータでおこなうか、またはPOSTデータ引数としておこなうかはユーザー自身が決めることができます。 以下の例では、クエリ文字列パラメータを使用しています:

string version = lbClient.AppVersion;
lbClient.AuthValues = new AuthenticationValues();
lbClient.AuthValues.AuthType = CustomAuthenticationType.Custom;
lbClient.AuthValues.AddAuthParameter("version", version);

カスタム認証のURLがhttps://example.comの場合、リクエストはhttps://example.com?version={version}として送信されます。 認証プロバイダ実装から受信するバージョンを取得し、比較してください。 バージョンが許可された場合、{ "ResultCode": 1}を返してください。 もし許可されない場合には、任意のカスタム値(1以外)でResultCodeを返し、できる限りメッセージも送信してください。 例: { "ResultCode": 5, "Message": "Version not allowed."}

 ドキュメントのトップへ戻る