В этой статье мы рассмотрим аутентификацию одностраничного приложения (созданного с использованием Vue.js) в Amazon Cognito с использованием протокола OAuth. В нашей предыдущей статье мы интегрировали серверное приложение с Amazon Cognito.
Строительные леса одностраничного приложения
Мы будем использовать vue-cli для создания пустого приложения Vuejs. Vue CLI можно установить, следуя инструкциям здесь .
Давайте создадим пустое приложение под названием aws-cognito-spa-demo , выполнив следующую команду:
|
1
|
vue create aws-cognito-spa-demo |
Вам будет предложено выбрать плагины

После того, как приложение было создано, вы можете перейти в этот каталог и выполнить команду для запуска приложения.
|
1
2
3
|
cd aws-cognito-spa-demonpm instalnpm run serve |
Приложение будет запущено по адресу http: // localhost: 8080.
Установка дополнительных зависимостей
Мы установим необходимые пакеты узлов, которые мы будем использовать для приложения:
|
1
2
3
4
|
npm install --save amazon-cognito-auth-jsnpm install --save amazon-cognito-identity-jsnpm install --save vue-routernpm install --save axios |
Создание нового клиента приложения в Amazon Cognito
Мы создадим новый клиент приложения под названием test-spa-client из консоли Amazon Cognito, как показано ниже:

Обновите настройки для созданного клиента, перейдя в «Настройки клиента приложения», указав значения URL-адреса обратного вызова, URL-адреса выхода из системы, разрешенного потока OAUth и областей OAuth:

Мы используем Implicit Grant в качестве потока OAuth для приложений SPA.
Создание переменных среды
Мы будем хранить настройки, связанные с Amazon Cognito, в файлах свойств, а Vue CLI сделает их доступными среди переменных среды во время выполнения приложения. Подробнее об определении переменных среды в приложениях Vue JS можно найти здесь .
Мы будем хранить общие настройки приложения, такие как URI перенаправления cognito, URI файле .env и некоторые локальные настройки в .env.local. Файлы .env. *. Local и .env.local игнорируются в git. Таким образом, вы не фиксируете локальные настройки для контроля версий. .env
|
1
2
3
4
|
# In .envVUE_APP_COGNITO_REDIRECT_URI=http://localhost:8080/login/oauth2/code/cognitoVUE_APP_COGNITO_REDIRECT_URI_SIGNOUT=http://localhost:8080/logoutVUE_APP_APP_URL=http://localhost:8080 |
Тогда следующее в .env.local:
|
1
2
3
|
VUE_APP_COGNITO_USERPOOL_ID=<cognito userpool id>VUE_APP_COGNITO_APP_DOMAIN=<cognito app domain>VUE_APP_COGNITO_CLIENT_ID=<app client id> |
Создание пользовательского информационного магазина
Мы будем использовать глобальный объект JSON для хранения зарегистрированной пользовательской информации. Это альтернативный подход к использованию Vuex . Давайте создадим объект JSON в src/app/user-info-store.js :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
var state = { cognitoInfo: {}, loggedIn: false, loadingState: true, errorLoadingState: false}function setLoggedIn(newValue) { state.loggedIn = newValue;}function setLoggedOut() { state.loggedIn = false; state.cognitoInfo = {};}function setCognitoInfo(newValue){ state.cognitoInfo = newValue;}export default { state: state, setLoggedIn: setLoggedIn, setLoggedOut: setLoggedOut, setCognitoInfo: setCognitoInfo} |
Оболочка для Amazon Cognito API
Давайте создадим оболочку src/app/auth.js для Amazon Cognito API, которая облегчит такие операции, как создание объекта CognitoAuth , login, logout:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
/* eslint-disable */import {CognitoAuth, StorageHelper} from 'amazon-cognito-auth-js';import IndexRouter from '../router/index';import UserInfoStore from './user-info-store';import UserInfoApi from './user-info-api';const CLIENT_ID = process.env.VUE_APP_COGNITO_CLIENT_ID;const APP_DOMAIN = process.env.VUE_APP_COGNITO_APP_DOMAIN;const REDIRECT_URI = process.env.VUE_APP_COGNITO_REDIRECT_URI;const USERPOOL_ID = process.env.VUE_APP_COGNITO_USERPOOL_ID;const REDIRECT_URI_SIGNOUT = process.env.VUE_APP_COGNITO_REDIRECT_URI_SIGNOUT;const APP_URL = process.env.VUE_APP_APP_URL;var authData = { ClientId : CLIENT_ID, // Your client id here AppWebDomain : APP_DOMAIN, TokenScopesArray : ['openid', 'email'], RedirectUriSignIn : REDIRECT_URI, RedirectUriSignOut : REDIRECT_URI_SIGNOUT, UserPoolId : USERPOOL_ID,}var auth = new CognitoAuth(authData);auth.userhandler = { onSuccess: function(result) { console.log("On Success result", result); UserInfoStore.setLoggedIn(true); UserInfoApi.getUserInfo().then(response => { IndexRouter.push('/'); }); }, onFailure: function(err) { UserInfoStore.setLoggedOut(); IndexRouter.go({ path: '/error', query: { message: 'Login failed due to ' + err } }); }};function getUserInfoStorageKey(){ var keyPrefix = 'CognitoIdentityServiceProvider.' + auth.getClientId(); var tokenUserName = auth.signInUserSession.getAccessToken().getUsername(); var userInfoKey = keyPrefix + '.' + tokenUserName + '.userInfo'; return userInfoKey;}var storageHelper = new StorageHelper();var storage = storageHelper.getStorage();export default{ auth: auth, login(){ auth.getSession(); }, logout(){ if (auth.isUserSignedIn()) { var userInfoKey = this.getUserInfoStorageKey(); auth.signOut(); storage.removeItem(userInfoKey); } }, getUserInfoStorageKey,} |
Получение информации о пользователе от Amazon Cognito
После аутентификации мы можем использовать токен доступа для получения информации о пользователе, вошедшем в систему. Для этого нам нужно будет выполнить GET-запрос к конечной точке: https://<app domain>/oauth2/userInfo . Мы создали служебный метод getUserInfo() в src/app/user-info.js как показано ниже:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
import axios from 'axios';import auth from './auth';export default{ getUserInfo(){ var jwtToken = auth.auth.getSignInUserSession().getAccessToken().jwtToken; var requestData = { headers: { 'Authorization': 'Bearer '+ jwtToken } } return axios.get(USERINFO_URL, requestData).then(response => { return response.data; }); }} |
Этот API был использован в оболочке Cognito, написанной в разделе выше.
Создание компонентов Vue
Давайте создадим несколько компонентов Vue для:
- отображая вошедшую в систему информацию о пользователе
- показывает выход из системы
- компонент обработки ошибок
Мы будем использовать Vue Router для отображения URL-пути к компонентам Vue. Определения компонентов показаны ниже:
Home компонент
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
<template> <div class="row"> <div class="col"> <h3>Welcome, </h3> <div class="alert alert-info"> {{userInfo}} </div> <router-link to="/logout"> Logout </router-link> </div> </div></template><script>import UserInfoStore from '../app/user-info-store';export default { name: 'Home', data: function() { return{ userInfo: UserInfoStore.state.cognitoInfo } }}</script><style></style> |
Компонент LogoutSuccess :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
<template><div class="row"> <div class="col"> <h2>Logged Out successfully</h2> <router-link to="/login">Login</router-link> </div></div></template><script>export default { mounted: function(){ }}</script> |
Компонент ошибки:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
<template> <div class="alert alert-danger"> {{message}} </div></template><script>export default { data: function(){ return { message: "" } }, mounted(){ this.message = this.$route.query.message; }}</script> |
Настройка роутера
Как упоминалось в предыдущем разделе, мы будем использовать Vue Router для сопоставления URL-пути с компонентами Vue. Мы настроим конфигурацию маршрутизатора в router/index.js как показано ниже:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
/* eslint-disable */import Vue from 'vue'import Router from 'vue-router'import Home from '@/components/Home'import auth from '../app/auth';import LogoutSuccess from '@/components/LogoutSuccess';import UserInfoStore from '../app/user-info-store';import UserInfoApi from '../app/user-info-api';import ErrorComponent from '@/components/Error';Vue.use(Router)function requireAuth(to, from, next) { if (!auth.auth.isUserSignedIn()) { UserInfoStore.setLoggedIn(false); next({ path: '/login', query: { redirect: to.fullPath } }); } else { UserInfoApi.getUserInfo().then(response => { UserInfoStore.setLoggedIn(true); UserInfoStore.setCognitoInfo(response); next(); }); }}export default new Router({ mode: 'history', base: '/', routes: [ { path: '/', name: 'Home', component: Home, beforeEnter: requireAuth }, { path: '/login', beforeEnter(to, from, next){ auth.auth.getSession(); } }, { path: '/login/oauth2/code/cognito', beforeEnter(to, from, next){ var currUrl = window.location.href; //console.log(currUrl); auth.auth.parseCognitoWebResponse(currUrl); //next(); } }, { path: '/logout', component: LogoutSuccess, beforeEnter(to, from, next){ auth.logout(); next(); } }, { path: '/error', component: ErrorComponent } ]}) |
Мы используем свойство beforeEnter объекта маршрутов для добавления любых предварительных beforeEnter необходимых для визуализации компонента. И в этом свойстве мы проверяем, вошел ли пользователь в систему или не использует созданную нами оболочку Cognito. Таким образом, для путей, которые требуют защиты, мы можем определить свойство beforeEnter .
Созданное приложение по умолчанию имеет компонент App.vue который будет нашим корневым компонентом. Мы используем <router-view/> чтобы указать, что HTML здесь будет основан на компоненте, к которому разрешается путь в конфигурации маршрутизатора.
Итак, наша версия App.vue выглядит так:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png"> <div class="contents"> <router-view/> </div> </div></template><script>export default { name: 'app'}</script><style>#app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px;}</style> |
Затем мы обновляем src/main.js для ссылки на каталог, который содержит конфигурацию маршрутизатора, как показано ниже:
|
01
02
03
04
05
06
07
08
09
10
|
import Vue from 'vue'import App from './App.vue'import router from './router'Vue.config.productionTip = falsenew Vue({ render: h => h(App), router}).$mount('#app') |
Запуск приложения
Вы можете запустить приложение, введя команду: npm run serve . Переход на localhost: 8080 приведет вас к экрану входа в Cognito:

Введите имя пользователя и пароль пользователя, которого вы зарегистрировали в пуле пользователей, или вы даже можете зарегистрироваться для нового пользователя. После входа вы будете перенаправлены обратно в приложение Vue JS:

Ссылка «Выход» приведет к выходу пользователя из системы.
Полный код можно найти в репозитории Github здесь .
|
Опубликовано на Java Code Geeks с разрешения Мохамеда Санауллы, партнера нашей программы JCG . См. Оригинальную статью здесь: Интеграция Amazon Cognito с одностраничным приложением (Vue.js) Мнения, высказанные участниками Java Code Geeks, являются их собственными. |