aws amplify

2023-03-10 20:06
2023-10-14 16:55

AWS Amplify に関する情報を集約するページ

Amplify API (GraphQL)

認証ルールについて

選択可能な認証ルールの種類

2022/06 現在、@auth ディレクティブを用いて以下の 6 通りのルールを指定できる

  • Strategy: public, Provider: apiKey: API キーを利用したリクエストの許可
  • Strategy: public, Provider: iam: 非認証なユーザーやデバイスに IAM を用いてリクエストを許可する
  • Strategy: owner, Provider: userPools/oidc: サインイン済みのユーザーに対して owner レコードの値に依存したアクセス制御を行う
  • Strategy: private, Provider: userPools/oidc/iam: 任意のサインイン済みユーザーへのアクセスを許可する
  • Strategy: group, Provider: userPools/oidc: サインイン済みのユーザーに対して group レコードの値に依存したアクセス制御を行う
  • Strategy: custom, Provider: function: Lambda 関数を利用したカスタムの認証ルールを設定する

see: Authorization strategies, Setup authorization rules

# API キーによる認証
type Post @model @auth(rules: [{ allow: public }]) {
  id: ID!
  content: String!
}

# IAM による認証(Unauth/Auth どちらのロールでも適切な権限を持っていればアクセス可能)
type Post @model @auth(rules: [{ allow: public, provider: iam }]) {
  id: ID!
  content: String!
}

# IAM による認証(Auth ロールでのみアクセス可能)
type Post @model @auth(rules: [{ allow: private }]) {
  id: ID!
  content: String!
}

# CUP/oidc による認証
# Post モデルには owner フィールドが自動的に定義され、そのフィールドの値と一致したユーザーのみアクセス可能
# ディレクティブのパラメタにて ownerField を指定することも可能
# ownerField が [String] である場合、ユーザーと一致する値があった際にアクセス可能
type Post @model @auth(rules: [{ allow: owner }]) {
  id: ID!
  content: String!
}

# CUP/oidc のユーザーグループベースの認証
# Post モデルには groups フィールドが自動的に定義され、そのフィールドの値と一致したグループに属するユーザーのみアクセス可能
# ディレクティブのパラメタにて groupsField を指定することも可能
type Post @model @auth(rules: [{ allow: groups }]) {
  id: ID!
  content: String!
}

# カスタム認証
# amplify update 時に対応する Lambda 関数の指定もしくは新規作成が可能
type Post @model @auth(rules: [{ allow: groups }]) {
  id: ID!
  content: String!
}

Owner のみへのアクセス許可する方法

Cognito ユーザープール認証を利用している必要がある

type Post @model @auth(rules: [{ allow: owner }]) {
  id: ID!
  title: String!
  owner: String
}

一部のオペレーションのみ許可する方法

@auth ディレクティブの operations プロパティで設定できる。

authorized operations (operations): which operations are allowed for the given strategy and provider. If not specified, create, read, update, and delete operations are allowed. -- read operation: read operation can be replaced with get, list, sync, search, list for a more granular query access API (GraphQL) - Authorization rules - AWS Amplify Docs

指定可能なオペレーションは create, read(get, list, sync, search), update, delete

IAM 認証モード時にマネジメントコンソールからのアクセスを可能にする

Amplify API で作成した AppSync GraphQL API で @auth(rules: [{ allow: public, provider: iam }]) により IAM 認証モードを追加している際にはデフォルトでは Amplify によって生成された IAM ロールからのアクセスのみを受け入れる形となっている。

開発中のマネジメントコンソールなどからの動作確認や手元でスクリプトを動かす場合には追加の設定が必要となる。API (GraphQL) - Authorization rules - AWS Amplify Docs に記載があるとおり amplify/backend/api/<api-name>/custom-roles.json というファイルを作成し以下の内容を追記したのちデプロイすればよい。

{
  "adminRoleNames": ["<YOUR_IAM_USER_OR_ROLE_NAME>"]
}

非ログインユーザーで取得できたレコードがログインユーザーで取得できない

下記のような @auth の設定状況下では非ログインユーザーはすべての Record の read が可能だがログインユーザーは owner が自身の sub と一致しているものしか取得できず、結果として非ログインユーザーより権限が弱くなる。

type Record
  @auth(
    rules: [
      { allow: public, provider: iam, operations: [read] }
      { allow: owner }
    ]
  )
  @model(subscriptions: null) {
  id: ID!
  description: String
}

非ログイン/ログイン状態双方で read を許可しつつ、更新は owner に限りたい場合は下記のように書く

type Record
  @auth(
    rules: [
      { allow: public, provider: iam, operations: [read] }
      { allow: private, operations: [read] }
      { allow: owner }
    ]
  )
  @model(subscriptions: null) {
  id: ID!
  description: String
}

@auth の private と private iam の違い

{ allow: private } は Cognito User Pool の JWT トークンを利用したアクセス、{ allow: private, provider: iam } は Authenticated Role を利用したアクセスという違いがある

アプリケーションとの連携

schema.graphql から API クライアントコード生成を行いたい

amplify codegen init コマンドにてコード生成に関する設定を行ったのちに amplify codegen コマンドを利用してコードを生成できる

クエリする方法にはどのようなものがあるか

  • amplify codegen によって生成されたクライアント
  • awslabs/aws-mobile-appsync-sdk-js
  • 一般の HTTP/S クライアントもしくは GraphQL API クライアント

Lambda リゾルバ

単純に入力した値を返す Lambda リゾルバを定義したい

see: API (GraphQL) - Configure Lambda resolvers - AWS Amplify Docs

まずLambda 関数自体を用意するため amplify add function コマンドを実行して下記のような実装を行ったうえでデプロイする。

exports.handler =  async function(event, context){
  return event.arguments.msg
}

その後、スキーマの定義に下記のようなクエリを追加してデプロイすればよい

type Query {
  echo(msg: String): String @function(name: "echofunction-${env}")
}

FAQ

公開レコードと認証済みユーザーのみに公開するレコードが混在したモデルを作成したい

  • 2022/06 現在、@auth ディレクティブのみでは実現できない
  • 公開レコードと認証済みユーザー向けレコードのモデルを分けるかカスタムリゾルバーを使うかのどちらかにて対応する必要がある

AppSync API を通じて画像のアップロード/ダウンロードを行いたい

詳細は How to Manage Image & File Uploads & Downloads を参照

GraphQL クエリ結果を日付順にソートした状態で得たい

詳細は GraphQL query with sorting by date を参照

以下のような GraphQL スキーマがあったとして ListTodos の結果を createdAt など日付順にソートして得たいというシチュエーションはよくある。

type Todo @model {
  id: ID!
  title: String!
  createdAt: AWSDateTime!
}

この場合に以下のように @index ディレクティブを活用することによりソートしたクエリ結果を得られる。ただし Todo のすべてのレコードが追加した type フィールドの値を持つようにテーブルのデータを更新する必要はある。

type Todo @model {
  id: ID!
  title: String!
  type: String! @index(name: "todosByCreatedAt", queryField: "listTodosOrderByCreatedAt", sortKeyFields: ["createdAt"])
  createdAt: AWSDateTime!
}

vercel コマンドでデプロイすると GraphQL API の接続先として localhost を参照する

  • amplify mock api コマンドを実行すると aws-exports.js の GraphQL エンドポイントがローカルとなる
  • mock API を停止すると aws-exports.js の GraphQL エンドポイントの向き先がもとに戻るのでその状態でデプロイすればよい

Amplify Function

Amplify Function の Lambda 関数を TypeScript で実装する

amplify add function コマンドで追加した Lambda 関数は手軽に TypeScript で実装できる状態にできる。手順の詳細は Functions - Build options - AWS Amplify Docs に記載されている。

すべての手順はおおまかに次のようなものとなる

  1. amplify add function コマンドにて Lambda 関数を追加する
  2. プロジェクトルートの package.json にトランスパイルを行うスクリプトを追加する
  3. 追加した Lambda 関数コードのディレクトリルートに tsconfig.json を配置する
  4. (Optional) 追加した Lambda 関数コードのディレクトリルートに .gitignore を配置しトランスパイルされた .js ファイルを git 管理対象から外す

see: Functions - Build options - AWS Amplify Docs

// package.json
{
  "scripts": {
    "amplify:generateReport": "cd amplify/backend/function/generateReport && tsc -p ./tsconfig.json && cd -"
  },
}

// tsconfig.json
{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "lib": ["dom", "esnext"],
    "module": "commonjs",
    "moduleResolution": "node",
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "outDir": "./src",
    "baseUrl": "./",
    "rootDir": "./lib",
    "paths": {
      "src": ["./lib"]
    }
  }
}

Lambda から AppSync GraphQL API にクエリしたい

see: 環境に応じたappsync-clientセットアップ

Amplify JavaScript

Logger

Logger の基本的な利用方法については Utilities - Logger を参照。Amplify JavaScript の Logger は Provider を指定することにより追加の処理を行うことができる。Provider は packages/core/src/Providers に配置してある。

Copyright © 53ningen.com