Implementing Access Control with Netlify Identity and Netlify Functions
Tags: netlify, security, javascript, jwt
Published: 2019-11-19 13:06:14

Netlify and JAMStack becoming more popular these days. In this post, I will walk through the process of using Netlify Identity and using it in your Netlify functions.

## Netlify Identity
From Netlify [docs](https://docs.netlify.com/visitor-access/identity/#enable-identity-in-the-ui):
*Netlify Identity service brings a full suite of authentication functionality, backed by the GoTrue API. This allows you to manage and authenticate users on your site or app, without requiring them to be users of Netlify or any other service. You can use this for gated content, site administration, and more.*
So basically, Netlify Identity bring Authentication and user capabilities to your static site using JWT and some authentication providers like GitHub and Google

## Enable Netlify Identity in Your Project
To enable Identity, select the identity tab and click **Enable Identity**
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/uapy9eey8vwmlirk6p9r.png)

## Embed Identity Widget in Your Site
For simplicity, I'm using [netlify-identity-widget](https://github.com/netlify/netlify-identity-widget) provided by Netflix in order to add login modal to my site.
Please follow the instruction from the [GitHub page](https://github.com/netlify/netlify-identity-widget), [Netlify's post](https://www.netlify.com/blog/2017/09/07/introducing-built-in-identity-service-to-streamline-user-management/), or from [examples](https://github.com/netlify/netlify-identity-widget/tree/master/example)

## Calling Netlify Functions With the Bearer Header
In order to make the function to know which user called the function, we need to pass the access-token we got from Netlify Identity to the function.
Create a file called `netlify.js`. This file will include two utility functions for calling your netlify functions - `GET` and `POST`.
```javascript
async function getToken() {
  const currentUser = netlifyIdentity.currentUser()
  if (!currentUser) {
    return ''
  }
  // fetchs new JWT token only if expired
  await currentUser.jwt()
  return currentUser.token.access_token
}

export async function GET(api) {
  const token = await getToken()
  return (await fetch(`/.netlify/functions${api}`, {
    headers: { Authorization: `Bearer ${token}` }
  })).json()
}

export async function POST(api, body) {
  const token = await getToken()
  return (await fetch(`/.netlify/functions${api}`, {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      Authorization: `Bearer ${token}`
    },
    body: JSON.stringify(body)
  })).json()
}
```

And use it in your frontend app when you need to call one of your functions
```javascript
import { GET } from '../../netlify'
const data = await GET(`/getData`)
```

## Getting the User Object Within Netlify Functions and Acting Upon
Now, after you passed the `Authorization` header, netlify will fetch the user object and put it inside the event context.
For example, read the roles of the user:

```javascript

function getUserRoles(context) {
    const { clientContext } = context
    const userRoles = clientContext.user
      ? clientContext.user.app_metadata.roles
      : ["guest"]
}

export async function handle(event, context) {
    const userRoles = getUserRoles(context)

    // Return with 401 if user is not logged in
    if (userRoles.includes("guest")) {
        return {
            statusCode: 401,
            body: "unauthorized"
        }
    }

    let data;

    // Get data only admins should see
    if (userRoles.includes("admin")) {
        data = getAllStatuses();
    }

    // Get data only owners should see
    else if (userRoles.includes("owner")) {
        data = getStatus();
    }

    return {
        statusCode: 200,
        body: JSON.stringify({
            data,
        })
    }
```


**Found this post useful? Add a star⭐️ to my Github project🙂**

{% github moshe/elasticsearch-comrade %}

🥳