Skip to content

tetsuo/frontdex

Repository files navigation

frontdex

OAuth2/OIDC middleware that fronts Dex

Go Reference Go Report Card

frontdex provides OAuth2/OIDC authentication middleware for applications that use Dex as the identity provider. It handles the authorization code flow (with PKCE) and stores tokens and claims in the request context for further processing.

Quickstart

1. Start Dex

Create a Dex config file dex.yaml like this:

# The URL where your app is reachable, not Dex itself
issuer: http://localhost:8080/login

# See https://dexidp.io/docs/storage/ for other storage options
storage:
  type: memory

web:
  http: 0.0.0.0:5556 # Dex will listen on this port
  clientRemoteIP:
    header: X-Forwarded-For # frontdex sets this header

oauth2:
  grantTypes:
    - "authorization_code"
  responseTypes: [ "code" ]
  skipApprovalScreen: true # must be set

staticClients:
- id: example-client
  redirectURIs:
  - 'http://localhost:8080/login/callback'
  name: 'Example client'
  secret: change-me-in-production

# See https://dexidp.io/docs/connectors/ for other connectors
connectors:
- type: github
  id: github
  name: GitHub
  config:
    clientID: YOUR_OAUTH_CLIENT_ID
    clientSecret: YOUR_OAUTH_CLIENT_SECRET
    redirectURI: http://localhost:8080/login/callback # your OAuth app's callback URL
- type: mockCallback # for testing without external IdP
  id: mock
  name: Mock

logger:
  level: "debug"
  format: "text"

Here, we enable the GitHub connector and a mock connector for testing. To use the GitHub connector, you need to register a new OAuth app on GitHub developer settings.

Start Dex with Docker:

docker run \
  --name dex \
  -p 5556:5556 \
  -v ./dex.yaml:/etc/dex/config.yaml \
  --rm \
  dexidp/dex:latest \
  dex serve /etc/dex/config.yaml

2. Create your app

Install:

go get github.com/tetsuo/frontdex

By default, frontdex connects the Dex instance running at localhost:5556. You can configure it to point elsewhere using the WithEndpointURL() option.

📄 See the API documentation at pkg.go.dev for all available options.

There aren't many options to configure to test it out locally. Here's a minimal example app:

package main

import (
	"encoding/json"
	"net/http"

	"github.com/tetsuo/frontdex"
)

func main() {
	fdx := frontdex.New(
		"http://localhost:8080/login",    // issuer URL
		"example-client",                 // client ID
		"change-me-in-production",        // client secret
		frontdex.WithCookieSecure(false), // for local testing
	)

	http.ListenAndServe(":8080", http.StripPrefix("/login", fdx(
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if payload := frontdex.Token(r); payload != nil {
				// User is logged in at /callback; payload contains the JWT and user info
				w.Header().Set("Content-Type", "application/json")
				_ = json.NewEncoder(w).Encode(payload)
			}
		}),
	)))
}