DexIdP - How to Set Up an OIDC IdP in 5 Minutes and Authenticate via GitHub

27.03.2024Tom Trapp
DevOps Identity Provider Authorization / Authentication oidc github oauth Single Sign On

Banner

Alright, new TechUp, Dex, seen at Erkan’s on LinkedIn, as always, first watch one or two talks about it on YouTube. Damn, there’s not a single talk in a language I understand. Okay, back to the roots, read, read, read.

Here are the questions I’m asking myself:

  • What is Dex❓
  • How does Dex work❓
  • Can I easily set up and test Dex locally❓
  • What makes Dex different or cooler than other IdPs❓
  • Dex or continue with Keycloak❓

What is Dex?

Dex is an OIDC & OAuth2 Identity Provider (IdP) that is part of the Cloud Native Computing Foundation (CNCF) and has had Sandbox status since 2020. Dex itself as an IdP can only be connected via OIDC, and that’s exactly the goal behind it! Dex abstracts numerous authentication options, so only one standard protocol needs to be implemented to communicate with Dex, namely OIDC.

IdP? –> see my TechUp

OIDC / OAuth2? –> see my TechUp

Dex itself promises to be a provider for everything. There are so-called Connectors, with which you can connect Dex to numerous other identity providers or authentication systems. These include LDAP, SAML, OAuth 2.0, GitHub, GitLab, Google, and many more.

It’s worth mentioning that Dex is written in Go and is fully containerized.

How does Dex work?

Dex acts as an abstraction layer for authentication using OIDC. A client only talks to Dex, and Dex talks to the actual identity provider. This means that the client no longer needs to know how to authenticate with a specific identity provider. That’s Dex’s job. This downstream IdP can also be called an Upstream IdP, as shown in the following image.

img.png

Here you can clearly see that the IdP can also be exchanged without the clients noticing or having to adapt anything. Clients here refer to various applications, such as web apps, mobile apps, CLI tools, etc.

The communication from Dex to the Upstream IdP runs via so-called Connectors, which implement the authentication methods of the Upstream IdPs. A list of all connectors can be found here.

Hands On - Can I easily set up and test Dex locally?

Let’s get started, we’ll first check out the repo, build the examples, and start Dex via Docker-Compose.

1
2
3
4
git clone https://github.com/dexidp/dex.git

make examples
make up

Damn, no matching manifest for linux/arm64/v8 in the manifest list entries. Due to my M1 Mac, there seems to be no suitable Docker image.

Build from source it is.

1
make build

And now, let’s start Dex.

1
./bin/dex serve examples/config-dev.yaml

Okay, perfect, Dex is running, and now what? Now we start the example app. The example app is a simple web application that authenticates against Dex.

1
./bin/example-app

Now we can access a web UI at http://localhost:5555 where we can log in.

We now see different fields where we can further configure our OIDC flow, but we’ll start with the standard flow first. As soon as we click on Login, we get to the next page.

img_1.png

There we are asked how we want to log in, first we choose Log in with Example.

img_2.png

Then comes the classic consent screen, which we confirm.

img_3.png

And we are logged in, we have received an ID token, an access token, and a refresh token. Thus, we have played through a complete OIDC flow.

img_4.png

The email login also works, the example configuration creates a user with the email admin@example.com, the password is password. In this simple example, we haven’t used a real connector, but static data, but the principle is the same.

Config File

Let’s take a closer look at the example config:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
issuer: http://127.0.0.1:5556/dex
storage:
  type: sqlite3
  config:
    file: examples/dex.db
web:
  http: 0.0.0.0:5556
telemetry:
  http: 0.0.0.0:5558
staticClients:
- id: example-app
  redirectURIs:
  - 'http://127.0.0.1:5555/callback'
  name: 'Example App'
  secret: ZXhhbXBsZS1hcHAtc2VjcmV0
connectors:
- type: mockCallback
  id: mock
  name: Example
enablePasswordDB: true

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

In short:

  • The endpoint for Dex is defined
  • Data storage is set to an SQLite DB, an example DB is created using dex.db
    • Dex requires storage for refresh tokens, signing keys, etc.
    • Currently, Etcd, CRDs, SQL, Postgres, MySQL, and SQLite3 are supported
  • Endpoints for web and telemetry are defined
  • A static OIDC client is created
  • Finally, a static user is created who can authenticate using email and password

Well and good, but that’s just static data, how can I create a new OIDC client at runtime, for example? Dex also offers a solution here, the Dex API, a gRPC interface. This allows Dex to be configured at runtime.

GitHub Connector

Now we want to take a look at the GitHub connector and use it for authentication.

First, we need to create a GitHub app here. I did this via this link.

  • Homepage URL: http://localhost:5555/
  • Authorization callback URL: http://localhost:5556/dex/callback

Then the OAuth client is created, and we have the clientID and clientSecret.

Now we can configure Dex to communicate with this GitHub app.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
issuer: http://127.0.0.1:5556/dex
storage:
  type: sqlite3
  config:
    file: examples/dex.db
web:
  http: 0.0.0.0:5556
telemetry:
  http: 0.0.0.0:5558
staticClients:
  - id: example-app
    redirectURIs:
      - 'http://127.0.0.1:5555/callback'
    name: 'Example App'
    secret: ZXhhbXBsZS1hcHAtc2VjcmV0

connectors:
  - type: github
    id: github
    name: GitHub
    config:
      clientID: <your clientId>
      clientSecret: <your clientSecret>
      redirectURI: http://127.0.0.1:5556/dex/callback
      loadAllGroups: true
      teamNameField: slug
      useLoginAsID: false

If we save this config file, for example, with the name b-nova_github.yaml in the examples folder, we can start Dex with this configuration.

1
./bin/dex serve examples/b-nova_github.yaml

And there you go, we can easily log in via OIDC against GitHub without having to change anything in the application (the client).

We press Login again and, if we are not logged in yet, we land directly at GitHub.

img_6.png

Here we can clearly see that we can authenticate via GitHub to then access techup-dex. Then comes the consent of our example app again, which we confirm. And voilà, we are logged in and have the familiar OAuth & OIDC tokens.

If we now look at the claims, we see that my real, actual GitHub information is returned.

img_5.png

However, we cannot clearly tell from the token itself that it is a GitHub login, and that’s a good thing! Since Dex acts as an abstraction layer, our web app doesn’t need to know how the user authenticated.

And so we have set up an OIDC IdP in 5 minutes and authenticated via GitHub. In a production setup, Dex would certainly run containerized, the secrets would not be plain in the config, and the setup would be secured through further hardening. Fortunately, Dex offers various container images, Helm charts, and a Kubernetes operator. More on that in a later TechUp! 🚀

What makes Dex different or cooler than other IdPs?

Basically, Dex is an IdP like many others, but it offers a very simple way to abstract different authentication methods and consolidate them using OIDC. Dex is the cloud-native alternative if you need a quick and easy IdP for an existing IDM system like LDAP, GitHub, or similar. The configuration is fully versioned but can also be adjusted at runtime using the API.

Dex or continue with Keycloak?

Hard to say! Keycloak, as a complete identity and access management system, naturally offers much more functionality than Dex. For example, Keycloak can map custom claims, has a web UI, can work realm-based, has various two-factor options, and other features.

Dex, on the other hand, is very lean and simple, it only offers the bare minimum to operate an IdP. It is fully containerized and offers a simple way to abstract different authentication methods and consolidate them using OIDC. So, if you already have an existing IDM or even IdP system and want to authenticate your clients via a single OIDC interface, then Dex is the right choice.

If you need more features, the choice would rather go towards Keycloak or even another IdP like ForgeRock or Okta.

Conclusion

Personally, I think Dex is cool, it hits exactly the CNCF idea, a small service with flexible configuration options for exactly one task.

Certainly, Dex is a great alternative, although the sandbox status is still clearly noticeable. For example, I miss the feature of being able to specify groups for local static users as well, in order to map different test cases.

Nevertheless, a great tool to quickly and easily set up and test an IdP.

Stay tuned! 💡

Sum-Up

  • What is Dex?

    • Dex is an OIDC & OAuth2 Identity Provider (IdP) that functions as part of the Cloud Native Computing Foundation (CNCF) and has had Sandbox status since 2020. It abstracts numerous authentication options and only requires the implementation of OIDC for communication.
  • How does Dex work?

    • Dex acts as an abstraction layer for authentication using OIDC, where it functions as an intermediary between the client and the actual identity provider. This means clients don’t need to know how to authenticate with different identity providers.
  • Can I easily set up and test Dex locally?

    • Yes, Dex can be easily set up and tested locally. The blog post provides instructions for local deployment of Dex, including using Docker-Compose and building from source code.
  • What makes Dex different or cooler than other IdPs?

    • Dex is characterized by its simplicity and the ability to consolidate various authentication methods using OIDC. It is particularly suitable for environments that require a quick and easy setup of an IdP, with the flexibility to connect it to a variety of authentication systems through connectors.
  • Dex or continue with Keycloak?

    • The choice between Dex and Keycloak depends on specific requirements. Dex is leaner, simpler, and focuses on abstracting various authentication methods using OIDC. Keycloak, on the other hand, offers broader functionality as a complete identity and access management system. For simple OIDC abstractions and integration of existing authentication systems, Dex is a good choice; for more comprehensive IAM functions, Keycloak might be more suitable.

This techup has been translated automatically by Gemini

Tom Trapp

Tom Trapp – Problemlöser, Innovator, Sportler. Am liebsten feilt Tom den ganzen Tag an der moderner Software und legt viel Wert auf objektiv sauberen, leanen Code.