はじめに
前回の記事にて、Auth0とOIDC(OpenID Connect)認証でAWS AppSync(以下「AppSync」)経由でGraphQLクエリを実行する方法について書きました。
ただし、もちろんAppSyncにはOIDC以外にも認証を行う方法はいくつかあります。
今回はその中から、前回の最後にも書いた「Lambda認証」について書きたいと思います。
やること
- Lambda認証の仕様&認証Lambdaを書く
- AppSyncの設定
- クエリを実行する
Lambda認証の仕様について
Lambda認証については、下記公式ドキュメントに記載されています。
上記公式ドキュメントを見ると、まずイベント引数(event)には下記の値が格納されるようです。
項目 | 説明 | 備考 |
---|---|---|
authorizationToken | Authorizationヘッダの値 | |
requestContext | 下記「requestContextの内容」が格納されたオブジェクト |
※requestContextの内容
項目 | 説明 | 備考 |
---|---|---|
apiId | 該当APIの API ID | |
accountId | 該当APIがあるAWSアカウントのアカウントID | |
requestId | 該当APIの呼び出しごとに付けられる一意のID | |
queryString | 実行されたクエリ/ミューテーションの内容 | |
operationName | 実行されたクエリ/ミューテーションの名前 | |
variables | 実行されたクエリ/ミューテーションの変数にとして設定されたキー&値 |
また、レスポンスには下記項目を格納したオブジェクトを返す必要があります。
項目 | 設定値 | 必須 | 備考 |
---|---|---|---|
isAuthorized | 認証処理の結果。(OK:true/NG:false) | 〇 | |
deniedFields | 認証NG時のNGフィールド名(?)の配列 | ARN形式またはTypeName.FieldNameの形式。 リゾルバで設定しても、強制的にnullになるとのこと。 |
|
resolverContext | リゾルバのレスポンスコンテキストに設定したフィールドの値 | ||
ttlOverride | 認証結果(のレスポンス)をキャッシュする時間 | 0の場合はキャッシュしない。 また未指定の場合、後述の「AppSyncの設定」の「Authorizer Response Cache TTL」に指定した値が適用される。 |
Lambda認証を行う場合、とりあえず下記の2点をおさえておけばOKです。
- 認証Lambdaのイベント引数の「authorizationToken」キーにAuthorizationヘッダの値が格納される
- レスポンスの「isAuthorized」に認証結果(true/false)を設定する。
実際に認証Lambdaを書く
では、実際に認証Lambdaを書きましょう。
といっても、先程の仕様に沿って、普通にLambda関数を書くだけです。
今回はサンプルということで、単純に「Authorizationヘッダの値が'hogehoge'の場合のみOKとする」処理にしています。
// event引数、およびレスポンスオブジェクトの定義。 // (どっかに定義ファイルがあるのかも) export interface AppSyncAuthLambdaEvent { authorizationToken: string; requestContext?: AppSyncAuthLambdaEventRequestContext; } interface AppSyncAuthLambdaEventRequestContext { apiId: string; accountId: string; requestId: string; queryString: string; operationName: string; variables: any; } export interface AppSyncAuthLambdaResponse { isAuthorized: boolean; deniedFields?: string[]; resolverContext?: any; ttlOverride?: number; } import { AppSyncAuthLambdaEvent, AppSyncAuthLambdaResponse } from '../../interface'; // OKにするAuthorizationヘッダの値 const CORRECT_TOKEN: string = 'hogehoge'; // 関数本体 export async function handler( event: AppSyncAuthLambdaEvent ): Promise<AppSyncAuthLambdaResponse> { console.info('Received event {}', JSON.stringify(event)); const authToken: string = event.authorizationToken ?? ''; const response: AppSyncAuthLambdaResponse = { isAuthorized: authToken === CORRECT_TOKEN }; console.info('Response JSON {}', JSON.stringify(response)); return response; }
AppSyncの設定
次にAppSyncの設定です。
まずは前回同様、作成したAppSync APIをクリックし、左ツリーの「設定」をクリックします。
その後設定画面の「デフォルトの認証モード」項目で、下記項目に下記の値を入力して「保存」をクリックします。
項目 | 設定値 | 必須 | 備考 |
---|---|---|---|
APIレベル | AWS Lambda | 〇 | |
AWSリージョン | 上記認証LambdaがあるAWSアカウントのリージョン | 〇 | 大抵は「AP-NORTHEAST-1(東京)」だと思う |
関数のARN | 上記認証LambdaのARN | 〇 | リストから選択。表示されない場合「関数が表示されませんか?」リンクをクリックすると直接入力できる |
Authorizer Response Cache TTL | 認証結果(のレスポンス)をキャッシュする時間 | 認証Lambdaのレスポンスに「ttlOverride」を指定しない場合、この値が適用される。 デフォルト300秒(=5分)、0の場合はキャッシュしない、というのはttlOverrideと同じ |
|
Token regex | 許可するAuthorizetionトークンの正規表現パターン | ここのパターンに一致しない場合、認証NGとなる |
クエリを実行する
では、実際にクエリを実行しましょう。 今回Rest Clientのみで確認します。
結果が下図ですが。「Authorization」ヘッダの値が「hogehoge」の場合は正しく結果が取得できており、逆に「hogehoge」ではない場合は「UnauthorizedException」が発生しているのが分かります。
ですのでLambda認証が正しく動いていると言えそうです。
また、一時的に「Token Regex」に以下の値(=半角数字のみ許可)を設定すると、例え「Authorization」ヘッダの値に「hogehoge」を設定しても「UnauthorizedException」が発生しているので、これも問題なさそうです。
まとめ
以上がLambda認証でGraphQLクエリを実行する方法でした。
Lambda認証を使えば、独自処理を色々追加するなど、割とカスタマイズが出来そうなので、臨機応変というか柔軟な対応ができると思います。(その分管理とかが大変そうだけど)
さて次ですが、やはり残るAppSync認証のいずれかを記事にしようか...と考えてます。(IAMかCognitoあたり。APIキーはボリュームが少なそうで...)
あるいは、また別のネタでも書こうかな。(ネタ自体はそれなりにあるので)
それでは、今回はこの辺で。