OAuth 2.0 Token Introspection Authentication¶
OAuth 2.0 Token Introspection allows Traefik Enterprise to retrieve metadata about an access token from an oAuth 2.0 server with the Token Introspection extension. The metadata can be used to restrict the access to applications. For more information please refer to the RFC.
Authentication Source¶
Before configuring an OAuth 2.0 Token Introspection middleware, an Authentication Source must be defined in the static configuration.
Below is an example of a minimal OAuth 2.0 Token Introspection Authentication Source that can be added to a static configuration:
[authSources]
[authSources.oAuthIntroSource]
[authSources.oAuthIntroSource.oAuthIntrospection]
url = "https://localhost/oauth2/introspect"
authorizationHeader = "Basic dGVzdDp0ZXN0"
authSources:
oAuthIntroSource:
oAuthIntrospection:
url: https://localhost/oauth2/introspect
authorizationHeader: Basic dGVzdDp0ZXN0
Authentication Source Options¶
url
¶
Required, Default=""
The url
is the full introspection endpoint URL. It must include the scheme and path.
[authSources]
[authSources.oAuthIntroSource]
[authSources.oAuthIntroSource.oAuthIntrospection]
url = "https://localhost/oauth2/introspect"
authSources:
oAuthIntroSource:
oAuthIntrospection:
url: https://localhost/oauth2/introspect
authorizationHeader
¶
Optional, Default=""
The authorizationHeader
is the authentication used to access the introspection server endpoint. The value is used as the Authorization
header sent to the introspection server.
[authSources]
[authSources.oAuthIntroSource]
[authSources.oAuthIntroSource.oAuthIntrospection]
authorizationHeader = "Basic dGVzdDp0ZXN0"
authSources:
oAuthIntroSource:
oAuthIntrospection:
authorizationHeader: Basic dGVzdDp0ZXN0
customHeaders
¶
Optional, Default=""
The customHeaders
are user defined headers to send in every introspection request.
[authSources]
[authSources.oAuthIntroSource]
[authSources.oAuthIntroSource.oAuthIntrospection]
[authSources.oAuthIntroSource.oAuthIntrospection.customHeaders]
Custom-Header = "test"
Source = "traefikee"
authSources:
oAuthIntroSource:
oAuthIntrospection:
customHeaders:
Custom-Header: test
Source: traefikee
OAuth 2.0 Token Introspection Middleware¶
After declaring an OAuth 2.0 Token Introspection Authentication Source in the static configuration of the cluster, OAuth 2.0 Token Introspection middleware can be added to routers in the dynamic configuration:
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.source=oAuthIntroSource"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-oauth-intro
spec:
plugin:
oAuthIntrospection:
source: oAuthIntroSource
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.source=oAuthIntroSource"
"labels": {
"traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.source": "oAuthIntroSource"
}
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.source=oAuthIntroSource"
[http.middlewares]
[http.middlewares.test-oauth-intro.plugin.oAuthIntrospection]
source = "oAuthIntroSource"
http:
middlewares:
test-oauth-intro:
plugin:
oAuthIntrospection:
source: oAuthIntroSource
Middleware Options¶
source
¶
Required, Default=""
The source
option should contain the name of the Authentication Source used by the middleware.
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.source=oAuthIntroSource"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-oauth-intro
spec:
plugin:
oAuthIntrospection:
source: oAuthIntroSource
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.source=oAuthIntroSource"
"labels": {
"traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.source": "oAuthIntroSource"
}
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.source=oAuthIntroSource"
[http.middlewares]
[http.middlewares.test-oauth-intro.plugin.oAuthIntrospection]
source = "oAuthIntroSource"
http:
middlewares:
test-oauth-intro:
plugin:
oAuthIntrospection:
source: oAuthIntroSource
tokenQueryKey
¶
Optional, Default=""
The tokenQueryKey
sets the middleware to look for the token to introspect in a specific query parameter if not found in the Authorization
header. The middleware will always look in the Authorization
header first.
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenQueryKey=tok"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-oauth-intro
spec:
plugin:
oAuthIntrospection:
tokenQueryKey: tok
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenQueryKey=tok"
"labels": {
"traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenQueryKey": "tok"
}
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenQueryKey=tok"
[http.middlewares]
[http.middlewares.test-oauth-intro.plugin.oAuthIntrospection]
tokenQueryKey = "tok"
http:
middlewares:
test-oauth-intro:
plugin:
oAuthIntrospection:
tokenQueryKey: tok
tokenTypeHint
¶
Optional, Default=""
The tokenTypeHint
is a hint to the introspection server as to what type of token is being introspected. Please refer to the official documentation for more details.
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenTypeHint=access_token"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-oauth-intro
spec:
plugin:
oAuthIntrospection:
tokenTypeHint: access_token
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenTypeHint=access_token"
"labels": {
"traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenTypeHint": "access_token"
}
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenTypeHint=access_token"
[http.middlewares]
[http.middlewares.test-oauth-intro.plugin.oAuthIntrospection]
tokenTypeHint = "access_token"
http:
middlewares:
test-oauth-intro:
plugin:
oAuthIntrospection:
tokenTypeHint: access_token
forwardAuthorization
¶
Optional, Default=false
The forwardAuthorization
option determines if the authorization headers will be forwarded or stripped from a request after it has been approved by the middleware.
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardAuthorization=true"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-oauth-intro
spec:
plugin:
oAuthIntrospection:
forwardAuthorization: true
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardAuthorization=true"
"labels": {
"traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardAuthorization": "true"
}
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardAuthorization=true"
[http.middlewares]
[http.middlewares.test-oauth-intro.plugin.oAuthIntrospection]
forwardAuthorization = true
http:
middlewares:
test-oauth-intro:
plugin:
oAuthIntrospection:
forwardAuthorization: true
forwardHeaders
¶
Optional, Default=None
The forwardHeaders
option sets the HTTP headers to add to requests and populates them with values extracted from an introspection response.
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Group=grp"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Scope=scope"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-oauth-intro
spec:
plugin:
oAuthIntrospection:
forwardHeaders:
Group: grp
Scope: scope
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Group=grp"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Scope=scope"
"labels": {
"traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Group": "grp",
"traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Scope": "scope"
}
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Group=grp"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Scope=scope"
[http.middlewares]
[http.middlewares.test-oauth-intro.plugin.oAuthIntrospection]
[http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders]
Group = "grp"
Scope = "scope"
http:
middlewares:
test-oauth-intro:
plugin:
oAuthIntrospection:
forwardHeaders:
Group: grp
Scope: scope
claims
¶
Optional, Default=""
The claims
option sets claims to validate in order to authorize the request.
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.claims=Equals(`grp`, `admin`)"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-oauth-intro
spec:
plugin:
oAuthIntrospection:
claims: Equals(`grp`, `admin`)
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.claims=Equals(`grp`, `admin`)"
"labels": {
"traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.claims": "Equals(`grp`, `admin`)"
}
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.claims=Equals(`grp`, `admin`)"
[http.middlewares]
[http.middlewares.test-oauth-intro.plugin.oAuthIntrospection]
claims = "Equals(`grp`, `admin`)"
http:
middlewares:
test-oauth-intro:
plugin:
oAuthIntrospection:
claims: Equals(`grp`, `admin`)
Syntax¶
The following functions are supported in claims
:
Function | Description | Example |
---|---|---|
Equals | Validated the equality of the value in key with value . |
Equals(`grp`, `admin`) |
Prefix | Validates the value in key has the prefix of value . |
Prefix(`referrer`, `http://example.com`) |
Contains (string) | Validates the value in key contains value . |
Contains(`referrer`, `/foo/`) |
Contains (array) | Validates the key array contains the value . |
Contains(`areas`, `home`) |
SplitContains | Validates the value in key contains the value once split by the separator. |
SplitContains(`scope`, ` `, `writer`) |
OneOf | Validates the key array contains one of the values . |
OneOf(`areas`, `office`, `lab`) |
All functions can be joined by boolean operands. The supported operands are:
Operand | Description | Example |
---|---|---|
&& | Compares two functions and returns true only if both evaluate to true. | Equals(`grp`, `admin`) && Equals(`active`, `true`) |
|| | Compares two functions and returns true if either evaluate to true. | Equals(`grp`, `admin`) || Equals(`active`, `true`) |
! | Returns false if the function is true, otherwise returns true. | !Equals(`grp`, `testers`) |
All examples will return true for the following data structure:
{
"active": true,
"grp": "admin",
"scope": "reader writer deploy",
"referrer": "http://example.com/foo/bar",
"areas": [
"office",
"home"
]
}
Nested claims¶
Nested claims are supported by using a .
between keys. For example:
user.name
{
"active": true,
"grp": "admin",
"scope": "reader writer deploy",
"referrer": "http://example.com/foo/bar",
"areas": [
"office",
"home"
],
"user" {
"name": "John Snow",
"status": "undead"
}
}
John Snow
Handling keys that contain a '.'
If the key
contains a dot, the dot can be escaped using \.
Handling a key that contains a '\'
If the key
contains a \
, it needs to be doubled \\
.
Advanced Configuration Example¶
Below is an advanced configuration example using custom claims validation and forward headers:
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.source=oAuthIntroSource"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenQueryKey=tok"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenTypeHint=access_token"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Group=grp"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Expires-At=exp"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.claims=Equals(`grp`, `admin`)"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-oauth-intro
spec:
plugin:
oAuthIntrospection:
source: oAuthIntroSource
tokenQueryKey: tok
tokenTypeHint: access_token
forwardHeaders:
Group: grp
Expires-At: exp
claims: Equals(`grp`, `admin`)
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.source=oAuthIntroSource"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenQueryKey=tok"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenTypeHint=access_token"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Group=grp"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Expires-At=exp"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.claims=Equals(`grp`, `admin`)"
"labels": {
"traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.source": "oAuthIntroSource"
"traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenQueryKey": "tok"
"traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenTypeHint": "access_token"
"traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Group": "grp"
"traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Expires-At": "exp"
"traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.claims": "Equals(`grp`, `admin`)"
}
labels:
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.source=oAuthIntroSource"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenQueryKey=tok"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.tokenTypeHint=access_token"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Group=grp"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders.Expires-At=exp"
- "traefik.http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.claims=Equals(`grp`, `admin`)"
[http.middlewares]
[http.middlewares.test-oauth-intro.plugin.oAuthIntrospection]
source = "oAuthIntroSource"
tokenQueryKey = "tok"
tokenTypeHint = "access_token"
claims = "Equals(`grp`, `admin`)"
[http.middlewares.test-oauth-intro.plugin.oAuthIntrospection.forwardHeaders]
Group = "grp"
Expires-At = "exp"
http:
middlewares:
test-oauth-intro:
plugin:
oAuthIntrospection:
source: oAuthIntroSource
tokenQueryKey: tok
tokenTypeHint: access_token
forwardHeaders:
Group: grp
Expires-At: exp
claims: Equals(`grp`, `admin`)