今回の記事について
Vue.js / Nuxt.jsにおけるログインの実装方法を調べることにしました
Nuxt.jsのAuth Moduleとmiddlewareを使うと実装できるということでやり方についてまとめつつ
サンプルも作成することで理解度をあげたいと思います
登場人物
Auth0について
Auth0とは
IDaaSを提供している認証基盤サービスのこと
IDaaSとは「Identity as a Service」の略であり、クラウド経由でログイン認証を管理することができる
Auth0を使うことで数行のコードを書くだけでアプリケーションにログイン認証を実装することができる
開発者向けのドキュメントは英語だが、アプリからフロント、バックエンドまで幅広い言語に対応しており、言語毎にドキュメントも作成されている
ソーシャルログインを実装することもでき、連携できる数が多い
↓下記の画像は連携例、表示しきれないだけで実際はもっとある
また導入実績としては9000社以上あるとのことなので実績も多い
Multi-factor Authentication(多要素認証)にも対応しているためため、認証に関しては大抵のことができるはず
認証周りを全てAuth0に丸投げしてしまうということはAuth0がダウンするとサービスが使えなくなってしまうが、2021年1月22日現在JP-1は稼働率は99.999%以上となっているらしい、以下のページより確認できる
Auth0の料金体系について
当然のことながらOSSではないためお金がかかる
2021年1月現在は月額$23とのこと(Web検索して2019年の記事を見ると$13と書いてあったのでもしかしたら値上げしたのかも?)
認証処理はサービスロジックではないためあまり手間をかけたくない部分ではあるが、個人情報流出漏洩まで繋がってしまうと会社の信頼に関わってしまうため念密に考え実装する必要がある
会社によってはセキュリティ専門の人材がいるぐらい重要度が高いためそこをAuth0にやってもらえると考えた上で懐の事情と相談した上で採用するかどうかは考えるべきかも
22日間の無料トライアルがあり以下のことができる
- 最大7000アクティブユーザー & ログイン回数無制限
- パスワードレス認証
- Web, iOS, Android対応
- 2種類までのソーシャルログイン設定
- Rules機能の利用は無制限
Auth Moduleとは
Nuxt.jsアプリケーションに簡単に認証を追加することができる公式モジュールのこと
下記サンプルの実装を見ながらどんなものかを理解してもらえればと
middlewareについて
ページがレンダリングされる前(SSR処理などが行われる前)に設定された関数を実行することができる
従って主に認証しているかのチェックに使われることが多い
middlewareの実行順序について覚えておくとどのタミングで認証チェックしているかがわかるのでメモ程度に記載しておくことにする
SSRあり
- plugins (SSR)
- middleware (SSR)
- fetch (SSR)
- beforeCreate (SSR)
- plugins (CSR)
- beforeEach (CSR)
- afterEach (CSR)
- beforeCreate (CSR)
SSRなし
- beforeEach (CSR)
- middleware (CSR)
- fetch (CSR)
- afterEach (CSR)
- beforeCreate (CSR)
作成するサンプルアプリケーションについて
構成
以下の3つのページ構成のサンプルアプリケーションを作成する
- トップページ:見出しや文言を表示するだけのページ
- ログイン画面:ログインをすることができるページ
- マイページ:ログイン時のみ表示できるページ、Auth0で登録している名前を表示される
サンプルはこちらのGitHubリポジトリに用意しています、使い方はREADME.mdをご覧頂けたらと
https://github.com/tomsato/sample-nuxt-auth
トップページ
ログイン画面
「Auth0でログイン」のボタンを押すとログインモーダルが表示される
ログインをするとマイページにリダイレクトされる
マイページ
ログインしていない状態でアクセスするとアラートモーダルを出しつつログインページにリダイレクトする
ログインしていればニックネームが表示される
※ 軽微なバグとして非ログイン時にナビゲーションバーにある「MyPage」へのリンク経由でマイページを表示すると上記の挙動になるが、/mypage
を直接表示するとアラートモーダルは表示されず「こんにちは、ゲストさん」という表示になる、この辺りは必要に応じて修正する必要がある
サンプルアプリケーションの作成 - 事前準備
Nuxt.jsの準備
まずばcreate-nuxt-appを使ってNuxt.jsのプロジェクトを用意する
// とりあえずUniversalにはした方が良いかも
$ yarn create nuxt-app sample-nuxt-auth
create-nuxt-app v3.4.0
✨ Generating Nuxt.js project in sample-nuxt-auth
? Project name: sample-nuxt-auth
? Programming language: TypeScript
? Package manager: Yarn
? UI framework: Bulma
? Nuxt.js modules: Axios
? Linting tools: ESLint, Prettier, Lint staged files, StyleLint
? Testing framework: Jest
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Server (Node.js hosting)
? Development tools: jsconfig.json (Recommended for VS Code if you're not using typescript)
? Continuous integration: None
? Version control system: Git
...
See : https://typescript.nuxtjs.org/cookbook/components/
✨ Done in 312.43s.
$ cd sample-nuxt-auth/
$ yarn dev
この状態で以下にアクセスするとサンプルページを見ることができる
Auth Moduleの追加
パッケージ追加
$ yarn add @nuxtjs/auth
// TypeScriptを使う際には型定義も導入する
$ yarn add -D @types/nuxtjs__auth
設定の追加
// nuxt.config.js
modules: [
...
'@nuxtjs/auth', // 追加
]
// nuxt.config.js
auth: {
strategies: {
auth0: {
domain: 'XXXXX', // Auth0 App Domain
client_id: 'XXXXX', // Auth0 App Client ID
},
},
redirect: {
login: '/', // 未ログイン時のリダイレクト先
logout: '/logout', // ログアウト処理を実行した直後のリダイレクト先
callback: '/callback', // コールバックURL
home: '/mypage', // ログイン後に遷移するページ
},
},
domainやclient_idはAuth0の画面内で確認することができる
ログイン後に表示されるページから「Applications」タブ →「Default App」をクリックすると以下のような表示になるはずで、その中の「Domain」と「Client ID」を記載することになる
// tsconfig.json
"types": [
...
"@types/nuxtjs__auth" // 追加
]
また store/index.js
を空で用意する、ない場合は以下のエラーが出る
FATAL Enable vuex store by creating store/index.js.
$auth
についてIDE等でESLintのエラーが出た場合は以下のファイルを作成しておく
// vue-shim.d.ts
import { Auth } from 'nuxtjs__auth'
declare module 'vue/types/vue' {
interface Vue {
$auth: Auth
}
}
Auth0の設定方法
「Allowed Callback URLs」の設定
Callback URLを登録する、これを設定しないとうまく動作しないため必ず実施する
Auth0でログイン後に「Applications」タブより「Default App」をクリック、「Domain」や「Client ID」の表示の少し下の方に設定項目があるはず
今回は「http://localhost:3000/callback」を設定する
サンプルアプリケーションの作成 - 実装
画面の作り込みを行う
差分はGitHubのプルリクとしてもまとめたのでこっちの方がわかりやすいかも
layouts/default.vue
全ページ共通のナビゲーションバーの実装
CSSフレームワークとしてはBulmaを使っているのでそれにあった書き方にしている
<template>
<div>
<nav class="navbar is-light">
<div class="navbar-brand">
<nuxt-link to="/" class="navbar-item">Home</nuxt-link>
<nuxt-link to="/mypage" class="navbar-item">MyPage</nuxt-link>
<nuxt-link to="/login" class="navbar-item">Login</nuxt-link>
</div>
</nav>
<Nuxt />
</div>
</template>
pages/callback.vue
ログイン後にID Providerによってこのパスにリダイレクトされる
nuxt.config.jsでhomeの設定にてログイン後には/mypage
にリダイレクトするようになっているため、ログイン時にはこのページが一瞬見えてすぐに/mypage
にリダイレクトするように見える
<template>
<div class="container has-text-centered mt-6">
<div>
<h1 class="title">sample-nuxt-auth</h1>
<h2 class="subtitle">Callback</h2>
<p>Please Wating...</p>
</div>
</div>
</template>
pages/index.vue
<template>
<div class="container has-text-centered mt-6">
<div>
<h1 class="title">sample-nuxt-auth</h1>
<h2 class="subtitle">トップページ</h2>
<p>このサイトはNuxt.jsでAuth0を試すサンプルアプリケーションです</p>
</div>
</div>
</template>
pages/login.vue
ログイン画面の実装
ログインボタンをクリックするとthis.$auth.loginWith('auth0')
が呼ばれログインモーダルが立ち上がる
<template>
<div class="container has-text-centered mt-6">
<div>
<h1 class="title">sample-nuxt-auth</h1>
<h2 class="subtitle">ログインページ</h2>
<button class="button is-dark is-large" @click="loginWithAuthZero">
Auth0でログイン
</button>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
methods: {
loginWithAuthZero() {
this.$auth.loginWith('auth0')
},
},
})
</script>
pages/logout.vue
ログアウト後に呼ばれるページ
<template>
<div class="container has-text-centered mt-6">
<div>
<h1 class="title">sample-nuxt-auth</h1>
<h2 class="subtitle">ログアウトしました</h2>
</div>
</div>
</template>
※ 追記: ログアウトボタンを設置するのを忘れてしまいましたmm ログアウトボタンを用意してクリック時に this.$auth.logout()
を実行するとログアウトされて /logout
にリダイレクトされるはずです
pages/mypage.vue
ログインしていないと見ることができないマイページ
middleware: 'userAuth'
にてページを表示する前にログインをしているかの認証部分の処理を呼び出している
なので認証をかけたいページについてmiddlewareの記述をすれば良い
<template>
<div class="container has-text-centered mt-6">
<div>
<h1 class="title">sample-nuxt-auth</h1>
<h2 class="subtitle">マイページ</h2>
<p>こんにちは、さん</p>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
middleware: 'userAuth',
computed: {
famlyName() {
return this.$auth.loggedIn ? this.$auth.$state.user.nickname : 'ゲスト'
},
},
})
</script>
middleware/userAuth.js
ログインしていない場合にalertモーダルを出しつつリダイレクトする処理を追加
export default function ({ store, redirect }) {
if (!store.state.auth.loggedIn && process.client) {
window.alert('ログイン画面を表示します')
redirect('/login')
}
}
動作確認
ここまで実装した上で yarn dev
で起動してページにアクセスするとログイン画面ではログインができるように、マイページではログインしていなければログイン画面にリダイレクトをして、ログインしていれば名前を表示できるようになっているはず
もし実装漏れなど何かあればコメントいただけたらと思いますmm
終わりに
今回はVue.js / Nuxt.jsにおけるログインの実装例として
Auth0と、Nuxt.jsのAuth Moduleとmiddlewareを使った実装例を紹介しました
middlewareをうまく使えばチェック処理などができることがわかったかと思います
またAuth Moduleもnuxt.config.jsをちょろっといじるぐらいで認証を取り入れることができるため簡単さを感じていただけたかと思います
機会があればAuth0を使ったソーシャルログイン方法についてもまとめてみたいと思います
コメントを書く
コメント一覧