echo("備忘録");

IT技術やプログラミング関連など、技術系の事を備忘録的にまとめています。

【AppSync】Lambda認証でGraphQLクエリを実行する

はじめに

前回の記事にて、Auth0とOIDC(OpenID Connect)認証でAWS AppSync(以下「AppSync」)経由でGraphQLクエリを実行する方法について書きました。

ただし、もちろんAppSyncにはOIDC以外にも認証を行う方法はいくつかあります。

今回はその中から、前回の最後にも書いた「Lambda認証」について書きたいと思います。

やること

  • Lambda認証の仕様&認証Lambdaを書く
  • AppSyncの設定
  • クエリを実行する

Lambda認証の仕様について

Lambda認証については、下記公式ドキュメントに記載されています。

docs.aws.amazon.com

上記公式ドキュメントを見ると、まずイベント引数(event)には下記の値が格納されるようです。

項目 説明 備考
authorizationToken Authorizationヘッダの値
requestContext 下記「requestContextの内容」が格納されたオブジェクト

※requestContextの内容

項目 説明 備考
apiId 該当APIAPI 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となる

f:id:Makky12:20210913104107p:plain

クエリを実行する

では、実際にクエリを実行しましょう。 今回Rest Clientのみで確認します。

結果が下図ですが。「Authorization」ヘッダの値が「hogehoge」の場合は正しく結果が取得できており、逆に「hogehoge」ではない場合は「UnauthorizedException」が発生しているのが分かります。
ですのでLambda認証が正しく動いていると言えそうです。

f:id:Makky12:20210913104940p:plain
f:id:Makky12:20210913104959p:plain

また、一時的に「Token Regex」に以下の値(=半角数字のみ許可)を設定すると、例え「Authorization」ヘッダの値に「hogehoge」を設定しても「UnauthorizedException」が発生しているので、これも問題なさそうです。

f:id:Makky12:20210913105539p:plain f:id:Makky12:20210913105525p:plain

まとめ

以上がLambda認証でGraphQLクエリを実行する方法でした。

Lambda認証を使えば、独自処理を色々追加するなど、割とカスタマイズが出来そうなので、臨機応変というか柔軟な対応ができると思います。(その分管理とかが大変そうだけど)

さて次ですが、やはり残るAppSync認証のいずれかを記事にしようか...と考えてます。(IAMかCognitoあたり。APIキーはボリュームが少なそうで...)

あるいは、また別のネタでも書こうかな。(ネタ自体はそれなりにあるので)

それでは、今回はこの辺で。