• Stars
    star
    137
  • Rank 265,293 (Top 6 %)
  • Language
    JavaScript
  • Created about 6 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

How to handle authentication with serverless functions

Serverless Auth strategies

How do we keep certain functions protected & scoped down to specific users (i.e. admin/paid users)?

This will walk through the different strategies available for authorizing access to your functions.

The code in this repo covers primarily AWS lambda functions but these strategies can apply to any FAAS provider.

Pick your auth provider

There are a boatload of services that provide out of the box auth for your app. It's recommended to use one of these mainly because it's quite easy to mess up some piece of the security chain rolling your own auth.

Some options out there include:

Choose a strategy

There are many ways to protect for your functions. The list below will walk through them and the pros/cons of each.

1. Inline auth checking

Inlined function authentication happens inside your function code

We do a check on the auth headers or the body of the request to verify the user is okay to access the function.

const checkAuth = require('./utils/auth')

exports.handler = (event, context, callback) => {
  // Use the event data auth header to verify
  checkAuth(event).then((user) => {
    console.log('user', user)
    // Do stuff
    return callback(null, {
      statusCode: 200,
      body: JSON.stringify({
        data: true
      })
    })
  }).catch((error) => {
    console.log('error', error)
    // return error back to app
    return callback(null, {
      statusCode: 401,
      body: JSON.stringify({
        error: error.message,
      })
    })
  })
}

Benefits of this approach:

  • it's easy to do for a single function. Ship it!

Drawbacks of this approach:

  • this authentication method is hard to share across multiple functions as your API grows and can lead to non DRY code
  • Caching can be a challenge and if your authentication is an expensive operation or takes a while this can result in a slower UX and cost you more in compute time.

2. Middleware

Next up we have the middleware approach to authentication. This is still happening at the code level but now your logic that verifies the user is allowed to access the function is abstracted up a level into reusable middleware.

MiddyJs does a great job at enabling a sane middleware approach in lambda functions

const middy = require('middy')
const authMiddleware = require('./utils/middleware')

const protectedFunction = (event, context, callback) => {
  // Do my custom stuff
  console.log('⊂◉‿◉つ This is a protected function')

  return callback(null, {
    statusCode: 200,
    body: JSON.stringify({
      data: 'auth true'
    })
  })
}

exports.handler = middy(protectedFunction).use(authMiddleware())

Our middy middleware looks like this:

const checkAuth = require('./auth')

module.exports = function authMiddleware(config) {
  return ({
    before: (handler, next) => {
      checkAuth(handler.event).then((user) => {
        console.log('user', user)
        // set user data on event
        handler.event.user = user
        // We have the user, trigger next middleware
        return next()
      }).catch((error) => {
        console.log('error', error)
        return handler.callback(null, {
          statusCode: 401,
          body: JSON.stringify({
            error: error.message
          })
        })
      })
    }
  })
}

You can also instrument this yourself as seen in the movie demo(link here)

3. "Legacy" middleware

This middleware approach is using a familiar web framework with express PR flask and using their an auth module from their ecosystem.

In the case of express, you can use passport strategies in a lambda function

const express = require('express')
const cors = require('cors')
const bodyParser = require('body-parser')
const compression = require('compression')
const morgan = require('morgan')
const serverless = require('serverless-http')
const customLogger = require('./utils/logger')
const auth0CheckAuth = require('./utils/auth0')

/* initialize express */
const app = express()
const router = express.Router()

/*  gzip responses */
router.use(compression())

/* Setup protected routes */
router.get('/', auth0CheckAuth, (req, res) => {
  res.json({
    super: 'Secret stuff here'
  })
})

/* Attach request logger for AWS */
app.use(morgan(customLogger))

/* Attach routes to express instance */
const functionName = 'express'
const routerBasePath = (process.env.NODE_ENV === 'dev') ? `/${functionName}` : `/.netlify/functions/${functionName}/`
app.use(routerBasePath, router)

/* Apply express middlewares */
router.use(cors())
router.use(bodyParser.json())
router.use(bodyParser.urlencoded({ extended: true }))

/* Export lambda ready express app */
exports.handler = serverless(app)

Benefits of this approach:

  • Leverage existing code to GSD

Cons to this approach:

  • This takes a step backwards in the "serverless" approach to doing things because you have an entire express app bootstrapping on every incoming request
  • This will cost more over time with additional ms runtime because of express overhead
  • This introduces the idea that monoliths can work in lambda functions and this is considered an anti pattern

4. Auth decorators

Similar to auth middleware, decorators wrap the function code and return another function

Some developers prefer this more explicit approach as opposed to middleware

@AuthDecorator // <-- ref to auth wrapper function
function protectedFunction(event, context, callback) {
  // protected logic
}

5. Custom authorizers

Custom authorizers are a feature from AWS API gateway.

They are essentially another function that checks if the user is authorized to access the next function. If the auth checks out, then request then invokes the next lambda function.

Benefits to this approach:

  • authorization can be cached with a TTL (time to live). This can save on subsequent requests where the cached authentication doesn't need to make the potential slow auth check each time. This saves on compute time, ergo saves $$

Drawbacks to this approach:

  • you need to be using AWS API gateway to use custom authorizers

6. Proxy level

Similar to custom authorizers, you can verify requests at the proxy level.

This works in Netlify by checking for an http only secure cookie.

If the nf_jwt cookie exists in the request headers, Netlify will deserialize it and pass it into the context object of the lambda function

If the cookie is no valid, you can send the request to a non authorized endpoint (http code X)

# If visitor has 'nf_jwt' with role set, let them see site.
/.netlify/functions/protected-function /.netlify/functions/protected-function 200! Role=*

# Else, redirect them to login portal site.
/.netlify/functions/protected-function /not-allowed 401!

7. Single use access token

Some third party services like AWS, and faunaDB make it possible to use single use tokens in the client to invoke their APIs directly.

This means no function middleman to make the API calls to other services.

Benefits to this approach:

  • Cheaper (no function runtime to pay for)
  • Faster (no function latency in the middle)

Cons to this approach:

  • More complex to setup
  • Provider must support secure single use access tokens

For more information on this approach see AWS Cognito docs.

More Repositories

1

analytics

Lightweight analytics abstraction layer for tracking page views, custom events, & identifying visitors
JavaScript
2,024
star
2

isomorphic-react-example

Deprecated! ReactJS + NodeJS ( express ) demo tutorial with video. Universal/Isomorphic JS = Shared JavaScript that runs on both the client & server.
JavaScript
1,692
star
3

markdown-magic

💫  Automatically format markdown files using comment blocks. Update contents via custom transforms, external data sources & your source code.
JavaScript
785
star
4

netlify-functions-workshop

Netlify Serverless Functions Workshop
JavaScript
335
star
5

advanced-markdown

Learn about advanced markdown techniques
JavaScript
283
star
6

serverless-workshop

⚡️ Open source serverless workshop. Ready to deploy serverless examples on AWS
JavaScript
184
star
7

responsible

Responsible.js - Give visitors the mobile experience THEY want
JavaScript
164
star
8

types-with-jsdocs

Using JSDoc for Typescript Types
JavaScript
128
star
9

awesome-stoicism

💆‍♂️ Stoic philosophy resources
JavaScript
124
star
10

safe-await

Safely use async await without all the try/catch blocks
JavaScript
120
star
11

PostCSS-tutorial

Tutorial on adding PostCSS to `create-react-app` CLI
JavaScript
102
star
12

aws-profile-manager

GUI for managing AWS profile credentials.
JavaScript
58
star
13

atom-react-autocomplete

(Deprecated/Maintainer wanted) Atom Plugin for autocompleting react components & their props
JavaScript
55
star
14

next-with-react-router-v6

Next.js with React Router v6 demo
TypeScript
48
star
15

icon-pipeline

🚚 SVG icon pipeline - Optimize icons & build SVG sprites
JavaScript
45
star
16

pnpm-workspaces-example

PNPM workspaces example for monorepos
JavaScript
39
star
17

cache-me-outside

📁 Caching tool for quicker builds in CI systems
JavaScript
37
star
18

react-router-tutorial

Learn how to add routing to your React App
JavaScript
30
star
19

serverless-manifest-plugin

Output manifest of endpoints, resources, outputs, etc. of a serverless service
JavaScript
27
star
20

video-app

👨‍💻 Electron App for showing your webcam in a window thats always on top
JavaScript
26
star
21

react-server-components

Example of react server components running in AWS Lambda deployed via serverless framework
JavaScript
24
star
22

easy-markdown

WordPress Plugin to support Github Flavored Markdown + Syntax Highlighting
PHP
24
star
23

npm-statistics

NPM Download Statistics for David's Open Source Projects
JavaScript
21
star
24

configorama

⚙️ ${variable} support for config files
JavaScript
20
star
25

dom-guard

🔐 Lock DOM node contents to protect people against scammers using browser devtools
HTML
19
star
26

davidwells.io

🌐 David's personal website
JavaScript
17
star
27

middy-example

Serverless project using middy middleware for so fresh & so clean clean lambdas 🛀
JavaScript
14
star
28

markdown-magic-github-contributors

markdown-magic Plugin to list out the contributors of your repository.
JavaScript
13
star
29

react-project-base

Super old. Do not use. My base for starting React Projects
JavaScript
12
star
30

aws-profile-cli

💻 CLI & Utils for managing AWS accounts on your machine
JavaScript
12
star
31

intro-to-react

Introduction to React Core Concepts
JavaScript
12
star
32

netlify-site-as-aws-custom-resource-example

Define Netlify sites as part of an AWS Cloudformation stack.
JavaScript
11
star
33

function-zips

Using zip based functions in Netlify
HTML
11
star
34

use-analytics-with-react-router-demo

Use analytics react hooks with React Router v6
JavaScript
9
star
35

davidwells-legacy-site

👴 David's old personal site
JavaScript
9
star
36

react-example-project

JavaScript
8
star
37

env-stage-loader

Loads .env files in order based on process.env.NODE_ENV value with [stage].local support
JavaScript
8
star
38

oparser

A very forgiving key-value option parser
JavaScript
6
star
39

redux-toolkit-vite-example

TypeScript
6
star
40

netlify-sentry-plugin

WIP - Plugin to automatically run sentry releases
JavaScript
6
star
41

redux-tutorial

JavaScript
6
star
42

debug-plugin-activation-errors

Plugin for Debugging WordPress Plugin Activation Errors. Instead of seeing: "The plugin generated ### characters of unexpected output during activation. If you notice “headers already sent” messages, problems with syndication feeds or other issues, try deactivating or removing this plugin." you get the errors being thrown.
PHP
6
star
43

react-autocomplete-cli

CLI companion to the atom-react-autocomplete plugin
JavaScript
4
star
44

happiness-as-a-service

Happiness as a serverless service
JavaScript
4
star
45

js-code-search

Quick links to find how people use npm packages.
JavaScript
4
star
46

scope

🔭 Scope - Create a birdeye's view of your Github project and embed on your site
JavaScript
4
star
47

google-tag-manager-serverless

TODO serverlessify google tag manager serverside implementation
JavaScript
4
star
48

node-docker-workflow

Node Docker Continuous Integration with Express + Redis
Shell
3
star
49

Next-JS-Landing-Page-Starter-Template

next template with tailwind jit & webpack 5
TypeScript
3
star
50

next-with-react-router-v5

Using Next.js as SPA with react router v5
TypeScript
3
star
51

lerna-example

Lerna example for monorepos
JavaScript
3
star
52

repo-using-markdown-magic

Example of repo using markdown magic
JavaScript
3
star
53

analytics-e2e-testing

WIP analytics testing via Cypress
JavaScript
3
star
54

npm-workspaces-example

NPM workspaces example for monorepos
JavaScript
3
star
55

calm

Check if person is calm or not with javascript
JavaScript
3
star
56

explorer-demo-with-video

2
star
57

whats-in-the-cache

Recursively lookup files in a (cache) directory & print a manifest
JavaScript
2
star
58

explorer-demo-weds-two

2
star
59

gitignore-utils

JavaScript
2
star
60

themeable-components-themes

CSS
2
star
61

test-repo-tues-two

HTML
2
star
62

js-library-starter-kit

JavaScript library starter kit for open source projects
JavaScript
2
star
63

parse-npm-script

Parse package.json "script" commands to see how they resolve
JavaScript
2
star
64

explorer-demo-tues-four

2
star
65

simple-supplier-distributor-tues

2
star
66

jsdoc-parser

Updated fork of dox
JavaScript
2
star
67

store-it

Store data in browser. Fallbacks for everythang
JavaScript
2
star
68

mono-repo-example

HTML
2
star
69

WordPress-UI

A CSS Framework and a Set of React Components that Implement WordPress UI
JavaScript
2
star
70

git-er-done

Notice! Moved! See link below...... Utility for dealing with modified, created, deleted files since a git commit.
JavaScript
2
star
71

ryan-wells-foundation

WordPress Site for Ryan Wells Foundation
PHP
1
star
72

my-new-uni

Vendia Universal Application
HTML
1
star
73

next-netlify-blog-starter

JavaScript
1
star
74

react-workshop

1
star
75

safe-chalk

🎨 Terminal colors. Wrapper for chalk package with easy enable/disable option.
JavaScript
1
star
76

react-angular-webpack

React + Angular using ES6 + webpack
JavaScript
1
star
77

vis-tree-demo

JavaScript
1
star
78

customerio-example

JavaScript
1
star
79

electron-dev-setup

Starter project for electron apps
JavaScript
1
star
80

demo-netlify-gated-sites-login-site

JavaScript
1
star
81

redact-logs

Redact sensitive env vars from logs & CLI output.
JavaScript
1
star
82

buslify

Show me da bus
JavaScript
1
star
83

awesomesauce

JavaScript
1
star
84

react-dom-primitives

React Base Dom Primatives
JavaScript
1
star
85

addon-api-example

Example Netlify Add-on API using Netlify functions
JavaScript
1
star
86

netlify-build-mono-repo-base-dir

Mono repo base dir issue https://github.com/homertherefore/netlify-monorepo-project
JavaScript
1
star
87

amplify-vs-cognito-sdk-bundle-size-test

Amplify vs Cognito SDK bundle size test
HTML
1
star
88

minimal-code-sandbox

JavaScript
1
star
89

begin-basic-crud-app

Begin app
HTML
1
star
90

vgs-vanilla-demo

HTML
1
star
91

themeable-components

Themable (at build) react components using CSS
JavaScript
1
star
92

react-router-fibonacci

Fibonacci Sequence with React Router
JavaScript
1
star
93

tiny-cognito

Get AWS Cognito creds to use with aws4fetch
JavaScript
1
star
94

install-github-dep

Git submodules without using submodules
JavaScript
1
star
95

test-repo-cxz

HTML
1
star
96

components

React Components
JavaScript
1
star
97

get-object-diff

JavaScript
1
star
98

react-meetup-demo

Real world react meetup demo!!!!!!!!
JavaScript
1
star
99

react-i18next-advanced

react-i18next with local storage fallback
JavaScript
1
star
100

old-analytics-example

[Old] Example site using `analytics` package
JavaScript
1
star