You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
title: Writing an Authentication Store in Svelte
slug: svelte-auth
category: tutorial
tags: ['Tech', 'Svelte', auth, AWS]
description: This is my attempt today wrapping an Authentication workflow into a Svelte Store
date: 2020-01-22
This is my attempt today wrapping an Authentication workflow into a Svelte Store, just like I did with Netlify Identity and React Hooks + Context. This example uses Amplify Auth, but really its going to be the exact same for any auth library/system.
⚠️Note: this is a backward reconstruction of my process, I have not doublechecked that I have accounted for every step of the process if you followed this tutorial from top down. Thinking caps on!
Originally I set out to try out Amplify's new DataStore, but quickly got sidetracked because it requires auth and there is no Amplify Svelte adaptor. So I embarked on a little bit of yak shaving to implement auth in a simple Svelte app.
I think the best way to start is to boot up a standard Svelte app:
npx degit sveltejs/template-webpack svelte-app # must use webpack, Amplify doesnt work with rollupcd svelte-app
npm install
npm run dev
And then follow some of the steps on Amplify's Auth docs:
Now lets actually wire up the submit handler to sign up the user:
<!-- src/Login.svelte --><script>import{store}from'./auth.js'importAuthfrom'@aws-amplify/auth';letusername=""letpassword=""letemail=""functionhandleSubmit(){Auth.signUp({
username,
password,attributes: {
email,},}).then(user=>{$store=user// save user object, representing a successful login})}</script><!-- etc -->
Ok, this lets us sign people up but then we also need to confirm the user. Amplify requires a two step signup process - a sign up and then a confirm step for 2FA verification (in this case, your email, but they also do SMS). Because this is Amplify specific, I'm going to handwave over it and ask you to look at my demo if you need details. It's gonna be dependent on whatever you actually end up using.
Showing Promise State
It's a good user experience to tell the user exactly what's going on with their login, while it happens. Svelte helps with this too with the super handy await syntax. The trick to this is assigning a promise to a variable, and then letting Svelte track/unroll the state of the promise as it goes inflight and results in either success or failure:
What we've made isn't really reusable. I like wrapping up reusable behavior in UI-less libraries - this was the original impetus behind hooks, which Merrick Christensen called Headless Components. This way, you get to reuse this code however you like with whatever UI you like. We're also mixing a lot of business logic into our Login component, and it might be nice to split it out a bit.
So lets revisit the store and do the move:
// src/auth.jsimport{writable}from'svelte/store';importAuthfrom'@aws-amplify/auth';exportconststore=writable(null);exportconstlogout=()=>store.set(null);exportasyncfunctionsignUp(username,password,email){returnAuth.signUp(username,password,email).then((data)=>voidstore.set(data));}// etc, as needed
Now I can import { logout, signUp } from './auth' anywhere in my app and use this logic!
Draw the rest of the Owl
Do more of the same for signing in an already signed up user.
Bonus: persisting state to localStorage
It can be annoying to lose the logged in user state on refresh. People expect their session to stick around. so you might want to sync up the user object to localStorage:
// src/auth.jsimport{writable}from'svelte/store';importAuthfrom'@aws-amplify/auth';let_user=localStorage.getItem('amplifyUser');exportconststore=writable(_user ? JSON.parse(_user) : null);store.subscribe((value)=>{if(value)localStorage.setItem('amplifyUser',JSON.stringify(value));elselocalStorage.removeItem('amplifyUser');// for logout});
Note some caveats - this may need an isomorphic wrapper if you are doing server side rendering, and that there are some security situations in which you should not store JWT's in localStorage. You can adapt your code to your needs but this will get you started.
That's all I've got - even getting here took longer than I thought! I hope to return to DataStore at some point but figured I would write up what I have.
title: Writing an Authentication Store in Svelte
slug: svelte-auth
category: tutorial
tags: ['Tech', 'Svelte', auth, AWS]
description: This is my attempt today wrapping an Authentication workflow into a Svelte Store
date: 2020-01-22
Chris Dhanaraj, one half of the AMAZING Toolsday duo with the equally talented Una Kravets, and serial mispronouncer of my name, recently schooled me that Svelte Stores are very similar to React Hooks. I objected at first, but Rich Harris confirmed he was right.
This is my attempt today wrapping an Authentication workflow into a Svelte Store, just like I did with Netlify Identity and React Hooks + Context. This example uses Amplify Auth, but really its going to be the exact same for any auth library/system.
Bottom Line Up Front
You can see my Live Demo here: https://d1tdmagl19vwso.cloudfront.net/
and the source code is at: https://github.com/sw-yx/svelte-amplify-auth-demo
Process - setup from Scratch
Originally I set out to try out Amplify's new DataStore, but quickly got sidetracked because it requires auth and there is no Amplify Svelte adaptor. So I embarked on a little bit of yak shaving to implement auth in a simple Svelte app.
I think the best way to start is to boot up a standard Svelte app:
And then follow some of the steps on Amplify's Auth docs:
You will also need to modify Svelte's root js page to use amplify's generated config files (adapting their Configuration docs):
You are now ready to add Svelte stores.
Adding a Svelte Store
Svelte stores are dead easy to use. I gave an Intro to Svelte Stores recently. You could also RTFM but where's the fun in that??
And so we have a two line store we can now use in our app. Let's also create a login component:
Here we are using two way binding and the
$
store autosubscribe syntax to make creating the form easy.Implementing logout is even easier:
and you can tie them together in your main app:
Adapting the Auth Library
Now lets actually wire up the submit handler to sign up the user:
Ok, this lets us sign people up but then we also need to confirm the user. Amplify requires a two step signup process - a sign up and then a confirm step for 2FA verification (in this case, your email, but they also do SMS). Because this is Amplify specific, I'm going to handwave over it and ask you to look at my demo if you need details. It's gonna be dependent on whatever you actually end up using.
Showing Promise State
It's a good user experience to tell the user exactly what's going on with their login, while it happens. Svelte helps with this too with the super handy await syntax. The trick to this is assigning a promise to a variable, and then letting Svelte track/unroll the state of the promise as it goes inflight and results in either success or failure:
You can test the rejection case works by assigning
Moving Logic into the Store
What we've made isn't really reusable. I like wrapping up reusable behavior in UI-less libraries - this was the original impetus behind hooks, which Merrick Christensen called Headless Components. This way, you get to reuse this code however you like with whatever UI you like. We're also mixing a lot of business logic into our Login component, and it might be nice to split it out a bit.
So lets revisit the store and do the move:
Now I can
import { logout, signUp } from './auth'
anywhere in my app and use this logic!Draw the rest of the Owl
Do more of the same for signing in an already signed up user.
Bonus: persisting state to localStorage
It can be annoying to lose the logged in user state on refresh. People expect their session to stick around. so you might want to sync up the user object to localStorage:
Note some caveats - this may need an isomorphic wrapper if you are doing server side rendering, and that there are some security situations in which you should not store JWT's in localStorage. You can adapt your code to your needs but this will get you started.
That's all I've got - even getting here took longer than I thought! I hope to return to DataStore at some point but figured I would write up what I have.
The text was updated successfully, but these errors were encountered: