Serverless Authentication with AWS Amplify and Vuex Modules
Services like Auth0 and Firebase have been the go-to for serverless authentication, but now you have an option that lets you stay within the AWS Stack: AWS Amplify. Now it’s a lot easier to get some of the great AWS services on the client (securing storage with ease, Secure Lambda API calls with API Gateway, etc). Amplify has two main benefits:
- The
Amplify-CLI
will generate all the security and permissions automatically avoiding a lot of manual setup - It comes with libraries to interact with the AWS stack on the client side in multiple languages and UI frameworks
You can use the Amplify Vue components on top of the core library which should handle most use cases. If you do decide to build your own components, it is probably for one of the following reasons:
- Utilize an already loaded UI framework
- Full customization of the experience
- The components don’t support your requirements
- You like to control all-the-things
Customize your own authentication components
This article will:
- Walk through the authentication/Cognito setup
- Show a Vuex module for interacting with Cognito
- Provide an example component to handle sign-in
How this example works
- Users log in with an email for a username
- Users must signup and confirm email address before logging in
Setting up AWS Amplify
For full customization, we will need to add our own user pool, but first use the client to set up all the permissions and services.
- Setup the AWS Amplify Cli (
@aws-amplify/cli
) - Initiate your Amplify project
amplify init
- Make sure you are in the desired AWS region
- Add a (temporary) Authentication/Cognito service
amplify add auth
- Add any other services you want to use ie:
Storage
- Push your project
amplify push
Now we can setup AWS Cognito
- Login to AWS Cognito, selection the region, and Create a
User Pool
with the desired settings - You probably will want to customize the User Pool
email verification messages
since this solution requires email confirmation - In User Pool settings go to the
App clients
link and clickAdd another app client
- Create an app client but uncheck
Generate client secret
since this only applies to server-to-server communication:
Setting up Amplify on the Client
Amplify will generate an aws-exports.js
file but we can’t rely on it not getting overwritten, also you should add it to your .gitignore
for security. In your main.js
file add the amplify dependencies:
For the purpose of this demo I am placing secrets in code, never add this to your repo, use environment variables and secret storage.
Account Vuex Module Example
This Vuex module will do all the heavy lifting so your components deal with an easy API and you can easily check on the users’ authenticated state.
When a user logs in, a timer is set to automatically refresh the token when it expires.
Vuex Module Explained
State Variables:
authorized
A boolean you can check if a user is authorized ($store.state.account.authorized
)user
An object of the user's informationloginError
A string containing the Cognito response on an invalid login attemptsignupError
A string containing the Cognito response on an invalid signup attemptconfirm
Boolean indicating if the user wants to confirm their email address. This can happen right after signup or if a user comes back later.confirmError
A string containing the Cognito response on an invalid email confirmation
Module Usage:
These 3 module actions trigger the AWS Amplify Authentication/Cognito Service.
Other Actions
fetchUser
attempts to refresh theuser
state from Cognito. Should only call once on application initialize, or if you want to refresh the tokenlogout
will ensure the user has logged out
Handling Authentication Changes:
Most cases will require logic run when a user gets logged in or out. You can add this to main.js
or app.vue
then choose to redirect the user, load components, etc on change.
Fetching the JWT (JSON Web Token)
You may need to obtain the JWT
for interacting with a server or API. Here is some example code to fetch it:
The state is passed to the method purely to check if the user is currently authorized, this can be handled differently.
Extending Authentication to a Server API
Very soon I will release an article on:
- Using Axios including attaching authorization headers
- Express middleware for authorizing API requests
- Auto handling expired tokens
A Complete Sign-in Component Using Vuetify
This lengthy example component handles all operations on one page (login, signup, and email validation).
This would be easy to customize for your Cognito setup and port to Bootstrap/Element/whatever framework you use.
Component Notes
- The
section
component is a simple card view with a title - I attempt to turn off browser autocomplete
Computed Confirmation Value From State.account
The computed confirmation variable tells the sign-in component if the user wants to confirm their email address (with the verification code sent). This happens when the user has just signed up or when the user has returned from checking their email for the verification code. Once verified, the user can log in.
Error Handling
There are two levels of error handling:
- If the field rules are not passed when submitting forms
- Errors passed by the Amplify library from the Cognito Service
The errors are then displayed on the components until a successful submittal.
That’s all for now, let me know if I am missing something or you want more information on anything.