Dex is a tool created to make setting up and managing authentication methods easy. It is a single sign-on and identity management tool that can be used to authenticate users against a variety of backends. It is a great tool to use when you want to add authentication to your application without having to worry about managing the users yourself but still gives you the option if you want to. This post will show you how to run Dex locally to decide if it is the right tool for you. This does not cover how to integrate Dex into your application or integration with other authentication providers but I will cover that in a future article.

Getting the Dex image

There are two different Docker images available for Dex. One built on top of Alpine and another that is built on top of a distroless image. This example will use the distroless image in order to run Dex as lightweight as possible.

1
docker pull dexidp/dex:latest-distroless

Configuration

Before Dex can be ran, it needs to know the configuration to run with. A full example config can be found in the project’s source code. This example will use a minimal configuration that will allow you to get started using Dex locally. This configuration can be thought of as having the following sections:

  • Where to reach Dex
  • Where Dex should store its data
  • What client applications can authenticate with Dex
  • A list of users that can authenticate
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
issuer: http://127.0.0.1:5556/dex
storage:
  type: sqlite3
web:
  http: 0.0.0.0:5556
staticClients:
  - id: example-app
    redirectURIs:
      - "http://127.0.0.1:5555/callback"
    name: "Example App"
    secret: ZXhhbXBsZS1hcHAtc2VjcmV0
enablePasswordDB: true
staticPasswords:
  - email: "admin@example.com"
    hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W"
    username: "admin"
    userID: "08a8684b-db88-4b73-90a9-3cd1661f5466"

Issuer & Web

1
2
3
issuer: http://127.0.0.1:5556/dex
web:
  http: 0.0.0.0:5556

These two configuration values look very similar and can easily be confused.

The web section is where the Dex webpage will be available at. This is where client applications will direct users when they want to authenticate. Dex will present a login page with the different configured authentication methods when navigating to this page.

The issuer is the URL that Dex will use to identify itself. After all the redirects done during the authentication process, Dex will verify that the issuer is the same as the one that was used to start the authentication process.

Both of these use 5556 as the default http port. This would need to be switched over to 5554 and https in a production environment. Since Dex will be running on the same machine as the client application, it is fine to use http for this example.

We’re also using the loopback address 127.0.0.1 as the issuer hostname. To access the Dex web interface from another machine, the hostname would need to be changed to the hostname or IP address of the machine running Dex.

Storage

1
2
storage:
  type: sqlite3

Dex supports a number of different storage options. Deciding which one to use should be based on the number of basic users that you expect to have. If you will not be creating many and you will instead be using external providers such as SAML or OIDC, then this can be kept simple and use sqlite or kubernetes objects. If you plan to create more users, then a full fledged database such as postgres or mysql should be used.

Static Clients

1
2
3
4
5
6
staticClients:
  - id: example-app
    redirectURIs:
      - "http://127.0.0.1:5555/callback"
    name: "Example App"
    secret: ZXhhbXBsZS1hcHAtc2VjcmV0

This is a list of client applications that can authenticate with Dex. The Dex project provides a basic example app that can be used to test the setup of Dex. The information provided here will also be sent by the client application when it wants to authenticate with Dex. If the values don’t match, then Dex will not allow the client application to authenticate.

The redirectURIs is where Dex will send the user after they have authenticated. This is the URL that the client application will be listening on for the user with the authentication information. For this example, the example app will be running on the local machine on port 5555.

The secret is a secret that is shared between the client application and Dex. This is used to verify that the client application is who it says it is. This “secret” is not very secret as it is sent by the client application to Dex through a web request parameter.

Static Passwords

1
2
3
4
5
staticPasswords:
  - email: "admin@example.com"
    hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W"
    username: "admin"
    userID: "08a8684b-db88-4b73-90a9-3cd1661f5466"

This section contains the information for a basic user that can authenticate with Dex. Dex also provides a gRPC API that can be used to create users dynamically while it is running. The information in this section is straight forward to understand.

The hash is the actual password that has already been hashed. To change the password, run the desired password through the bcrypt algorithm.

1
$(echo <password> | htpasswd -BinC 10 admin | cut -d: -f2)

where <password> is the desired password.

Running Dex

Now that the configuration is complete, the Dex container can be started. The following command will start the container with the configuration file mounted as a volume and the port 5556 exposed to the host machine.

1
docker run -p 5556:5556 -v ./config.docker.yaml:/etc/dex/config.docker.yaml dexidp/dex:latest-distroless

Running the example app

The Dex project has an example app to make it easy test Dex with. This app is available either by compiling it from source or by pulling a docker image. You can install the binary from the docker image on your local machine copying it from the docker image using the following command:

1
2
3
4
docker pull ghcr.io/dexidp/example-app:latest &&
    id=$(docker create ghcr.io/dexidp/example-app:latest) &&
    sudo docker cp $id:/usr/local/bin/example-app /usr/local/bin/dex-example-app &&
    (docker rm $id >/dev/null)

You can then run the example app with the default configuration and it will connect to the Dex app at localhost:5556

1
/usr/local/bin/dex-example-app

Authentication flow

Your system is now ready to authenticate using Dex. Start by visiting the example app in the browser at localhost:5555.

It will ask you for some information. The only required value is to specify the example app as the client-id.

Once you click login, the example app will redirect you to Dex itself. Dex will present you with a login page containing all of the configured authentication options. In this example, we only configured a static user and so that is all that will be available.

Login using the credentials specified in the staticPasswords section of the Dex config. admin@example.com:password. Dex will then ask you if you would like grant permissions and then redirect you to the example-app which will display your token and other authentication information.

Summary

This example went over a very basic Dex setup in order to start to get an understanding of how Dex works. This setup should be used for testing only and should not be used in a production setup. Read additional articles to learn more about the different configuration options of Dex.