A presentation at Nation JS in in Washington, DC, USA by Divya
THE INTERNET IN THE BEGINNING… username username username ••••••••••• ••••••••••• username username ••••••••••• ••••••••••• username ••••••••••• ••••••••••• ••••••••••• username ••••••••••• username username ••••••••••• ••••••••••• username username username ••••••••••• username ••••••••••• ••••••••••• username username ••••••••••• usern usern ••••••••••• ••••••• ••••••• username ••••••••••• username username ••••••••••• ••••••••••• username username ••••••••••• ••••••••••• username username ••••••••••• username ••••••••••• •••••••••••
THE INTERNET IN THE BEGINNING…
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVC J9.eyJhcHBfbWV0YWRhdGEiOnsiYXV0aG9 yaXphdGlvbiI6eyJyb2xlcyI6WyJhZG1pb iIsImVkaXRvciJdfX19.4IKFHH33EXWseN jNIRO4-u5IlSlJOLyibG20qPA4Djs ????????? ????????? ?????????
Authentication for the REST of us Divya Sasidharan @shortdiv
works here Divya Sasidharan
WHY DOES IT MATTER? INTRODUCTION SECURITY STRATEGIES WHERE AUTHENTICATION WHAT WHO WHY WHEN HOW DON’T PANIC AUTHENTICATION INTRODUCTION
INTRODUCTION SECURITY STRATEGIES AUTHENTICATION DON’T PANIC AUTHENTICATION WHO WHAT WHY WHERE WHEN HOW INTRODUCTION WHY DOES IT MATTER?
WHY DOES IT MATTER? AUTHENTICATION WHY DOES IT MATTER?
AUTHENTICATION WHY DOES IT MATTER?
AUTHENTICATION WHY DOES IT MATTER?
AUTHENTICATION
CHARACTERISTICS HISTORY HOW TO HAVE FUN WITH AUTHORIZATION HOW TO NOT CONFUSE YOURSELF WHAT TO AVOID AUTHENTICATION
AUTHORIZATION AUTHENTICATION AUTHORIZATION
AUTHENTICATION AUTHORIZATION User Authenticated: Hitchhiker
AUTHENTICATION AUTHORIZATION ERROR: Hitchhiker NOT AUTHORIZED
AUTHENTICATION AUTHORIZATION
HOW IT WORKS AUTHENTICATION
AUTHENTICATION HOW IT WORKS username •••••••••••
AUTHENTICATION HOW BASIC IT WORKS AUTH Username: FPrefect Password: thisisn0t@dri11 1 RlByZWZlY3Q6dGhpc2lzbjB0QGRya 2 TEx
AUTHENTICATION HOW IT WORKS Username:Password FPrefect:thisisn0t@dri11 Authorization: Basic RlByZWZlY3Q6dGhpc2lzbjB0 QGRyaTEx BASIC AUTH { 3 “id”:”89765-1”, “role”:”hitchhiker”, “email”:”ford@infinidim.com”, … 4 }
AUTHENTICATION HOW IT WORKS BASIC AUTH { “id”:”89765-1”, “role”:”hitchhiker”, “email”:”ford@infinidim.com”, … Authorization: Basic RlByZWZlY3Q6dGhpc2lzbjB0 QGRyaTEx }
AUTHENTICATION HOW IT WORKS BASIC AUTH
AUTHENTICATION HOW IT WORKS BASIC AUTH
AUTHENTICATION SESSION HOWBASED IT WORKS AUTH Username: FPrefect Password: thisisn0t@dri11 1 2 setcookie:hiker=“SESSION_ID; path=/; Secure; HttpOnly; SameSite”
AUTHENTICATION HOW IT WORKS SESSION BASED AUTH { cookie:“hiker=XHTGubdsnHFJ 3 KHHJGFJHGKHhgjgJHNJGHGJHjs ddsBHJGGFJKHtcbjBUY” “id”:”89765-1”, “role”:”hitchhiker”, “email”:”ford@infinidim.com”, … 4 }
AUTHENTICATION HOW IT WORKS SESSION BASED AUTH
AUTHENTICATION HOW IT WORKS SESSION BASED AUTH
AUTHENTICATION TOKEN HOW BASED IT WORKS AUTH SESSION BASED AUTH
AUTHENTICATION HOW IT WORKS Username: FPrefect Password: thisisn0t@dri11 1 TOKEN BASED AUTH eyJhbGciOiJIUzI1NiIsInR5cCI6I kpXVCJ9.eyJuYW1lIjoiRm9yZCBQc mVmZWN0Iiwic3ViIjoiZm9yZEBpbm ZpbmlkaW0uY29tIiwiaWF0IjoxNTE 2 2MjM5MDIyLCJhcHBfbWV0YWRhdGEi OnsiYXV0aG9yaXphdGlvbiI6eyJyb 2xlcyI6WyJqb3VybmFsaXN0Il19fX 0.0eXsZauX7hjEB9oGjx7cg6LdyU8 QzNnFFS7tevWnqCA
AUTHENTICATION HOW IT WORKS Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5c CI6IkpXVCJ9.eyJuYW1lIjoiR m9yZCBQcmVmZWN0Iiwic3ViIj oiZm9yZEBpbmZpbmlkaW0uY29 tIiwiaWF0IjoxNTE2MjM5MDIy LCJhcHBfbWV0YWRhdGEiOnsiY XV0aG9yaXphdGlvbiI6eyJyb2 xlcyI6WyJqb3VybmFsaXN0Il1 9fX0.0eXsZauX7hjEB9oGjx7c g6LdyU8QzNnFFS7tevWnqCA TOKEN BASED AUTH { 3 “id”:”89765-1”, “role”:”hitchhiker”, “email”:”ford@infinidim.com”, … 4 }
JWT AUTHENTICATION HOW IT WORKS TOKEN BASED AUTH
AUTHENTICATION TOKEN BASED AUTH JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ 9.eyJuYW1lIjoiRm9yZCBQcmVmZWN0Iiwic 3ViIjoiZm9yZEBpbmZpbmlkaW0uY29tIiwi aWF0IjoxNTE2MjM5MDIyLCJhcHBfbWV0YWR hdGEiOnsiYXV0aG9yaXphdGlvbiI6eyJyb2 xlcyI6WyJqb3VybmFsaXN0Il19fX0.0eXsZ auX7hjEB9oGjx7cg6LdyU8QzNnFFS7tevWn qCA
AUTHENTICATION TOKEN BASED AUTH JWT signature payload header eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ 9.eyJuYW1lIjoiRm9yZCBQcmVmZWN0Iiwic 3ViIjoiZm9yZEBpbmZpbmlkaW0uY29tIiwi aWF0IjoxNTE2MjM5MDIyLCJhcHBfbWV0YWR hdGEiOnsiYXV0aG9yaXphdGlvbiI6eyJyb2 xlcyI6WyJqb3VybmFsaXN0Il19fX0.0eXsZ auX7hjEB9oGjx7cg6LdyU8QzNnFFS7tevWn qCA
AUTHENTICATION { } { } TOKEN BASED AUTH JWT “alg”: “HS256”, “typ”: “JWT” “name”: “Ford Prefect”, “sub” : “ford@infinidim.com”, “exp” : “1577836800”, “app_metadata”: { “authorization”: { “roles”: [ “journalist” ] } }, header
AUTHENTICATION { } { } TOKEN BASED AUTH JWT “alg”: “HS256”, RS256 “typ”: “JWT” “name”: “Ford Prefect”, “sub” : “ford@infinidim.com”, “exp” : “1577836800”, “app_metadata”: { “authorization”: { “roles”: [ “journalist” ] } }, header
AUTHENTICATION { } { } TOKEN BASED AUTH JWT “alg”: “HS256”, “typ”: “JWT” “name”: “Ford Prefect”, “sub” : “ford@infinidim.com”, “exp” : “1577836800”, “app_metadata”: { “authorization”: { “roles”: [ “journalist” ] } }, header
AUTHENTICATION { } { } { TOKEN BASED AUTH JWT “alg”: “HS256”, “typ”: “JWT” “name”: “Ford Prefect”, “sub” : “ford@infinidim.com”, “exp” : “1577836800”, “app_metadata”: { “authorization”: { “roles”: [ “journalist” ] } }, payload
“name”: “Ford Prefect”, “sub” : “ford@infinidim.com”, JWT AUTHENTICATION TOKEN BASED AUTH “exp” : “1577836800”, “app_metadata”: { “authorization”: { “roles”: [ “journalist” ] } }, } { HMACSHA256( base64UrlEncode(header) + “.” + base64UrlEncode(payload), a-256-bit-super-secret-secret) } signature
AUTHENTICATION TOKEN BASED AUTH JWT
AUTHENTICATION TOKEN BASED AUTH JWT
CHARACTERISTICS HISTORY HOW TOIMPLEMENTATION HAVE FUN WITH HOW TO NOT CONFUSE YOURSELF WHAT TO AVOID AUTHENTICATION TOKEN BASED AUTH
CHARACTERISTICS HISTORY HOW TO HAVE FUN WITH HOW TO NOT CONFUSE YOURSELF WHAT TO AVOID AUTHENTICATION TOKEN BASED AUTH IMPLEMENTATION
AUTHENTICATION TOKEN BASED AUTH DEMO IMPLEMENTATION
AUTHENTICATION TOKEN BASED AUTH IMPLEMENTATION Auth Server Username: FPrefect Password: thisisn0t@dri11 Authorization: Bearer eyJhbGciOJ9.sfsfweHsefw9 .dgergeJGhg9HV… eyJhbGciOJ9.sfsfweHsefw9 .dgergeJGhg9HV… { “id”:”89765-1”, “role”:”hitchhiker”, … } Resource Server
AUTHENTICATION TOKEN BASED AUTH IMPLEMENTATION
AUTHENTICATION TOKEN BASED AUTH IMPLEMENTATION Authentication with Functions as a Service |—————-| | THERE | | ARE | | STILL | | SERVERS | | IN | | SERVERLESS| |—————-| (_/) || (•ㅅ•) || / づ |—————-| | THERE | | ARE | | STILL | | SERVERS | | IN | | SERVERLESS| |—————-| (_/) || (•ㅅ•) || / づ |—————-| | THERE | | ARE | | STILL | | SERVERS | | IN | | SERVERLESS| |—————-| (_/) || (•ㅅ•) || / づ |—————-| | THERE | | ARE | | STILL | | SERVERS | | IN | | SERVERLESS| |—————-| (_/) || (•ㅅ•) || / づ
AUTHENTICATION TOKEN BASED AUTH IMPLEMENTATION
AUTHENTICATION TOKEN BASED AUTH IMPLEMENTATION MYAWESOMESITE.netlify.com/.netlify/functions/jwt
AUTHENTICATION TOKEN BASED AUTH IMPLEMENTATION 56 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 const jwt = require(“jsonwebtoken”); const uuidv4 = require(“uuid/v4”); const axios = require(“axios”); exports.handler = function(event, context, callback) { const getExpiryDate = () => { const exp = Math.floor(Date.now() / 1000) + 60 * 60; // const expReadable = new Date(exp); return exp; }; const generateJWT = (exp, claims, roles, secret) => jwt.sign( { exp, app_metadata: { user_id: uuidv4(), authorization: { roles } }, user_metadata: claims }, secret ); const parsedBody = JSON.parse(event.body); const { claims, roles, secret } = parsedBody;
1 const jwt = require(“jsonwebtoken”); 2 const uuidv4 = require(“uuid/v4”); IMPLEMENTATION AUTHENTICATION TOKEN BASED AUTH 3 const axios = require(“axios”); 4 5 exports.handler = function(event, context, callback) { const getExpiryDate = () => { 6 const exp = Math.floor(Date.now() / 1000) + 60 * 60; 7 // const expReadable = new Date(exp); 8 return exp; 9 }; 10 const generateJWT = (exp, claims, roles, secret) => 11 jwt.sign( 12 { 13 exp, 14 app_metadata: { 15 user_id: uuidv4(), 16 authorization: { roles } 17 }, 18 user_metadata: claims 19 }, 20 secret 21 ); 22 const parsedBody = JSON.parse(event.body); 23 const { claims, roles, secret } = parsedBody; 24 25 const expiry = getExpiryDate(); 26 const token = generateJWT(expiry, claims, roles, secret); 27 28 const response = { 29
}, 18 user_metadata: claims 19 }, 20 IMPLEMENTATION TOKEN BASED AUTH secret 21AUTHENTICATION ); 22 const parsedBody = JSON.parse(event.body); 23 const { claims, roles, secret } = parsedBody; 24 25 const expiry = getExpiryDate(); 26 const token = generateJWT(expiry, claims, roles, secret); 27 28 const response = { 29 jwt: token, 30 }; 31 32 callback(null, { 33 statusCode: 200, 34 body: JSON.stringify(response) 35 }); 36 37 }; 38 39 40 41 42 43 44 45 46 47
1 const jwt = require(“jsonwebtoken”); 2 const uuidv4 = require(“uuid/v4”); 3 const axios = require(“axios”); IMPLEMENTATION AUTHENTICATION TOKEN BASED AUTH 4 5 exports.handler = function(event, context, callback) { const getExpiryDate = () => { 6 7 // const expReadable = new Date(exp); 8 return exp; 9 }; 10 const generateJWT = (exp, claims, roles, secret) => 11 jwt.sign( 12 { 13 exp, 14 app_metadata: { 15 user_id: uuidv4(), 16 authorization: { roles } 17 }, 18 user_metadata: claims 19 }, 20 secret 21 ); 22 const parsedBody = JSON.parse(event.body); 23 const { claims, roles, secret } = parsedBody; 24 25 const expiry = getExpiryDate(); 26 const token = generateJWT(expiry, claims, roles, secret); 27 28 const response = { 29 jwt: token, 30
1 const jwt = require(“jsonwebtoken”); 2 const uuidv4 = require(“uuid/v4”); 3 const axios = require(“axios”); IMPLEMENTATION AUTHENTICATION TOKEN BASED AUTH 4 5 exports.handler = function(event, context, callback) { const getExpiryDate = () => { 6 const exp = Math.floor(Date.now() / 1000) + 60 * 60; 7 // const expReadable = new Date(exp); 8 return exp; 9 }; 10 const generateJWT = (exp, claims, roles, secret) => 11 jwt.sign( 12 { 13 exp, 14 app_metadata: { 15 user_id: uuidv4(), 16 authorization: { roles } 17 }, 18 user_metadata: claims 19 }, 20 secret 21 ); 22 const parsedBody = JSON.parse(event.body); 23 const { claims, roles, secret } = parsedBody; 24 25 const expiry = getExpiryDate(); 26 const token = generateJWT(expiry, claims, roles, secret); 27 28 const response = { 29 jwt: token, 30
}, 18 user_metadata: claims 19 }, 20 IMPLEMENTATION AUTHENTICATION TOKEN BASED AUTH secret 21 ); 22 const parsedBody = JSON.parse(event.body); 23 const { claims, roles, secret } = parsedBody; 24 25 const expiry = getExpiryDate(); 26 const token = generateJWT(expiry, claims, roles, secret); 27 28 const response = { 29 jwt: token, 30 }; 31 32 callback(null, { 33 statusCode: 200, 34 body: JSON.stringify(response) 35 }); 36 37 }; 38 39 40 41 42 43 44 45 46 47
AUTHENTICATION
TOKEN BASED AUTH
IMPLEMENTATION
56 1 fetch(“/.netlify/functions/jwt”).then(res => { 2 fetch(“/.netlify/functions/super-secret-function”, { 3 method: “POST”, 4 headers: { 5 “Authorization”: Bearer ${res.jwt}
6 }, 7 body: JSON.stringify({ 8 text: someDataIWanttoPost 9 }) 10 }) 11 }) 12 13 14 15 16 17 18 19 20 21 22 23 24
AUTHENTICATION TOKEN BASED AUTH IMPLEMENTATION Auth Server Username: FPrefect Password: thisisn0t@dri11 Authorization: Bearer eyJhbGciOJ9.sfsfweHsefw9 .dgergeJGhg9HV… eyJhbGciOJ9.sfsfweHsefw9 .dgergeJGhg9HV… { “id”:”89765-1”, “role”:”hitchhiker”, … } Resource Server
AUTHENTICATION TOKEN BASED AUTH IMPLEMENTATION Auth Server Username: FPrefect Password: thisisn0t@dri11 cookie:“hiker=XHTGubdsnH FJKHHJGFJHGKHhgjgJHNJGHG JHjsddsBHJGGFJKHtcbjBUY” setcookie:hiker=“eyJhbGciOJ 9.sfsfweHsefw9.dgergeJGh g9HV…; path=/; Secure; HttpOnly; SameSite” { “id”:”89765-1”, “role”:”hitchhiker”, … } Resource Server
AUTHENTICATION TOKEN BASED AUTH IMPLEMENTATION 56 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 const const const const jwt = require(“jsonwebtoken”); uuidv4 = require(“uuid/v4”); cookie = require(“cookie”); axios = require(“axios”); exports.handler = function(event, context, callback) { const getExpiryDate = () => { const exp = Math.floor(Date.now() / 1000) + 60 * 60; // const expReadable = new Date(exp); return exp; }; const generateJWT = (exp, claims, roles, secret) => jwt.sign( { exp, app_metadata: { user_id: uuidv4(), authorization: { roles } }, user_metadata: claims }, secret ); const parsedBody = JSON.parse(event.body);
secret 22 ); 23 const parsedBody = JSON.parse(event.body); 24 IMPLEMENTATION TOKEN BASED const { claims, roles, secret } = AUTH parsedBody; 25AUTHENTICATION 26 const expiry = getExpiryDate(); 27 const token = generateJWT(expiry, claims, roles, secret); 28 29 const netlifyCookie = cookie.serialize(“nf_jwt”, token, { 30 secure: true, 31 path: “/”, 32 expires: new Date(expiry.toString()) 33 }); 34 35 const response = { 36 jwt: token, 37 exp: expiry 38 }; 39 40 callback(null, { 41 statusCode: 200, 42 headers: { 43 “Set-Cookie”: netlifyCookie, 44 “Cache-Control”: “no-cache” 45 }, 46 body: JSON.stringify(response) 47 }); 48 49 }; 50 51
secret 22 ); 23 const parsedBody = JSON.parse(event.body); 24 IMPLEMENTATION TOKEN BASED const { claims, roles, secret } = AUTH parsedBody; 25AUTHENTICATION 26 const expiry = getExpiryDate(); 27 const token = generateJWT(expiry, claims, roles, secret); 28 29 const netlifyCookie = cookie.serialize(“nf_jwt”, token, { 30 secure: true, 31 path: “/”, 32 expires: new Date(expiry.toString()) 33 }); 34 35 const response = { 36 jwt: token, 37 exp: expiry 38 }; 39 40 callback(null, { 41 statusCode: 200, 42 headers: { 43 “Set-Cookie”: netlifyCookie, 44 “Cache-Control”: “no-cache” 45 }, 46 body: JSON.stringify(response) 47 }); 48 49 }; 50 51
AUTHENTICATION TOKEN BASED AUTH DEMO IMPLEMENTATION
AUTHENTICATION TOKEN BASED AUTH IMPLEMENTATION
AUTHENTICATION TOKEN BASED AUTH IMPLEMENTATION auth.js export const state = { … } export const mutations = { … } export const actions = { … } export const getters = { … } src/state/auth.js
AUTHENTICATION 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 TOKEN BASED AUTH IMPLEMENTATION import GoTrue from “gotrue-js”; import axios from “axios”; const auth = new GoTrue({ APIUrl: “https://chipie.netlify.com/.netlify/identity”, audience: “”, setCookie: false }); export const state = { currentUser: getSavedState(“auth.currentUser”), loading: false, token: null, notifications: [] }; export const mutations = { SET_CURRENT_USER(state, value) { state.currentUser = value; saveState(“auth.currentUser”, value); }, TOGGLE_LOAD(state) { state.loading = !state.loading;
AUTHENTICATION 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 C TOKEN BASED AUTH IMPLEMENTATION import GoTrue from “gotrue-js”; import axios from “axios”; const auth = new GoTrue({ APIUrl: “https://chipie.netlify.com/.netlify/identity”, audience: “”, C setCookie: false }); export const state = { currentUser: getSavedState(“auth.currentUser”), loading: false, token: null, notifications: [] }; export const mutations = { SET_CURRENT_USER(state, value) { state.currentUser = value; saveState(“auth.currentUser”, value); }, TOGGLE_LOAD(state) { state.loading = !state.loading;
isLoggedIn(state) { 27 return !!state.currentUser; 28 C } 29AUTHENTICATION IMPLEMENTATION TOKEN BASED AUTH 30 }; 31 32 export const actions = { init() { 33 localStorage.removeItem(“auth.currentUser”); 34 }, 35 validate({ commit, state }) { 36 if (!state.currentUser) return Promise.resolve(null); 37 const user = auth.currentUser(); 38 commit(“SET_CURRENT_USER”, user); 39 return user; 40 }, 41 attemptLogin({ commit, dispatch }, credentials) { 42 return new Promise((resolve, reject) => { 43 dispatch(“attemptConfirmation”, credentials).then(() => { 44 auth 45 .login(credentials.email, credentials.password) 46 .then(response => { 47 resolve(response); 48 commit(“SET_CURRENT_USER”, response); 49 }) 50 .catch(error => { 51 reject(error.json); 52 }); 53 }); 54 }); 55 }, 56
isLoggedIn(state) { 27 return !!state.currentUser; 28 C } 29AUTHENTICATION IMPLEMENTATION TOKEN BASED AUTH 30 }; 31 32 export const actions = { init() { 33 localStorage.removeItem(“auth.currentUser”); 34 }, 35 validate({ commit, state }) { 36 if (!state.currentUser) return Promise.resolve(null); 37 const user = auth.currentUser(); 38 commit(“SET_CURRENT_USER”, user); 39 return user; 40 }, 41 attemptLogin({ commit, dispatch }, credentials) { 42 return new Promise((resolve, reject) => { 43 dispatch(“attemptConfirmation”, credentials).then(() => { 44 C auth 45 C .login(credentials.email, credentials.password) 46 .then(response => { 47 resolve(response); 48 commit(“SET_CURRENT_USER”, response); 49 C }) 50 .catch(error => { 51 reject(error.json); 52 }); 53 }); 54 }); 55 }, 56
11 loading: false, 12 token: null, 13 notifications: [] IMPLEMENTATION TOKEN BASED AUTH 14AUTHENTICATION }; 15 16 export const mutations = { 17 SET_CURRENT_USER(state, value)C{ 18 state.currentUser = value; C 19 saveState(“auth.currentUser”, value); 20 }, 21 TOGGLE_LOAD(state) { 22 state.loading = !state.loading; 23 } 24 }; 25 26 export const getters = { 27 isLoggedIn(state) { 28 return !!state.currentUser; 29 } 30 }; 31 32 export const actions = { 33 init() { 34 localStorage.removeItem(“auth.currentUser”); 35 }, 36 validate({ commit, state }) { 37 if (!state.currentUser) return Promise.resolve(null); 38 const user = auth.currentUser(); 39 commit(“SET_CURRENT_USER”, user); 40 return user;
56AUTHENTICATION TOKEN BASED AUTH IMPLEMENTATION 1 <template> 2 <div class=”login-screen”> 3 <div class=”account-login”> 4 <form @submit.prevent=”login()”> 5 <label> 6 <span>Email:</span> 7 <input 8 type=“text” 9 placeholder=“name” 10 v-model=“loginCreds.email” 11 /> 12 </label> 13 <label> 14 <span>Password:</span> 15 <input 16 type=”password” 17 placeholder=”password” 18 v-model=“loginCreds.password” 19 /> 20 </label> 21 <button type=”submit” class=“account-button”>Login</button> 22 </form> 23 </div> 24 </div> 25 </template>
56AUTHENTICATION TOKEN BASED AUTH IMPLEMENTATION 1 <template> 2 <div class=”login-screen”> 3 <div class=”account-login”> 4 <form @submit.prevent=”login()”> 5 <label> 6 <span>Email:</span> 7 <input 8 type=“text” 9 placeholder=“name” 10 v-model=“loginCreds.email” 11 /> 12 </label> 13 <label> 14 <span>Password:</span> 15 <input 16 type=”password” 17 placeholder=”password” 18 v-model=“loginCreds.password” 19 /> 20 </label> 21 <button type=”submit” class=“account-button”>Login</button> 22 </form> 23 </div> 24 </div> 25 </template>
22 </form> 23 </div> 24 </div> IMPLEMENTATION AUTHENTICATION TOKEN BASED AUTH 25 </template> 26 27 <script> 28 import { mapActions } from “vuex”; 29 30 export default { name: “LoginAccount”, 31 data() { 32 return { 33 isNewUser: true, 34 loginCreds: { 35 email: null, 36 password: null 37 } 38 } 39 }, 40 methods: { 41 …mapActions(“auth”, [“attemptLogin”]), 42 transferToDashboard() { 43 this.$router.push(this.$route.query.redirect || “/”); 44 }, 45 login() { 46 let token = decodeURIComponent(window.location.search) 47 .substring(1) 48 .split(“confirmation_token=”)[1]; 49 this.attemptLogin({ token, …this.loginCreds }) 50 .then(res => { 51
34 isNewUser: true, 35 loginCreds: { 36 email: null, IMPLEMENTATION 37AUTHENTICATION password: nullTOKEN BASED AUTH 38 } 39 } 40 }, 41 methods: { 42 …mapActions(“auth”, [“attemptLogin”]), 43 transferToDashboard() { 44 this.$router.push(this.$route.query.redirect || “/”); 45 }, 46 login() { 47 let token = decodeURIComponent(window.location.search) 48 .substring(1) 49 .split(“confirmation_token=”)[1]; 50 this.attemptLogin({ token, …this.loginCreds }) 51 .then(res => { 52 this.transferToDashboard(); 53 }) 54 .catch(err => { 55 console.log(err); 56 }); 57 }, 58 } 59 } 60 </script> 61 62 63
34 isNewUser: true, 35 loginCreds: { 36 email: null, IMPLEMENTATION AUTHENTICATION TOKEN BASED AUTH 37 password: null 38 } 39 } 40 }, 41 methods: { 42 …mapActions(“auth”, [“attemptLogin”]), 43 transferToDashboard() { 44 this.$router.push(this.$route.query.redirect || “/”); 45 }, 46 login() { 47 let token = decodeURIComponent(window.location.search) 48 .substring(1) 49 .split(“confirmation_token=”)[1]; 50 this.attemptLogin({ token, …this.loginCreds }) 51 .then(res => { 52 this.transferToDashboard(); 53 console.log(res); 54 }) 55 .catch(err => { 56 console.log(err); 57 }); 58 }, 59 } 60 } 61 </script> 62 63
AUTHENTICATION HOW IT WORKS IMPLEMENTATION
AUTHENTICATION HOW IT WORKS IMPLEMENTATION
AUTHENTICATION DON’T ROLL YOUR OWN Passwordless MFA SSO Centralized Auth Social Login
AUTHENTICATION DON’T ROLL YOUR OWN Passwordless MFA SSO Centralized Auth Social Login
AUTHENTICATION LINKS AND THINGS Roll your own JWT code: https://github.com/shortdiv/jwt-generate example: https://login-to-gated-site.netlify.com/ Identity Example code: https://github.com/shortdiv/gotruejs-in-vue example: https://netlify-gotrue-in-vue.netlify.com/
So Long and Thanks for All the Auth!!! Divya Sasidharan @shortdiv
Auth is a a daunting concept to grok, especially for the uninitiated. In addition to the many authentication strategies to choose from, there are also many cloud based authentication services available. Deciding the best authentication strategy for your application can be an incredibly overwhelming decision. In this session, we journey through the steps of securing a web application by taking a bare bones web application and progressively adding authentication to it. In the process of adding authentication, we will demystify the wonderful world of web authentication to take our web security skills to the next level!
In addition to covering a real world example, I will be covering simple tools and techniques you can use to start integrating authentication into applications without the stress.