AmplifyでホスティングしたAngularのアプリにログイン認証を追加してみた

2021.07.15

こんにちは!DA(データアナリティクス)事業本部 インテグレーション部の大高です。

先日、Amplifyの入門としてAngularアプリをホスティングして、実際にブラウザで表示・APIの利用をするところまでを試してみました。

今回、更にアプリにログイン認証を追加するところを試してみたいと思います。

前提

この環境は以下の記事のとおりAmplifyを利用したAngularのアプリを作成し、AWS上にホスティングしています。

今回やりたいこと

Angularアプリ上にログイン認証を組み込ませたいです。

ログイン認証を追加する

今回は、下記のドキュメントに記載の手順を参考に、ログイン認証を追加していきます。

認証サービスを追加する

まずはamplifyコマンドを利用して、認証サービスの追加を行います。「サインインにメールアドレスを使うようにしたいな」と思ったので、ここだけデフォルトの選択肢から変更しています。

$ amplify add auth
Using service: Cognito, provided by: awscloudformation
 
 The current configured provider is Amazon Cognito. 
 
 Do you want to use the default authentication and security configuration? Default configuration
 Warning: you will not be able to edit these selections. 
 How do you want users to be able to sign in? Email
 Do you want to configure advanced settings? No, I am done.
Successfully added auth resource helloamplifyangular9fdcbcb2 locally

Some next steps:
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

設定できたら、デプロイしましょう。

$ amplify push
✔ Successfully pulled backend environment dev from the cloud.

Current Environment: dev

| Category | Resource name               | Operation | Provider plugin   |
| -------- | --------------------------- | --------- | ----------------- |
| Auth     | helloamplifyangular9fdcbcb2 | Create    | awscloudformation |
| Hosting  | amplifyhosting              | No Change |                   |
| Api      | HelloAmplifyAngularApi      | No Change | awscloudformation |
? Are you sure you want to continue? Yes
⠏ Updating resources in the cloud. This may take a few minutes...

(〜略〜)

✔ All resources are updated in the cloud

デプロイが終わったら、下記のコマンドでAWS管理コンソールを開いて確認してみます。

$ amplify console
✔ Which site do you want to open? · Console

開いたコンソールの下記の「View in Cognito」リンクから作成されたリソースがCognitoの管理画面からも確認できます。

なお、作成した直後に開くとうまく表示されなかったのですが、しばらくしたら正常に表示されるようになりました。うまく表示されない場合には、少し待つと良いのかもしれません。

これでCognitoの「ユーザープール」と「フェデレーティッドアイデンティティ」が作成されたので、ここから実際にアプリでこれらを利用してログイン認証できるように組み込んでいく必要があります。

アプリケーションにログイン認証を組み込む

では、アプリケーションにログイン認証を組み込んでいきましょう。ログイン画面はAngular用のAmplify UIコンポーネントが提供されているので、これを利用します。

なお、aws-amplify@aws-amplify/ui-angularについては、下記エントリで既に導入済みなので、あとはログイン画面の設定だけになります。

まずはapp.module.tsimportsAmplifyUIAngularModuleを追加します。

src/app/app.module.ts

import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AmplifyUIAngularModule } from '@aws-amplify/ui-angular';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [AmplifyUIAngularModule, AppRoutingModule, BrowserModule, HttpClientModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

次に、app.component.htmlにログイン画面用のコンポーネントamplify-authenticatorを追加します。今回はAngularのテンプレートプロジェクトのままなので、囲む範囲が広いのですが、styleタグのあとの部分をまるっとすべて囲んでしまいましょう。

なお、Amplifyのドキュメントにはtemplateタグも記載されていますが、今回は不要なので削除しています。(templateタグで括ると真っ白な画面になってしまいます)

src/app/app.component.html

(...snip...)
  @media screen and (max-width: 575px) {
    svg#rocket-smoke {
      display: none;
      visibility: hidden;
    }
  }
</style>

<amplify-authenticator>
    <div>
<!-- Toolbar -->
<div class="toolbar" role="banner">
(...snip...)
<router-outlet></router-outlet>

<amplify-sign-out></amplify-sign-out>
</div>
</amplify-authenticator>

コードの修正がおわったら、該当コードをgitリポジトリにpushして、AmplifyのCI/CDを動かしてデプロイします。

エラーとの闘い

これで終わりと思いましたが、様々なエラーが出てきたので、それぞれ書いていきます。

aws-exports.js が存在しないエラー

ビルド時にaws-exports.jsが存在しない旨のエラーが発生しました。

2021-07-13T03:05:51.192Z [WARNING]: Error: src/main.ts:8:23 - error TS2307: Cannot find module './aws-exports' or its corresponding type declarations.

これは、.gitignoreでGitリポジトリにpushしないようにしているので当たり前なのですが、どうすれば良いのでしょうか?

Stack Overflowに同様の質問がありました。

ビルド設定を修正すれば良いようなので、AWS管理コンソールのAmplifyコンソールを開いて「アプリの設定 > ビルドの設定」からamplify.ymlを修正します。修正箇所はfrontend.phases.build.commandsの箇所です。

以下のようにamplifyPush --simpleを追加します。

amplify.yml

version: 1
frontend:
  phases:
    preBuild:
      commands:
        - yarn install
    build:
      commands: 
        - amplifyPush --simple
        - yarn build
  artifacts:
    baseDirectory: dist/hello-amplify-angular
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*

ここで指定しているのは、.amplifyの内容に応じてaws-exports.jsファイルを生成してくれるヘルパースクリプトになります。公式ドキュメントにも以下で記載がありました。

これで、該当のエラーは出なくなりました。

JSONValidationError

今度はJSONValidationErrorが発生しています。

JSONValidationError: File project: data should NOT have additional properties: 'graphqltransformer'

これは、以下によると「ローカルのAmplify CLIのバージョン」と、「Amplify CI/CD上のAmplify CLIのバージョン」が違うと発生するようでした。

ローカル環境はyarn global add @aws-amplify/cliで最新化してあるので、Amplify CI/CD上のほうを修正してみます。

AWS管理コンソールのAmplifyコンソールを開いて「アプリの設定 > ビルドの設定」から「Build image settings」の「Edit」を開きます。

開いたら、ダイアログ下部の「Add package version override」でAmplify CLIを選択します。このとき、自動で「Version」にlatestが設定されます。

設定したら「保存」ボタンで保存しましょう。これで、該当のエラーは出なくなりました。

設定については、下記のドキュメントにも記載がありますね。

Your app does not have a role

今度はRoleに関するエラーが発生しました。

Amplifyコンソールがバックエンドリソースをデプロイするために、サービスロールのアタッチが必要なようです。

「Fix this」をクリックしてみると、「アプリの設定」画面に飛ばされます。ここで「Service role」を設定せよということのようです。

調べてみると下記のドキュメントに手順が記載されていましたので、こちらに従って修正します。

修正後に再デプロイすることで、エラーは出なくなりました。

ログイン認証してみる

ついにビルドが成功したので、動作確認をしてみます。画面を開くとログイン画面が表示されています!

アカウントをまだ作成していないので、まずは「Create account」から作成していきます。

アカウント情報の入力については、UI側で細かい制御をまだしていないので、電話番号も含めて全部出ているようですね。今回はそのまま進めます。なお、amplify add authの際に「ユーザー名はEmailを利用する」としたので、ユーザー名にはメールアドレスを指定します。

アカウントを作成すると、検証コードがメール通知されるので、検証コードを入力すると初回ログインが完了します。

画面の最下部にも、設定したとおりログアウトボタンが表示されていますね。こちらはクリックすると、ログイン画面に戻ることができます。

まとめ

以上、AmplifyでホスティングしたAngularのアプリにログイン認証を追加してみました!

想定外にいくつかエラーが出て時間が掛かってしまいましたが、ログイン認証の追加自体は簡単ですね。あとはログイン画面の日本語化や項目の調整をすれば良い感じになりそうです。

日本語化については、ちょっと古いですが以前に記事を書いたので以下も参考になるかもしれません。

どなたかのお役に立てば幸いです。それでは!