pgm-auth v1.0.0
Auth System
This plug-in is designed to be easy-to-use client-side authentication using AWS Cognito + Amplify AUTH API with Vuetify UI components.
It will create a session with cognito for the user if they are in the pool, refresh the token and keep the session active. The token will be set as an axios auth header with the prefix "Cognito ".
New users must access their account and reset their password within 14* days to avoid their account being locked. If they fail to do this within the allotted time period, we currently do not have a way implemented to reset their account. You must delete and recreate the user.
Internal company users can continue to sign-in through Azure or login with cognito if needed (i.e. Azure goes down); a user account with "external_provider" will be created. Internal users using email + password will need to be/have been imported to the user pool; this will be two users within cognito, matching one in the database.
Region - "us-east-1"
Adding users to Cognito user pool
Users cannot sign themselves up with this tool.
Creating users with current pool settings
- set the username as the user email, select "Send an invitation to this new user?"
- no phone number needed, unselect "Mark phone number as verified?"
- set user email, select "Mark email as verified?"
Importing users - todo
Requirements
- Vue + Vuetify
- AWS Credentials - secret access key and access key id
- AWS Amplify
npm install -g @aws-amplify/cli
npm install aws-amplify
- app - AWS amplify -> kwikcatclient -> backend environments -> kktk
- AWS Cognito
- User Pool - "kktkpool-kktk"
- user pool Web App Client (app_clientWeb) (NO SECRET set on creation)
- User Pool - "kktkpool-kktk"
- Optional - Federated Sign in (SAML) (azure ad)
- azure app - Azure Portal -> Azure Active Directory -> App Registrations -> cognito-tk
- cognito user pool Domain Name set
Federated Sign In
Azure:
Azure Portal -> Azure Active Directory -> App Registrations ->
- Click "Endpoints" and copy "Federation metadata document"
- New Registration ->
- Add "Application ID URI" as "urn:amazon:cognito:sp:COGNITO POOL ID"
- new app/ cognito-tk -> Authentication
- Web platform with the Redirect URI as "FULL COGNITO DOMAIN NAME/saml2/idpresponse"
Cognito:
Federation ->
- Identity Providers -> SAML
- Enter "Federation metadata document" and the provider name with "Enable IdP sign out flow" checked, we are using "Azure"
- Attribute Mapping -> SAML -> "Azure"
- enter "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" as "SAML attribute" and select "email" from user pool attribute dropdown
App Integration -> App Client Settings -> app_clientWeb
- Enable Identity Providers
- Set callback & signout urls (examples: https://trackkat.com/, http://localhost:8000.com/)
- Enable authorization code (code)
- Allow any auth scopes but most importantly 'email'
From there you can launch Hosted UI to test if it's all working.
App
Amplify CLI
https://docs.amplify.aws/lib/auth/getting-started/q/platform/js
** You should use the CLI anytime a Cognito Pool ID OR "App Client" ID Changes if possible BE CAREFUL editting aws-exports.js manually. It will be overwritten when someone uses the CLI.
Be sure to check https://docs.amplify.aws/cli/reference/files#amplifyconfig on what files to commit. Don't commit aws-exports, instead update main.js Amplify.Configure for user pool related config.
# install
npm install -g @aws-amplify/cli
# pull OUR AMPLIFY APP
amplify pull --appId d18naine1f4qwi --envName kktk
# configure/sign in to AWS
amplify configure
# after install, run in project root
amplify init
# Unlink existing auth
amplify remove auth
# Create new Amplify-managed auth resources (create new user pool)
amplify add auth
# Update Amplify-managed auth resources (edit user pool, federation)
amplify update auth
# Use existing user pool
amplify import auth
# AFTER doing any of the above 4:
amplify push
amplify status
Using the CLI, you will be able to create all the necessary requirements to begin your authentication project (amplify app, cognito user+identity pool) or have the ability to set up a pre-existing project.
Quickstart
Step 1: Add plugin to /src/plugins/
Step 2: Add necessary imports to main.js. This will make the auth plugin and UI components (or simply auth) globally available
...
// Plug-in importing
import {DjangoAuth} from '@/auth'
// Dependencies
import Amplify from 'aws-amplify'
// AWS credentials
Amplify.configure({
Auth: {
region: 'us-east-1',
userPoolWebClientId: '4qnhq21pi6h1khdlni88vjpp45',
userPoolId: 'us-east-1_pr3KafRJD',
oauth: {
domain: 'pgm.auth.us-east-1.amazoncognito.com',
scope: [
'email',
'openid',
'profile',
'aws.cognito.signin.user.admin'
],
redirectSignIn: 'http://localhost:8001/',
redirectSignOut: 'http://localhost:8001/',
responseType: 'code'
}
}
})
Vue.use(DjangoAuth)
new Vue({})
...
Step 3: Wrap plugin and include in views
You can chose to include this in a dialog wrapper component and include in App.vue
This method was chosen for UI container flexibility (dialog, page, etc)
1 App Specific Wrapper (login)
Example dialog component
<template>
<v-dialog
persistent
max-width="450"
v-model="$store.getters.displayingLoginDialog"
@input="$emit('input', $event)"
>
<auth-card
:value="$store.getters.displayingLoginDialog"
@input="$store.commit('setLoginDialog', $event)"
@authenticated="authenticated"
/>
</v-dialog>
</template>
<script>
import AuthCard from '../plugins/auth/AuthCard.vue'
export default {
components: { AuthCard },
name: 'AuthWrapper'
methods: {
// Handle APP SPECIFIC user fetching & rerouting after success
authenticated () {
this.$store.dispatch('getUser').then(r => {
if (r) {
this.$store.commit('setLoginDialog', false)
this.$router.push({ name: 'dashboard' })
}
})
}
}
}
</script>
4 Login/Logout NavigationButtons.vue
// if not authenticated, allow login
<v-btn
text
v-if="!$auth.isAuthenticated"
@click="$store.commit('setLoginDialog', !$store.getters.displayingLoginDialog)"
>
Login
</v-btn>
// else logout
<v-list-item
@click="logout"
>
<v-list-item-title>
Logout
</v-list-item-title>
</v-list-item>
// script
methods: {
// logout
logout () {
// log out cognito session
this.$auth.logout().then(() => {
// handle APP SPECIFIC user state
this.$store.dispatch('logout')
// return to home back
if (this.$route.name !== 'home') this.$router.push({ name: 'home' })
})
}
}
5 App.vue
// APP SPECIFIC template
<login
:value="$store.getters.displayingLoginDialog"
@input="$store.commit('setLoginDialog', $event)"
/>
Step 6: Persist user state
We handle this in our router by using the router.beforeEach route guard + auth.isAuthenticated()
import {tokenAuth} from "@/plugins/auth";
const auth = tokenAuth()
router.beforeEach(async (to, from, next) => {
// try to get current session and user
if (!auth.isAuthenticated || (auth.isAuthenticated && !store.getters.currentUser)) {
try {
await auth.activeSession().then(() => {
store.dispatch('getUser').then(() => {
next()
})
})
return
} catch (err) {}
}
next()
})
User flows
Unauthenticated user
User initial login
- Users will receive an email with their login email and a temporary password on account creation
- User authentication successful, but the account requires a new password
Returns:
{ ChallengeName: "NEW_PASSWORD_REQUIRED", ChallengeParameters: { requiredAttributes: "[]", userAttributes: "{\"email_verified\":\"true\",\"email\":\"{useremail}\"}" }, Session: "" }
- Users will enter and confirm a new password
- Returns authentication results including a token and continues with login
Login
external user/traditional email + password sign in
Sends email & password to AWS to authenticate a user
If successful, reroutes user to dashboard, returns:
{ Credentials: { AccessKeyId: "" Expiration: " SecretKey: "" SessionToken: "" }, IdentityId: "" }
If unsuccessful, set error message
internal user
- Can choose between traditional sign in, or use Microsoft Azure AD federated sign-in
Password reset
- user enters email, and requests code
user then will enter the code, a new and confirmation password, returns authentication results and continues with login
You can also reset a users password from the user pool if they have logged in prior (not a first time login)
Authenticated user
Logout
- User clicks logout, their session is ended in cognito, user & session cleared in app state
Update Password
User enters old and new passwords and attempts to change password
If failed, sets error message
User Creation
- Create cognito users directly in the user pool by selecting "Create User" and setting the user email as username and email field. This is ideal for users that are pre-existing in our Database User Table or staff accounts.
- By a high level "admin" employee (must have KwikCat|kk profile|Add KK Profile permission) within the KWIKCAT-CLIENT project. This is ideal for "vendor" accounts. We use boto3 in our api for the account creation at this level. See kwikcat-client/src/components/AddUser
Components
AuthCard.vue
Primary auth component that wraps the other components for a seamless auth flow
components/SignIn.vue
User login fields and signin functionality
components/PasswordReset.vue
Provides logged-out user password reset functionality
components/UpdatePassword.vue
Provides fields for old password and new password for logged-in user password updating
components/PasswordFields.vue
Reusable New Password and Confirm Password fields
Resources
internal
aws
- https://console.aws.amazon.com/cognito/users/ - cognito user pool console
- https://console.aws.amazon.com/amplify/home amplify console
- https://docs.amplify.aws/cli/auth/overview amplify cli
- https://aws-amplify.github.io/amplify-js/api/classes/authclass.html amplify AUTH api
3 years ago