UnityでCognito UserPoolsから得たトークンでリクエストし、API Gatewayでsubを受け取る
前回の記事の続きです。
今回はUserPoolsにサインアップして、AWS側で認証したユーザーを確認するまでを行います。
API GatewayとCognito UserPoolsを連携する
事前に、Cognito UserPoolsを作成します。 前回の記事でCognito UserPoolsのUserPoolを作成しているので、追加で以下の操作を行います。
以下の操作のドキュメントはこちらを参照してください。
API GatewayでResourceとMethodを作成
リソース名としては良くないですが、今回はGET /authorize
を作成しました。
API Gateway Authorizerを作成
マネジメントコンソールのAPIs > Authorizers > Create New Authorizer
から、UserPoolsを指定してAuthorizerを作成しました。
Authorization Headerを見るので、Token SourceにはAuthorization
と記入します。
Method RequestのAuthorizationにAuthorizerを指定
以下の点に気をつけて指定します。
- Authorizationには、先ほど作成したAPI Gateway Authorizerを指定する
- OAuth ScopeはNONEのままにしておく
Request Validatorはデフォルトのままでも良いのですが、ValidationすることでAuthorization HeaderがないリクエストではLambdaを起動しない挙動になり、セキュリティの実装とコスト削減を手軽に実現できます。
この設定をする場合は、Method RequestのHTTP Request HeadersにAuthorizationを追加し、Requiredに設定します。
Integration RequestでLambda Proxyを設定
このあとUserPoolsのUser NameをsubとしてLambda Functionのevent objectで受け取れることを確認するので、Lambda Proxyを設定します。
事前に以下のようなLambda Functionを作成します。詳細は割愛します。
import json import logging logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): logger.info(event) return { 'statusCode': 200, 'body': json.dumps({'message': 'success'}, ensure_ascii=False), 'headers': {'Content-Type': 'application/json'} }
ここまでやったらStageにDeployします。
DeployしたAPIをUserPoolsのApp IntegrationでResource Serverに設定する
ドキュメントはこちらです。 https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-create-cognito-user-pool.html
- Nameは適当に入力します
- Identifierは、StageにDeployされたAPI Gateway APIに付与されるURLを記載します。Custom Domainを設定している場合はそちらを設定します。
Unity側のソースコードを変更する
前回のサンプルアプリを修正します。画面は以下の画像のようにしました。
サインアップとConfirmation Codeのスクリプトは前回の記事と一緒です。
サインイン
サインインも前回とやってることは一緒なのですが、APIの動作確認を楽にするためにIdTokenを自動でGETリクエストのフォームに入力するようにしました。
using System; using System.Collections; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using UnityEngine; using UnityEngine.UI; using Amazon; using Amazon.Runtime; using Amazon.CognitoIdentityProvider; using Amazon.Extensions.CognitoAuthentication; public class Signin : MonoBehaviour { public InputField emailField; public InputField passwordField; public InputField tokenField; static string clientId = "MyClientId"; static string userPoolId = "us-west-2_xxxxxxx"; void Start () { } void Update () { } public void OnClick() { Debug.Log("Start Signin"); try { CallAuthenticateTask(); } catch(Exception ex) { Debug.Log(ex); } } private async void CallAuthenticateTask() { var context = SynchronizationContext.Current; AuthFlowResponse response = await AuthenticateWithSrpAsync(); context.Post((state) => { tokenField.text = response.AuthenticationResult.IdToken; }, null); } private async Task<AuthFlowResponse> AuthenticateWithSrpAsync() { var provider = new AmazonCognitoIdentityProviderClient (null, RegionEndpoint.USWest2); CognitoUserPool userPool = new CognitoUserPool( userPoolId, clientId, provider ); CognitoUser user = new CognitoUser( emailField.text, clientId, userPool, provider ); return await user.StartWithSrpAuthAsync(new InitiateSrpAuthRequest(){ Password = passwordField.text }).ConfigureAwait(false); } }
Authorization Header付きGETリクエスト
詳細はUnityのドキュメントを参照してください。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; using UnityEngine.Networking; public class GetRequest : MonoBehaviour { public InputField tokenField; // API Gatewayが作成して、Resource Serverにも指定したURL static string url = "https://api-gw-published-url/authorize"; void Start () { } void Update () { } public void OnClick () { StartCoroutine(GetText()); } IEnumerator GetText() { string token = tokenField.text; // UserPoolsから取得したIdToken UnityWebRequest www = UnityWebRequest.Get(url); www.SetRequestHeader("Authorization", token); // Authorization Headerの付与 yield return www.SendWebRequest(); if (www.isNetworkError || www.isHttpError) { Debug.Log(www); } else { Debug.Log(www.downloadHandler.text); } } }
動作確認
Lambdaのlogger.info(event)
がCloudWatch Logsに出力されています。サインアップしたユーザーの情報が取得できていることがわかります。
{..., 'headers': {..., 'Authorization': 'eyJra...vqA', ..., 'requestContext': {..., 'authorizer': {'claims': {'sub': '0c08e593-f9f8-aaaa-bbbb-ccccccc', 'aud': '
まとめ
前回の記事に引き続き、Cognito UserPoolsとAPI Gatewayの連携を設定して、UnityアプリからAuthorization Header付きでHTTPリクエストを送り、クラウド側でUserPoolsが発行するUser IDをLambda Functiondで取得しました。