Auth0 deployment with GitHub Actions
Tags: 100daystooffload, auth0, githubactions, devops
Published: 2023-08-02 09:22:11

[Auth0](https://auth0.com/) is a flexible, drop-in solution to add authentication and authorization services to your applications. They have a free plan if you want to sign up and test it.

I will describe one possible way to setup the deployment pipeline for an Auth0 implementation so the configuration is defined as code. The main components that will be in use are:

* [Deploy CLI Tool](https://auth0.com/docs/deploy-monitor/deploy-cli-tool)
* [GitHub Actions](https://github.com/features/actions)
* [npm](https://www.npmjs.com/)

Begin with setting up the project.

```sh
mkdir auth0-deployment-example && $_

npm install auth0-deploy-cli --save-dev

echo "node_modules/" > .gitignore
git init
git add .
git commit -m"Create an Auth0 deployment example project

This project will use:
* Deploy CLI Tool
* GitHub Actions
* npm"

code .
```

The deploy cli tool will communicate with a management API that is provided by Auth0, therefore we first need to create an application on our tenant.

Create a new application (machine to machine) in the Auth0 dashboard. I will name it to **Deploy CLI** to catch the intention of the application.

![Create application](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/czxqr3llio741d7afm60.png)

In the next step select the **Auth0 Management API** in the drop down list. The permission list is harder, we want to follow the principle of least privilege, but it's still difficult to know which ones to select. The deploy cli tool will return good error/warning messages if you are missing any permissions, so one approach is to the use trial and error approach. This is how it's documented by Auth0.

> The principle of least privilege is abided, so it will operate within the set of permissions granted. , you'll need to select read:clients, but it’s recommended to select read:*, create:*, and update:* permissions for all resource types within management purview. To enable deletions, you delete:* scopes.

I will start out with **read:clients** only.

![Permissions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l4cc992n1t7bqjyvnubk.png)

The view below displays the credentials that we need for talking with the management API.

![Credentials](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zyf21tt4cyyfgsg1higd.png)

Add a new row in the _.gitignore_ file that ignores _.env_ files so that we can handle our credentials in a secure way in our project (remember to commit the changes to git).

```text
node_modules/
.env
```

Create a _.env_ file with the following keys, and add the required values for each key depending on your environment.

```text
AUTH0_DOMAIN=<from the Deploy CLI application>
AUTH0_CLIENT_ID=<from the Deploy CLI application>
AUTH0_CLIENT_SECRET=<from the Deploy CLI application>
```

With that file on place you can run following command so that your current shell also has them.

```sh
set -o allexport && source .env && set +o allexport
```

So lets test that we can communicate with our tenant via the management API.

```sh
npx a0deploy export --format=directory --output_folder=src/auth0
```

This gave me a lot of warnings.

![cli export](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lx8i27vhf1zoulmeicvb.png)

That is because I only allowed **read:clients** in the permission list. This how you can see what permissions you really need to give your application.

Personally I like to have read on most things since then it is easier to see if something has been manually changed in the Auth0 dashboard and not by the code. That is also a "debug" way to see what configuration files needs to be changed for a specific feature in Auth0.

When the export is successful you should have a bunch of json configuration files in the _src/auth0/_ directory. All these files should be committed to your git repository.

Usually there is more than one tenant in use because you might have a production, test and maybe more environments. To handle this you can have specific config files for each environment.

```sh
mkdir src/auth0/config
touch src/auth0/config/test.json
touch src/auth0/config/prod.json
```

The config files has some specific configuration properties that is described [here](https://auth0.com/docs/deploy-monitor/deploy-cli-tool/configuring-the-deploy-cli), it's worth reading.

For example you might allow logout URLs for your Auth0 application and they are different for each environment. Here is how test.json could look like.

```json
{
"AUTH0_KEYWORD_REPLACE_MAPPINGS": {
    "ENVIRONMENT": "dev",
    "ALLOWED_LOGOUTS": ["https://dev-test-site.com/logout", "localhost:3000/logout"],
    "ALLOWED_ORIGINS": ["https://dev-test-site.com", "localhost:3000"]
  }
}
```

To use this variable in your configuration file for a client you will need to change it like this (located in the clients directory)

```json
{
  ...
  "allowed_logout_urls": @@ALLOWED_LOGOUTS@@,
  "is_first_party": true,
  "oidc_conformant": true,
  "sso_disabled": false,
  "cross_origin_auth": false,
  ...
}
``` 

The cli tool will then replace the placeholder with correct values when the code is deployed to Auth0. The command for deploying your changes to Auth0 can look like this, depending on your needs.

```sh
npx a0deploy import -c ./src/auth0/config/test.json -i ./src/auth0
```

`-c` is the config file to use.
`-i` the folder where all configuration files are located

Last thing we need to do is to add some scripts to the _package.json_ file so the export and import commands are available for every developer. 

```json
{
  "scripts": {
    "deploy:prod": "a0deploy deploy -c ./src/auth0/config/prod.json -i ./src/auth0",
    "deploy:test": "a0deploy deploy -c ./src/auth0/config/test.json -i ./src/auth0",
    "dump": "a0deploy dump --format=directory --output_folder=src/auth0"
  },
  "devDependencies": {
    "auth0-deploy-cli": "^7.18.0"
  }
}
```

**Note:** I'm using the alias for _import_ and _export_ that is provided by _a0deploy_. These names are much better and has clearer intention. Just found out that they existed now when reading the documentation. So now I need to update my real projects.

Last step is to create a workflow file for GitHub Actions.

```sh
mkdir -p .github/workflows
touch .github/workflows/deploy-to-auth0-test.yml
```

The content of the workflow could look like this.

```yml
name: Deploy to Auth0 test

on:
  workflow_dispatch: # Enable manual deploy from GitHub UI
  # Deploy on each push to main that concerns the Auth0 code configuration
  push:
    branches:
      - main
    path:
      # Auth0 configuration files
      - "src/auth0/**"
      # This workflow file
      - ".github/workflows/deploy-to-auth0-test.yml"

jobs:
  deploy:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ./src/auth0/
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Install Node.js
        uses: actions/setup-node@v3 
        with:
          node-version: 18
      - name: Install Auth0 dependencies
        run: npm ci
      - name: Deploy to the tenant
        env:
          AUTH0_DOMAIN: the-domain.eu.auth0.com
          AUTH0_CLIENT_ID: ${{ secrets.TEST_AUTH0_CLIENT_ID }}
          AUTH0_CLIENT_SECRET: ${{ secrets.TEST_AUTH0_CLIENT_SECRET }}
        run: npm run deploy:test
```

Make sure that you use GitHubs [encrypted secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets) for your Auth0 secrets. I like to prefix my secrets with the environment to group them toghether in the UI.

That's about it. Now there is an automatic pipeline for deploying changes of the Auth0 configuration of a tenant.

This action will deploy all changes to Auth0 when someone makes a commit to main that concerns the code for Auth0. It is also a possible to run the deployment manually. That can be handy to do a "rollback" in Auth0 if someone has made some test changes in the dashboard, a way to get back to a known state.

My experience is that it's good to make a dump time to time from Auth0 to see if the configuration files are drifting or not. That could be because of someone has made a change in the Auth0 dashboard, but the changes hasn't been commited to the repository as code. Another reason is that Auth0 has added/changed a feature which might give the dump new default values for that feature or configuration possibilities.

This solution has worked smooth over the time I have been using it. Before starting to use the _Deploy CLI Tool_, I used [Terraform](https://auth0.com/blog/use-terraform-to-manage-your-auth0-configuration/) instead, it worked great too. However I think you should already be invested in Terraform if you want to use it with Auth0 also.