Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/dbendit/traefik-forward-auth-plex-sso
Minimal forward authentication service that provides Plex SSO based login and authentication for the traefik reverse proxy
https://github.com/dbendit/traefik-forward-auth-plex-sso
authentication docker docker-swarm go golang kubernetes plex traefik
Last synced: 4 months ago
JSON representation
Minimal forward authentication service that provides Plex SSO based login and authentication for the traefik reverse proxy
- Host: GitHub
- URL: https://github.com/dbendit/traefik-forward-auth-plex-sso
- Owner: DBendit
- License: mit
- Created: 2022-01-17T21:56:52.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2024-08-12T03:21:10.000Z (6 months ago)
- Last Synced: 2024-08-12T04:31:42.298Z (6 months ago)
- Topics: authentication, docker, docker-swarm, go, golang, kubernetes, plex, traefik
- Language: Go
- Homepage:
- Size: 162 KB
- Stars: 19
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# Traefik Forward Auth - Plex SSO ![Build Status](https://img.shields.io/github/workflow/status/dbendit/traefik-forward-auth-plex-sso/CI) [![Go Report Card](https://goreportcard.com/badge/github.com/dbendit/traefik-forward-auth-plex-sso)](https://goreportcard.com/report/github.com/dbendit/traefik-forward-auth-plex-sso) [![GitHub release](https://img.shields.io/github/release/dbendit/traefik-forward-auth-plex-sso.svg)](https://GitHub.com/dbendit/traefik-forward-auth-plex-sso/releases/)
A minimal forward authentication service that provides Plex SSO login and authentication for the [traefik](https://github.com/containous/traefik) reverse proxy/load balancer.
## Why?
- Seamlessly overlays any http service with a single endpoint (see: `url-path` in [Configuration](#configuration))
- Supports multiple domains/subdomains by dynamically generating redirect_uri's
- Allows authentication to be selectively applied/bypassed based on request parameters (see `rules` in [Configuration](#configuration))
- Supports use of centralised authentication host/redirect_uri (see `auth-host` in [Configuration](#configuration))
- Allows authentication to persist across multiple domains (see [Cookie Domains](#cookie-domains))
- Supports extended authentication (see: `lifetime` in [Configuration](#configuration))# Contents
- [Usage](#usage)
- [Simple](#simple)
- [Advanced](#advanced)
- [Configuration](#configuration)
- [Overview](#overview)
- [Option Details](#option-details)
- [Concepts](#concepts)
- [Forwarded Headers](#forwarded-headers)
- [User Restriction](#user-restriction)
- [Applying Authentication](#applying-authentication)
- [Global Authentication](#global-authentication)
- [Selective Ingress Authentication in Kubernetes](#selective-ingress-authentication-in-kubernetes)
- [Selective Container Authentication in Swarm](#selective-container-authentication-in-swarm)
- [Rules Based Authentication](#rules-based-authentication)
- [Operation Modes](#operation-modes)
- [Overlay Mode](#overlay-mode)
- [Auth Host Mode](#auth-host-mode)
- [Logging Out](#logging-out)
- [To-do](#to-do)
- [Copyright](#copyright)
- [License](#license)## Usage
#### Simple:
See below for instructions on how to setup your [Provider Setup](#provider-setup).
docker-compose.yml:
```yaml
version: '3'services:
traefik:
image: traefik:v2.2
command: --providers.docker
ports:
- "8085:80"
volumes:
- /var/run/docker.sock:/var/run/docker.socktraefik-forward-auth-plex-sso:
image: ghcr.io/dbendit/traefik-forward-auth-plex-sso:latest
environment:
- SECRET=something-random
- INSECURE_COOKIE=true # Example assumes no https, do not use in production
labels:
- "traefik.http.middlewares.traefik-forward-auth-plex-sso.forwardauth.address=http://traefik-forward-auth-plex-sso:4181"
- "traefik.http.middlewares.traefik-forward-auth-plex-sso.forwardauth.authResponseHeaders=X-Forwarded-User"
- "traefik.http.services.traefik-forward-auth-plex-sso.loadbalancer.server.port=4181"whoami:
image: containous/whoami
labels:
- "traefik.http.routers.whoami.rule=Host(`whoami.mycompany.com`)"
- "traefik.http.routers.whoami.middlewares=traefik-forward-auth-plex-sso"
```#### Advanced:
Please see the examples directory for a more complete [docker-compose.yml](https://github.com/dbendit/traefik-forward-auth-plex-sso/traefik-v2/swarm/docker-compose.yml) or [kubernetes/simple-separate-pod](https://github.com/dbendit/traefik-forward-auth-plex-sso/blob/master/examples/traefik-v2/kubernetes/simple-separate-pod/).
Also in the examples directory is [docker-compose-auth-host.yml](https://github.com/dbendit/traefik-forward-auth-plex-sso/blob/master/examples/traefik-v2/swarm/docker-compose-auth-host.yml) and [kubernetes/advanced-separate-pod](https://github.com/dbendit/traefik-forward-auth-plex-sso/blob/master/examples/traefik-v2/kubernetes/advanced-separate-pod/) which shows how to configure a central auth host, along with some other options.
## Configuration
### Overview
The following configuration options are supported:
```
Usage:
traefik-forward-auth [OPTIONS]Application Options:
--log-level=[trace|debug|info|warn|error|fatal|panic] Log level (default: warn) [$LOG_LEVEL]
--log-format=[text|json|pretty] Log format (default: text) [$LOG_FORMAT]
--auth-host= Single host to use when returning from 3rd party auth [$AUTH_HOST]
--config= Path to config file [$CONFIG]
--cookie-domain= Domain to set auth cookie on, can be set multiple times [$COOKIE_DOMAIN]
--insecure-cookie Use insecure cookies [$INSECURE_COOKIE]
--cookie-name= Cookie Name (default: _forward_auth) [$COOKIE_NAME]
--csrf-cookie-name= CSRF Cookie Name (default: _forward_auth_csrf) [$CSRF_COOKIE_NAME]
--default-action=[auth|allow] Default action (default: auth) [$DEFAULT_ACTION]
--domain= Only allow given email domains, can be set multiple times [$DOMAIN]
--lifetime= Lifetime in seconds (default: 43200) [$LIFETIME]
--logout-redirect= URL to redirect to following logout [$LOGOUT_REDIRECT]
--url-path= Callback URL Path (default: /_oauth) [$URL_PATH]
--secret= Secret used for signing (required) [$SECRET]
--whitelist= Only allow given email addresses, can be set multiple times [$WHITELIST]
--port= Port to listen on (default: 4181) [$PORT]
--rule..= Rule definitions, param can be: "action" or "rule"
--product Identity of this service to send to Plex in X-Plex-Product header [$PRODUCT]
--client-identifier Client identifier of this service to send to Plex in X-Plex-Client-Identifier header [$CLIENT_IDENTIFIER]
--server-identifier Identifier for the server that users must be members of to successfully authenticate [$SERVER_IDENTIFIER]Help Options:
-h, --help Show this help message
```All options can be supplied in any of the following ways, in the following precedence (first is highest precedence):
1. **Command Arguments/Flags** - As shown above
2. **Environment Variables** - As shown in square brackets above
3. **File**
1. Use INI format (e.g. `url-path = _oauthpath`)
2. Specify the file location via the `--config` flag or `$CONFIG` environment variable
3. Can be specified multiple times, each file will be read in the order they are passed### Option Details
- `auth-host`
When set, when a user returns from authentication with a 3rd party provider they will always be forwarded to this host. By using one central host, this means you only need to add this `auth-host` as a valid redirect uri to your 3rd party provider.
The host should be specified without protocol or path, for example:
```
--auth-host="auth.example.com"
```For more details, please also read the [Auth Host Mode](#auth-host-mode), operation mode in the concepts section.
Please Note - this should be considered advanced usage, if you are having problems please try disabling this option and then re-read the [Auth Host Mode](#auth-host-mode) section.
- `config`
Used to specify the path to a configuration file, can be set multiple times, each file will be read in the order they are passed. Options should be set in an INI format, for example:
```
url-path = _oauthpath
```- `cookie-domain`
When set, if a user successfully completes authentication, then if the host of the original request requiring authentication is a subdomain of a given cookie domain, then the authentication cookie will be set for the higher level cookie domain. This means that a cookie can allow access to multiple subdomains without re-authentication. Can be specificed multiple times.
For example:
```
--cookie-domain="example.com" --cookie-domain="test.org"
```For example, if the cookie domain `test.com` has been set, and a request comes in on `app1.test.com`, following authentication the auth cookie will be set for the whole `test.com` domain. As such, if another request is forwarded for authentication from `app2.test.com`, the original cookie will be sent and so the request will be allowed without further authentication.
Beware however, if using cookie domains whilst running multiple instances of traefik/traefik-forward-auth for the same domain, the cookies will clash. You can fix this by using a different `cookie-name` in each host/cluster or by using the same `cookie-secret` in both instances.
- `insecure-cookie`
If you are not using HTTPS between the client and traefik, you will need to pass the `insecure-cookie` option which will mean the `Secure` attribute on the cookie will not be set.
- `cookie-name`
Set the name of the cookie set following successful authentication.
Default: `_forward_auth`
- `csrf-cookie-name`
Set the name of the temporary CSRF cookie set during authentication.
Default: `_forward_auth_csrf`
- `default-action`
Specifies the behavior when a request does not match any [rules](#rules). Valid options are `auth` or `allow`.
Default: `auth` (i.e. all requests require authentication)
- `default-provider`
Set the default provider to use for authentication, this can be overridden within [rules](#rules). Valid options are currently `google` or `oidc`.
Default: `google`
- `domain`
When set, only users matching a given domain will be permitted to access.
For example, setting `--domain=example.com --domain=test.org` would mean that only users from example.com or test.org will be permitted. So [email protected] would be allowed but [email protected] would not.
For more details, please also read [User Restriction](#user-restriction) in the concepts section.
- `lifetime`
How long a successful authentication session should last, in seconds.
Default: `43200` (12 hours)
- `logout-redirect`
When set, users will be redirected to this URL following logout.
- `match-whitelist-or-domain`
When enabled, users will be permitted if they match *either* the `whitelist` or `domain` parameters.
This will be enabled by default in v3, but is disabled by default in v2 to maintain backwards compatibility.
Default: `false`
For more details, please also read [User Restriction](#user-restriction) in the concepts section.
- `url-path`
Customise the path that this service uses to handle the callback following authentication.
Default: `/_oauth`
Please note that when using the default [Overlay Mode](#overlay-mode) requests to this exact path will be intercepted by this service and not forwarded to your application. Use this option (or [Auth Host Mode](#auth-host-mode)) if the default `/_oauth` path will collide with an existing route in your application.
- `secret`
Used to sign cookies authentication, should be a random (e.g. `openssl rand -hex 16`)
- `whitelist`
When set, only specified users will be permitted.
For example, setting `[email protected] [email protected]` would mean that only those two exact users will be permitted. So [email protected] would be allowed but [email protected] would not.
For more details, please also read [User Restriction](#user-restriction) in the concepts section.
- `rule`
Specify selective authentication rules. Rules are specified in the following format: `rule..=`
- `` can be any string and is only used to group rules together
- `` can be:
- `action` - same usage as [`default-action`](#default-action), supported values:
- `auth` (default)
- `allow`
- `domains` - optional, same usage as [`domain`](#domain)
- `rule` - a rule to match a request, this uses traefik's v2 rule parser for which you can find the documentation here: https://docs.traefik.io/v2.0/routing/routers/#rule, supported values are summarised here:
- ``Headers(`key`, `value`)``
- ``HeadersRegexp(`key`, `regexp`)``
- ``Host(`example.com`, ...)``
- ``HostRegexp(`example.com`, `{subdomain:[a-z]+}.example.com`, ...)``
- ``Method(methods, ...)``
- ``Path(`path`, `/articles/{category}/{id:[0-9]+}`, ...)``
- ``PathPrefix(`/products/`, `/articles/{category}/{id:[0-9]+}`)``
- ``Query(`foo=bar`, `bar=baz`)``
- `whitelist` - optional, same usage as whitelist`](#whitelist)For example:
```
# Allow requests that being with `/api/public` and contain the `Content-Type` header with a value of `application/json`
rule.1.action = allow
rule.1.rule = PathPrefix(`/api/public`) && Headers(`Content-Type`, `application/json`)# Allow requests that have the exact path `/public`
rule.two.action = allow
rule.two.rule = Path(`/public`)# Allow [email protected] to `/janes-eyes-only`
rule.two.action = allow
rule.two.rule = Path(`/janes-eyes-only`)
rule.two.whitelist = [email protected]
```Note: It is possible to break your redirect flow with rules, please be careful not to create an `allow` rule that matches your redirect_uri unless you know what you're doing. This limitation is being tracked in in #101 and the behaviour will change in future releases.
## Concepts
### User Restriction
You can restrict who can login with the following parameters:
* `domain` - Use this to limit logins to a specific domain, e.g. test.com only
* `whitelist` - Use this to only allow specific users to login e.g. [email protected] onlyNote, if you pass both `whitelist` and `domain`, then the default behaviour is for only `whitelist` to be used and `domain` will be effectively ignored. You can allow users matching *either* `whitelist` or `domain` by passing the `match-whitelist-or-domain` parameter (this will be the default behaviour in v3). If you set `domains` or `whitelist` on a rule, the global configuration is ignored.
### Forwarded Headers
The authenticated user is set in the `X-Forwarded-User` header, to pass this on add this to the `authResponseHeaders` config option in traefik, as shown below in the [Applying Authentication](#applying-authentication) section.
### Applying Authentication
Authentication can be applied in a variety of ways, either globally across all requests, or selectively to specific containers/ingresses.
#### Global Authentication
This can be achieved by enabling forward authentication for an entire entrypoint, for example, with http only:
```ini
--entryPoints.http.address=:80
--entrypoints.http.http.middlewares=traefik-forward-auth # "default-traefik-forward-auth" on kubernetes
```Or https:
```ini
--entryPoints.http.address=:80
--entryPoints.http.http.redirections.entryPoint.to=https
--entryPoints.http.http.redirections.entryPoint.scheme=https
--entryPoints.https.address=:443
--entrypoints.https.http.middlewares=traefik-forward-auth # "default-traefik-forward-auth" on kubernetes
```Note: Traefik prepends the namespace to the name of middleware defined via a kubernetes resource. This is handled automatically when referencing the middleware from another resource in the same namespace (so the namespace does not need to be prepended when referenced). However the full name, including the namespace, must be used when referenced from static configuration (e.g. command arguments or config file), hence you must prepend the namespace to your traefik-forward-auth middleware reference, as shown in the comments above (e.g. `default-traefik-forward-auth` if your middleware is named `traefik-forward-auth` and is defined in the `default` namespace).
#### Selective Ingress Authentication in Kubernetes
If you choose not to enable forward authentication for a specific entrypoint, you can apply the middleware to selected ingressroutes:
```yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami
labels:
app: whoami
spec:
entryPoints:
- http
routes:
- match: Host(`whoami.example.com`)
kind: Rule
services:
- name: whoami
port: 80
middlewares:
- name: traefik-forward-auth
```See the examples directory for more examples.
#### Selective Container Authentication in Swarm
You can apply labels to selected containers:
```yaml
whoami:
image: containous/whoami
labels:
- "traefik.http.routers.whoami.rule=Host(`whoami.example.com`)"
- "traefik.http.routers.whoami.middlewares=traefik-forward-auth"
```See the examples directory for more examples.
#### Rules Based Authentication
You can also leverage the `rules` config to selectively apply authentication via traefik-forward-auth. For example if you enabled global authentication by enabling forward authentication for an entire entrypoint, you can still exclude some patterns from requiring authentication:
```ini
# Allow requests to 'dash.example.com'
rule.1.action = allow
rule.1.rule = Host(`dash.example.com`)# Allow requests to `app.example.com/public`
rule.two.action = allow
rule.two.rule = Host(`app.example.com`) && Path(`/public`)
```### Operation Modes
#### Overlay Mode
Overlay is the default operation mode, in this mode the authorisation endpoint is overlaid onto any domain. By default the `/_oauth` path is used, this can be customised using the `url-path` option.
The user flow will be:
1. Request to `www.myapp.com/home`
2. User redirected to Plex login
3. After Plex login, user is redirected to `www.myapp.com/_oauth`
4. Token, user and CSRF cookie is validated (this request in intercepted and is never passed to your application)
5. User is redirected to `www.myapp.com/home`
6. Request is allowed#### Auth Host Mode
This is an optional mode of operation that is useful when dealing with a large number of subdomains, it is activated by using the `auth-host` config option (see [this example docker-compose.yml](https://github.com/dbendit/traefik-forward-auth-plex-sso/blob/master/examples/traefik-v2/swarm/docker-compose-auth-host.yml) or [this kubernetes example](https://github.com/dbendit/traefik-forward-auth-plex-sso/tree/master/examples/traefik-v2/kubernetes/advanced-separate-pod)).
To utilise an auth host, permit domain level cookies by setting the cookie domain to `test.com` then set the `auth-host` to: `auth.test.com`.
The user flow will then be:
1. Request to `app10.test.com/home/page`
2. User redirected to Plex login
3. After Plex login, user is redirected to `auth.test.com/_oauth`
4. Token, user and CSRF cookie is validated, auth cookie is set to `test.com`
5. User is redirected to `app10.test.com/home/page`
6. Request is allowedTwo criteria must be met for an `auth-host` to be used:
1. Request matches given `cookie-domain`
2. `auth-host` is also subdomain of same `cookie-domain`Please note: For Auth Host mode to work, you must ensure that requests to your auth-host are routed to the traefik-forward-auth container, as demonstrated with the service labels in the [docker-compose-auth.yml](https://github.com/dbendit/traefik-forward-auth-plex-sso/blob/master/examples/traefik-v2/swarm/docker-compose-auth-host.yml) example and the [ingressroute resource](https://github.com/dbendit/traefik-forward-auth-plex-sso/blob/master/examples/traefik-v2/kubernetes/advanced-separate-pod/traefik-forward-auth/ingress.yaml) in a kubernetes example.
### Logging Out
The service provides an endpoint to clear a users session and "log them out". The path is created by appending `/logout` to your configured `path` and so with the default settings it will be: `/_oauth/logout`.
You can use the `logout-redirect` config option to redirect users to another URL following logout (note: the user will not have a valid auth cookie after being logged out).
Note: This only clears the auth cookie from the users browser and as this service is stateless, it does not invalidate the cookie against future use. So if the cookie was recorded, for example, it could continue to be used for the duration of the cookie lifetime.
# To-do
* Bulk up test coverage
* Import additional examples
* Verify server access levels globally
* Verify server access levels in rules## Copyright
* 2022 Dave Bendit
* 2018 Thom Seddon (https://github.com/thomseddon/traefik-forward-auth)## License
[MIT](https://github.com/dbendit/traefik-forward-auth-plex-sso/blob/master/LICENSE)