AWS Amplifyを使ってサインインを実装する-4

今回はサインインエラーの対応を記載します。
合わせてパスワードを忘れた際のページを作成しています。
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については、メッセージを表示するだけで済ませています。
ユーザにそれぞれのエラー詳細を教えることはしていません。

コード


<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>


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")
}
]
});
view raw

router.js

hosted with ❤ by GitHub


<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>
view raw

Signin.vue

hosted with ❤ by GitHub

コメント

タイトルとURLをコピーしました