今回はサインインエラーの対応を記載します。
合わせてパスワードを忘れた際のページを作成しています。
Multi-Factor Authentication (MFA)は扱いません。
前回のAWS Amplifyを使ってサインインを実装する-3 に追加していきます。
基本的に、views/Signin.vue
を修正します。
環境等
項目 | バージョン |
---|---|
node | v10.15.3 |
npm | 6.4.1 |
@aws-amplify/cli | 1.6.11 |
aws-amplify | 1.1.28 |
aws-amplify-vue | 0.2.11 |
vuesax | 3.8.65 |
material-icons | 0.3.1 |
実装
コードは最後にまとめて記載しています。
サインインエラー
サインイン時のエラーは以下があります。
エラーコード | 説明 |
---|---|
UserNotConfirmedException | Sign up時のユーザ確認が完了していない |
PasswordResetRequiredException | Cognitoコンソールでパスワードがリセットされた |
NotAuthorizedException | 間違ったパスワードが入力された |
UserNotFoundException | 指定されたユーザ名/メールアドレスがユーザプールに存在しない |
Sign up時のユーザ確認が完了していない
Auth.resendSignUpを利用して、再度検証コードを送信します。
そして、ConfirmSignup.vue
に遷移し、あとはSign up
と同じ流れになります。
Cognitoコンソールでパスワードがリセットされた
Auth.forgotPasswordを利用して、パスワードを忘れた際のリクエストを発行します。
検証コードが発行されるので、そのコードとパスワードを入力させるため、ForgotPassword.vue
に遷移させます。(router.js
にルートを追加)
ここでは、email, 検証コード, パスワードを入力してもらい、その内容で登録します。
登録には、Auth.forgotPasswordSubmitを利用します。
パスワードを忘れた際のページができたので、ついでにSign inページにリンクを用意しています。
間違ったパスワード/ユーザプールに存在しない
NotAuthorizedException
,UserNotFoundException
については、メッセージを表示するだけで済ませています。
ユーザにそれぞれのエラー詳細を教えることはしていません。
コード
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<vs-row vs-justify="center"> | |
<vs-col type="flex" vs-lg="6" vs-xs="10"> | |
<vs-card fixedHeight> | |
<div slot="header"> | |
<h3> | |
Forgot Password | |
</h3> | |
</div> | |
<div class="centerx"> | |
<vs-row> | |
<vs-col vs-w="12"> | |
<vs-input | |
type="email" | |
label-placeholder="email" | |
v-model="userInfo.email" | |
class="input" | |
size="large" | |
/> | |
</vs-col> | |
</vs-row> | |
<vs-row> | |
<vs-col vs-w="12"> | |
<vs-input | |
label-placeholder="Code" | |
v-model="userInfo.code" | |
class="input" | |
size="large" | |
/> | |
</vs-col> | |
</vs-row> | |
<vs-row> | |
<vs-col vs-w="12"> | |
<vs-input | |
type="password" | |
label-placeholder="Password" | |
v-model="userInfo.password" | |
class="input" | |
size="large" | |
/> | |
</vs-col> | |
</vs-row> | |
<vs-row> | |
<vs-col vs-w="12"> | |
<vs-input | |
type="password" | |
label-placeholder="Confirm Password" | |
v-model="userInfo.confirmPassword" | |
class="input" | |
size="large" | |
/> | |
</vs-col> | |
</vs-row> | |
<vs-row> | |
<vs-col vs-w="12"> | |
<vs-button class="forgotPassword" @click="forgotPassword"> | |
Submit | |
</vs-button> | |
</vs-col> | |
</vs-row> | |
<div slot="footer" class="error-message"> | |
{{ this.errorMessage }} | |
</div> | |
</div> | |
</vs-card> | |
</vs-col> | |
</vs-row> | |
</template> | |
<script> | |
export default { | |
name: "ForgotPassword", | |
data() { | |
return { | |
userInfo: { | |
email: "", | |
code: "", | |
password: "" | |
}, | |
errorMessage: "" | |
}; | |
}, | |
mounted() { | |
if (this.$route.params.email) { | |
this.userInfo.email = this.$route.params.email; | |
} | |
}, | |
methods: { | |
async forgotPassword() { | |
try { | |
await this.$Amplify.Auth.forgotPasswordSubmit( | |
this.userInfo.email, | |
this.userInfo.code, | |
this.userInfo.password | |
); | |
this.$router.push("/signin"); | |
} catch { | |
this.errorMessage = "新しいパスワードを設定できませんでした。"; | |
} | |
} | |
} | |
}; | |
</script> | |
<style lang="sass" scoped> | |
.centerx | |
display: flex | |
align-items: center | |
justify-content: center | |
flex-wrap: wrap | |
.input | |
width:100% | |
padding: 16px 64px | |
.forgotPassword | |
width: calc(100% – 64px * 2) | |
padding: 16px 0 | |
margin: 32px 64px 0 | |
.error-message | |
color: #FF0000 | |
margin: 32px 64px | |
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Vue from "vue"; | |
import Router from "vue-router"; | |
import { Auth } from "aws-amplify"; | |
import Home from "./views/Home.vue"; | |
Vue.use(Router); | |
async function requireAuth(to, from, next) { | |
try { | |
await Auth.currentAuthenticatedUser(); | |
next(); | |
} catch { | |
next({ | |
name: "signin" | |
}); | |
} | |
} | |
export default new Router({ | |
mode: "history", | |
base: process.env.BASE_URL, | |
routes: [ | |
{ | |
path: "/", | |
name: "home", | |
component: Home | |
}, | |
{ | |
path: "/about", | |
name: "about", | |
// route level code-splitting | |
// this generates a separate chunk (about.[hash].js) for this route | |
// which is lazy-loaded when the route is visited. | |
component: () => | |
import(/* webpackChunkName: "about" */ "./views/About.vue"), | |
beforeEnter: requireAuth | |
}, | |
{ | |
path: "/signin", | |
name: "signin", | |
component: () => import("./views/Signin.vue") | |
}, | |
{ | |
path: "/signup", | |
name: "signup", | |
component: () => import("./views/Signup.vue") | |
}, | |
{ | |
path: "/confirm-signup", | |
name: "confirm-signup", | |
component: () => import("./views/ConfirmSignup.vue") | |
}, | |
{ | |
path: "/signout", | |
name: "signout", | |
async beforeEnter(to, from, next) { | |
await this.$Amplify.Auth.signOut(); | |
next("signin"); | |
} | |
}, | |
{ | |
path: "/forgot-password", | |
name: "forgot-password", | |
component: () => import("./views/ForgotPassword.vue") | |
} | |
] | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<vs-row vs-justify="center"> | |
<vs-col type="flex" vs-lg="6" vs-xs="10"> | |
<vs-card fixedHeight> | |
<div slot="header"> | |
<h3> | |
Sign in | |
</h3> | |
</div> | |
<div class="centerx"> | |
<vs-row> | |
<vs-col vs-w="12"> | |
<vs-input | |
type="email" | |
label-placeholder="email" | |
v-model="userInfo.email" | |
class="input" | |
size="large" | |
/> | |
</vs-col> | |
</vs-row> | |
<vs-row> | |
<vs-col vs-w="12"> | |
<vs-input | |
type="password" | |
label-placeholder="Password" | |
v-model="userInfo.password" | |
class="input" | |
size="large" | |
/> | |
</vs-col> | |
</vs-row> | |
<vs-row> | |
<vs-col vs-w="12"> | |
<vs-button class="signin" @click="signIn">Sign in</vs-button> | |
</vs-col> | |
</vs-row> | |
<vs-row> | |
<vs-col vs-w="12" class="forgotPassword"> | |
<a @click="forgotPassword"> | |
Forgot password? | |
</a> | |
</vs-col> | |
</vs-row> | |
<div slot="footer" class="error-message"> | |
{{ this.errorMessage }} | |
</div> | |
</div> | |
</vs-card> | |
</vs-col> | |
</vs-row> | |
</template> | |
<script> | |
import { AmplifyEventBus } from "aws-amplify-vue"; | |
export default { | |
name: "Signin", | |
data() { | |
return { | |
userInfo: { | |
email: "", | |
password: "" | |
}, | |
errorMessage: "" | |
}; | |
}, | |
methods: { | |
async signIn() { | |
try { | |
await this.$Amplify.Auth.signIn( | |
this.userInfo.email, | |
this.userInfo.password | |
); | |
AmplifyEventBus.$emit("authState", "signedIn"); | |
this.$router.push("/about"); | |
} catch (e) { | |
switch (e.code) { | |
case "UserNotConfirmedException": | |
await this.$Amplify.Auth.resendSignUp(this.userInfo.email); | |
this.$router.push({ | |
name: "confirm-signup", | |
params: { email: this.userInfo.email } | |
}); | |
break; | |
case "PasswordResetRequiredException": | |
await this.$Amplify.Auth.forgotPassword(this.userInfo.email); | |
this.$router.push({ | |
name: "forgot-password", | |
params: { email: this.userInfo.email } | |
}); | |
break; | |
case "NotAuthorizedException": | |
case "UserNotFoundException": | |
default: | |
this.errorMessage = "emailかpasswordが間違っています。"; | |
break; | |
} | |
if (!e.code) { | |
this.errorMessage = "ログインできませんでした"; | |
} | |
} | |
}, | |
async forgotPassword() { | |
if (!this.userInfo.email) { | |
this.errorMessage = "emailを入力してください。"; | |
return; | |
} | |
await this.$Amplify.Auth.forgotPassword(this.userInfo.email); | |
this.$router.push({ | |
name: "forgot-password", | |
params: { email: this.userInfo.email } | |
}); | |
} | |
} | |
}; | |
</script> | |
<style lang="sass" scoped> | |
.centerx | |
display: flex | |
align-items: center | |
justify-content: center | |
flex-wrap: wrap | |
.input | |
width:100% | |
padding: 16px 64px | |
.signin | |
width: calc(100% – 64px * 2) | |
padding: 16px 0 | |
margin: 32px 64px 0 | |
.forgotPassword | |
width: calc(100% – 64px * 2) | |
padding: 16px 0 | |
margin: 0 64px | |
text-align: right | |
a | |
cursor: pointer | |
.error-message | |
color: #FF0000 | |
margin: 32px 64px | |
</style> |
ECMAScript,Javaを扱います。
最近は、vue.jsなどフロントエンドの技術に興味あり!
中日ドラゴンズを応援してます。
コメント