A presentation at Serverless Chicago + Chicago NodeJS (April 2019) in in Chicago, IL, USA by Divya
Serverless Auth Strategies with Netlify Identity Divya Sasidharan @shortdiv
Why Authentication?
What is Authentication?
Login ??? Log Out Logged In
SSO MFA Silent Auth Social Login Passwordless
https://www.netlify.com/blog/ 2018/11/28/authentication-for-therest-of-us/
Netlify Identity
yarn add netlify-identity-widget
const netlifyIdentity = require(‘netlify-identity-widget’); netlifyIdentity.open(); const user = netlifyIdentity.currentUser(); netlifyIdentity.on(‘init’, user => { console.log(‘init’, user) }); netlifyIdentity.on(‘login’, user => { console.log(‘login’, user) }); netlifyIdentity.on(‘logout’, user => { console.log(‘logout’) }); netlifyIdentity.close();
const netlifyIdentity = require(‘netlify-identity-widget’); netlifyIdentity.open(); const user = netlifyIdentity.currentUser(); netlifyIdentity.on(‘init’, user => { console.log(‘init’, user) }); netlifyIdentity.on(‘login’, user => { console.log(‘login’, user) }); netlifyIdentity.on(‘logout’, user => { console.log(‘logout’) }); netlifyIdentity.close();
const netlifyIdentity = require(‘netlify-identity-widget’); netlifyIdentity.open(); const user = netlifyIdentity.currentUser(); netlifyIdentity.on(‘init’, user => { console.log(‘init’, user) }); netlifyIdentity.on(‘login’, user => { console.log(‘login’, user) }); netlifyIdentity.on(‘logout’, user => { console.log(‘logout’) }); netlifyIdentity.close();
const netlifyIdentity = require(‘netlify-identity-widget’); netlifyIdentity.open(); const user = netlifyIdentity.currentUser(); netlifyIdentity.on(‘init’, user => { console.log(‘init’, user) }); netlifyIdentity.on(‘login’, user => { console.log(‘login’, user) }); netlifyIdentity.on(‘logout’, user => { console.log(‘logout’) }); netlifyIdentity.close();
const netlifyIdentity = require(‘netlify-identity-widget’); netlifyIdentity.open(); const user = netlifyIdentity.currentUser(); netlifyIdentity.on(‘init’, user => { console.log(‘init’, user) }); netlifyIdentity.on(‘login’, user => { console.log(‘login’, user) }); netlifyIdentity.on(‘logout’, user => { console.log(‘logout’) }); netlifyIdentity.close();
Demo Time!
MUCH FUN SUCH FUNCTIONS
export function handler(event, context, callback) { console.log(event) callback(null, { statusCode: 200, body: JSON.stringify({msg: “Hello, World!”}) }) } src/lambda/hello.js
[build] command = “yarn build” functions = “lambda” publish = “dist” netlify.toml
/.netlify/functions/{function_name}
/.netlify/functions/login
Custom Webhooks API Call
Custom Webhooks API Call
netlifyIdentity.on(‘signup’, user => { axios({ url: /.identity/functions/login
, method: “GET” }) });
netlifyIdentity.on(‘signup’, user => { axios({ url: /.identity/functions/login
, method: “GET” }) });
Custom Webhooks API Call Automagic web hooks
validate signup login
export function handler(event, context, callback) { console.log(event) callback(null, { statusCode: 200, body: JSON.stringify({msg: “Hello, World!”}) }) } src/lambda/identity-login.js
exports.handler = function(event, context, callback) { const {identity, user} = context.clientContext; // do some stuff // callback(null, { statusCode: 200, body: JSON.stringify({ msg: “hello”}) }); };
exports.handler = function(event, context, callback) { const {identity, user} = context.clientContext; // do some stuff // callback(null, { statusCode: 200, body: JSON.stringify({ msg: “hello”}) }); };
exports.handler = function(event, context, callback) { const {identity, user} = context.clientContext; // do some stuff // callback(null, { statusCode: 200, body: JSON.stringify({ msg: “hello”}) }); };
exports.handler = function(event, context, callback) { const data = JSON.parse(event.body); const { user } = data; console.log(user.email); console.log(“identity yourself”, context.clientContext.identity); const validateUser = email => { if (email.split(“@”)[1] === “netlify.com”) { return [“editor”]; } else { return [“visitor”]; } }; const roles = validateUser(user.email); const responseBody = { app_metadata: { roles, my_user_info: “this is user info that the user can’t change from the UI” }, user_metadata: { …user.user_metadata, custom_data_from_function: “hurray this is some extra metadata” } }; }; callback(null, { statusCode: 200, body: JSON.stringify(responseBody) });
exports.handler = function(event, context, callback) { const data = JSON.parse(event.body); const { user } = data; console.log(user.email); console.log(“identity yourself”, context.clientContext.identity); const validateUser = email => { if (email.split(“@”)[1] === “netlify.com”) { return [“editor”]; } else { return [“visitor”]; } }; const roles = validateUser(user.email); const responseBody = { app_metadata: { roles, my_user_info: “this is user info that the user can’t change from the UI” }, user_metadata: { …user.user_metadata, custom_data_from_function: “hurray this is some extra metadata” } }; }; callback(null, { statusCode: 200, body: JSON.stringify(responseBody) });
exports.handler = function(event, context, callback) { const data = JSON.parse(event.body); const { user } = data; console.log(user.email); console.log(“identity yourself”, context.clientContext.identity); const validateUser = email => { if (email.split(“@”)[1] === “netlify.com”) { return [“editor”]; } else { return [“visitor”]; } }; const roles = validateUser(user.email); const responseBody = { app_metadata: { roles, my_user_info: “this is user info that the user can’t change from the UI” }, user_metadata: { …user.user_metadata, custom_data_from_function: “hurray this is some extra metadata” } }; }; callback(null, { statusCode: 200, body: JSON.stringify(responseBody) });
exports.handler = function(event, context, callback) { const data = JSON.parse(event.body); const { user } = data; console.log(user.email); console.log(“identity yourself”, context.clientContext.identity); const validateUser = email => { if (email.split(“@”)[1] === “netlify.com”) { return [“editor”]; } else { return [“visitor”]; } }; const roles = validateUser(user.email); const responseBody = { app_metadata: { roles, my_user_info: “this is user info that the user can’t change from the UI” }, user_metadata: { …user.user_metadata, custom_data_from_function: “hurray this is some extra metadata” } }; }; callback(null, { statusCode: 200, body: JSON.stringify(responseBody) });
exports.handler = function(event, context, callback) { const data = JSON.parse(event.body); const { user } = data; console.log(user.email); console.log(“identity yourself”, context.clientContext.identity); const validateUser = email => { if (email.split(“@”)[1] === “netlify.com”) { return [“editor”]; } else { return [“visitor”]; } }; const roles = validateUser(user.email); const responseBody = { app_metadata: { roles, my_user_info: “this is user info that the user can’t change from the UI” }, user_metadata: { …user.user_metadata, custom_data_from_function: “hurray this is some extra metadata” } }; }; callback(null, { statusCode: 200, body: JSON.stringify(responseBody) });
{ }; app_metadata: { roles, …user.app_metadata, my_user_info: “some user info” }, user_metadata: { …user.user_metadata, custom_data_from_function: “hurray extra metadata!” }
{ }; app_metadata: { roles, …user.app_metadata, my_user_info: “some user info” }, user_metadata: { …user.user_metadata, custom_data_from_function: “hurray extra metadata!” }
Demo Time!
What about local development?
Netlify Identity
GoTrue An SWT based API for managing users and issuing SWT tokens GoTrueJS
import GoTrue from “gotrue-js”; export const auth = new GoTrue({ APIUrl: “https://auth-to-know.com/.netlify/identity”, audience: “”, setCookie: false });
const attemptLogin = ({ commit, dispatch }, creds) => { return new Promise((resolve, reject) => { auth .login(creds.email, creds.password) .then(response => { resolve(response); commit(“SET_CURRENT_USER”, response); }) .catch(error => { reject(error.json); }); }); };
https://www.netlify.com/blog/ 2018/12/07/gotrue-js—-bringingauthentication-to-static-sites-withjust-3kb-of-js/
! serverless chicago https://noti.st/shortdiv Divya Sasidharan @shortdiv
Authentication is often a complex concept and integrating it into apps can require a lot of effort, especially for those not used to the mechanics of securing apps. In the past authentication used to be something reserved for the backend, but the frontend is more feature rich and authentication is now a necessary concept to understand when building a robust client-side application. In this talk, we will cover the various pieces that makeup authentication as well as strategies to integrate authentication, specifically Netlify Identity, seamlessly into your serverless workflows.