LoginSignup
26
40

More than 5 years have passed since last update.

Nuxt.jsとaws-amplifyでログインするだけ

Posted at

Nuxt.jsAmazon Cognitoでユーザー登録、ログインを実装しました。
mode:'spa'です。

リポジトリ: nuxt-aws-amplify-sample

実装にあたり以下の記事とリポジトリを大いに参考にしました。

Cognitoの準備

ユーザープール作成

基本的にはデフォルトのままです。1ヶ所だけ変えています。
「属性」の「エンドユーザーをどのようにサインインさせますか」を「Eメールアドレスおよび電話番号」「Eメールアドレスを許可」に変更します。
これにより、メールアドレスでログインできるようになります。

スクリーンショット 2018-06-14 15.36.53.png

ユーザープールを作成すると、「プールID」が発行されます。

「アプリクライアント」を開きます。「クライアントシークレットを作成」のチェックを外し、作成してください。

スクリーンショット 2018-06-14 15.38.45.png

作成すると、「アプリクライアントID」が発行されます。

IDプール作成

「認証されていないIDに対してアクセスを有効にする」にチェックを入れてください。
認証プロバイダーで「Cognito」を選び、「ユーザープールID」と「アプリクライアントID」に先ほど発行されたIDを登録します。

スクリーンショット 2018-06-14 15.44.26.png

「IDプールの編集」画面に行くと、「IDプールのID(ややこしい)」がわかります。

これでCognitoの準備は終わりです。

追加ライブラリ

AWS Amplify
JavaScriptからAWSの機能を利用するためのライブラリ。
@nuxtjs/dotenv
Nuxtで.envを利用するためのライブラリ。

$ yarn add aws-amplify
$ yarn add @nuxtjs/dotenv

aws-amplifyの初期化

初期化はpluginで行なっています。
.envファイルはコミットしていないので、ルートディレクトリに準備してください。

.env
AWS_AMPLIFY_AUTH_REGION=リージョン
AWS_AMPLIFY_AUTH_USER_POOL_ID=ユーザープールID
AWS_AMPLIFY_AUTH_USER_POOL_WEB_CLIENT_ID=アプリクライアントID
AWS_AMPLIFY_AUTH_IDENTITY_POOL_ID=IDプールのID

たぶんaws-exportsを使う方がいいのでしょうが、フォーマットがわからなかったもので……。

画面

ログインや登録処理は各vueファイルに記載しています。

  • index.vue: トップページ
  • secret.vue: ログイン時にしか見られないページ
  • signin.vue: ログインフォーム
  • signup.vue: 新規登録フォーム
  • confirm.vue: 認証フォーム

ログイン判定

参考記事の知見に従い、middlewareに実装しました。未ログインの場合、ログインフォームに遷移します。
async/awaitをしないと一瞬画面が表示されてしまいます。

amplify-auth.js
import { Auth } from 'aws-amplify'

export default async ({ redirect }) => {
  let signed_in = false
  await Auth.currentUserInfo()
    .then(data => signed_in = Boolean(data))
    .catch(err => console.log(err))
    .then(() => signed_in || redirect('/signin'))
}

aws-amplify-vueでは、Auth.currentUserInfo()ではなく、Auth.currentAuthenticatedUser()をしてからAuth.currentCredentials()しています。
どちらの方がよいのでしょうか?
というか単純にログイン状態を見るようなことはできないのね。

登録後の認証

Cognitoに新規登録をすると、メールアドレスに認証コードが送られます。認証に必要なのはこのコードとusername(今回はメールアドレス)です。
何度も入力するのは手間なので、新規登録時にメールアドレスをstoreに保管し、認証フォームではstoreに値があれば最初から入力されている状態になるようにしました。

signup.vue
signUp () {
  Auth.signUp(this.email, this.password)
    .then(data => {
      this.$store.dispatch('amplify/setUsername', this.email)
      this.$router.push('/confirm')
    })
    .catch(err => this.errors = err)
}
confirm.vue
data () {
  return {
    email: this.$store.getters['amplify/username'],
    code: '',
    errors: ''
  }
},

aws-amplify-reactでは、storeにusernameがあればformにhiddenを追加し、なければ入力欄を表示するような作りになっています。

その他

プロダクションレベルにするためには、まだまだ考慮しなければいけないことが多そう。

エラー処理

入力値のバリデーションはaws-amplifyでやってくれます。
バリデーションエラーを含めたエラーメッセージは日本語化されないため、独自に設定する必要がありそうです。

パスワード変更必須

Cognito側でユーザーを作成すると仮パスワードが発行され、パスワード変更必須状態になります。
ログイン時にユーザーの状態を確認し、パスワード変更画面に遷移させる必要があるでしょう。

SSR

aws-amplifyはlocalStorageを使っているため、SSRするとログイン判定が行えません。
参考記事ではCookieを利用しています。
そもそもログイン機能が必要な画面でSSRする必要があるのか、という疑問……。

IAM

Cognitoが行うのはユーザーの認証だけで、リソースへのアクセス許可はIAMで行います。
IDプールで認証されたユーザーに与えられるロールが決められるので、適切に設定する必要があります。
(この辺りがややこしくて現状は「あーそーゆことね完全に理解した」状態)

それはともかく

慣れるとPHPとMySQLでゴニョゴニョするよりはるかに楽です。
もうユーザー関連は全部Cognito任せになってほしい。

26
40
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
40