🐕‍🦺

AmplifyでPublicアクセス認証方式を追加する。(2021年3月時点)

2021/03/01に公開

スキーマの修正

例えば以下のようなスキーマがあるとする。
これはAMAZON_COGNITO_USER_POOLSを使用してデータ作成者(Owner)のみデータの更新ができ、それ以外は読み込み(read)のみ可能という状態である。

type Product 
  @model 
  @auth(rules: [{ allow: owner, operations: [create, delete, update] }]) {
  id: ID!
  name: String!
  description: String
}

この状態だとログインしていないゲストユーザーではProductデータのreadしようとすると"No Current User"というエラーが出てしまう。
ログインしていない状態のユーザー(ゲストユーザー)でもこのデータにアクセスできるようにするには以下のpublicアクセスを許可する設定を追加する。

type Product 
  @model 
  @auth(rules: [
    { allow: owner, operations: [create, delete, update] },
    { allow: public, operations: [read] } # unauthenticated users can read
   ]) {
  id: ID!
  name: String!
  description: String
}

PublicアクセスはAPI_KEYかAWS_IAMを使用したアクセスになる。
API_KEYの使用は手軽だが、最大でも365日毎に手動で新しいAPI_KEYの作成を行わなければいけない。そのためAWS_IAMを使用する設定を追加する。
providerの記述がないとデフォルトではAPI_KEYを使用しようとする。

type Product 
  @model 
  @auth(rules: [
    { allow: owner, operations: [create, delete, update] },
    { allow: public, provider: iam, operations: [read] } # unauthenticated users can read
   ]) {
  id: ID!
  name: String!
  description: String
}

バックエンドの修正

AWS_IAMを使用するためにバックエンドをCLIを使用して修正する。

$ amplify update api
? Please select from one of the below mentioned services: GraphQL
? Select from the options below Walkthrough all configurations
? Choose the default authorization type for the API Amazon Cognito User Pool
Use a Cognito user pool configured as a part of this project.
? Do you want to configure advanced settings for the GraphQL API Yes, I want to make some additional changes.
? Configure additional auth types? Yes
? Choose the additional authorization types you want to configure for the API IAM
? Configure conflict detection? No

最後に設定変更を反映する

$ amplify push

これでバックエンドの修正は完了。

アプリロジックの修正

これで完成かと思いきや、最後にアプリ側で修正が1点ある。
Publicアクセスを許可するデータ取得の前に以下のようにAmplify.configureを修正するロジックを挟む必要がある。
AWS_IAMがバックエンドで使用可能となっていても、AmplifyはデフォルトでAMAZON_COGNITO_USER_POOLSを使用してしまい"No Current User"が返されてしまう。
そのため、アクセス方式の切り替えロジックが必要となる。

// isAuthenticated: ログインしているかの変数
if (isAuthenticated) {
  Amplify.configure({
    "aws_appsync_authenticationType": "AMAZON_COGNITO_USER_POOLS", 
  });
} else {
  Amplify.configure({
    "aws_appsync_authenticationType": "AWS_IAM", 
  });
}
listProduct();  // データ取得

以上でPublicアクセスができるはずである。

何か他の方法があれば、情報提供いただけると助かります。
お読みいただきありがとうございました。

Discussion