OIDC Auth Method
Enterprise
This feature requires version 1.8.0+ of self-managed Consul Enterprise. Refer to the enterprise feature matrix for additional information.
The oidc
auth method can be used to authenticate with Consul using OIDC. This method allows authentication via a configured OIDC provider using the user’s web browser. This method may be initiated from the Consul UI or the command line.
This page assumes general knowledge of OIDC concepts and the concepts described in the main auth method documentation.
Both the jwt and the oidc auth method types allow additional processing of the claims data in the JWT.
JWT vs OIDC Auth Methods
Since both the oidc
and jwt
auth methods ultimately operate on JWTs as bearer tokens, it may be confusing to know which is right for a given use case.
JWT: The user or application performing the Consul login must already be in possession of a valid JWT to begin. There is no browser interaction required. This is ideal for machine-oriented headless login where an operator may have already arranged for a valid JWT to be dropped on a VM or provided to a container.
OIDC: The user performing the Consul login does not have a JWT nor do they even need to know what that means. This is ideal for human-oriented interactive login where an operator or administrator may have deployed SSO widely and doesn’t want to have the burden of tracking and distributing Consul ACL tokens to any authorized coworker who may need to have access to a Consul instance. Browser interaction is required. This is only available in Consul Enterprise.
Config Parameters
The following auth method Config parameters are required to properly configure an auth method of type oidc
:
OIDCDiscoveryURL
(string: <required>)
- The OIDC Discovery URL, without any .well-known component (base path).OIDCDiscoveryCACert
(string: "")
- PEM encoded CA cert for use by the TLS client used to talk with the OIDC Discovery URL. NOTE: Every line must end with a newline (\n
). If not set, system certificates are used.OIDCClientID
(string: <required>)
- The OAuth Client ID configured with your OIDC provider.OIDCClientSecret
(string: <required>)
- The OAuth Client Secret configured with your OIDC provider.AllowedRedirectURIs
(array<string>)
- A list of allowed values forredirect_uri
. Must be non-empty.ClaimMappings
(map[string]string)
- Mappings of claims (key) that will be copied to a metadata field (value). Use this if the claim you are capturing is singular (such as an attribute).When mapped, the values can be any of a number, string, or boolean and will all be stringified when returned.
ListClaimMappings
(map[string]string)
- Mappings of claims (key) will be copied to a metadata field (value). Use this if the claim you are capturing is list-like (such as groups).When mapped, the values in each list can be any of a number, string, or boolean and will all be stringified when returned.
OIDCScopes
(array<string>)
- A list of OIDC scopes.OIDCACRValues
(array<string>)
- A list of Authentication Context Class Reference values to use for the authentication request. See OIDC reference for more info on this parameter. Added in v1.11.0.JWTSupportedAlgs
(array<string>)
- JWTSupportedAlgs is a list of supported signing algorithms. Defaults toRS256
. (Available algorithms)BoundAudiences
(array<string>)
- List ofaud
claims that are valid for login; any match is sufficient.VerboseOIDCLogging
(bool: false)
- Log received OIDC tokens and claims when debug-level logging is active. Not recommended in production since sensitive information may be present in OIDC responses.
Sample Config
{
...other fields...
"Config": {
"AllowedRedirectURIs": [
"http://localhost:8550/oidc/callback",
"http://localhost:8500/ui/oidc/callback"
],
"BoundAudiences": [
"V1RPi2MYptMV1RPi2MYptMV1RPi2MYpt"
],
"ClaimMappings": {
"http://example.com/first_name": "first_name",
"http://example.com/last_name": "last_name"
},
"ListClaimMappings": {
"http://consul.com/groups": "groups"
},
"OIDCClientID": "V1RPi2MYptMV1RPi2MYptMV1RPi2MYpt",
"OIDCClientSecret": "...(omitted)...",
"OIDCDiscoveryURL": "https://my-corp-app-name.auth0.com/"
}
}
{
...other fields...
"Config": {
"AllowedRedirectURIs": [
"http://localhost:8550/oidc/callback",
"http://localhost:8500/ui/oidc/callback"
],
"BoundAudiences": [
"V1RPi2MYptMV1RPi2MYptMV1RPi2MYpt"
],
"ClaimMappings": {
"http://example.com/first_name": "first_name",
"http://example.com/last_name": "last_name"
},
"ListClaimMappings": {
"http://consul.com/groups": "groups"
},
"OIDCClientID": "V1RPi2MYptMV1RPi2MYptMV1RPi2MYpt",
"OIDCClientSecret": "...(omitted)...",
"OIDCDiscoveryURL": "https://my-corp-app-name.auth0.com/"
}
}
JWT Verification
JWT signatures will be verified against public keys from the issuer via OIDC discovery. Keys will be fetched from the OIDC Discovery URL during authentication and OIDC validation criteria (e.g. iss
, aud
, etc.) will be applied.
OIDC Authentication
Consul includes two built-in OIDC login flows: the Consul UI, and the CLI using consul login.
Redirect URIs
An important part of OIDC auth method configuration is properly setting redirect URIs. This must be done both in Consul and with the OIDC provider, and these configurations must align. The redirect URIs are specified for an auth method with the AllowedRedirectURIs parameter. There are different redirect URIs to configure the Consul UI and CLI flows, so one or both will need to be set up depending on the installation.
Consul UI
Logging in via the Consul UI requires a redirect URI of the form: http://localhost:8500/ui/oidc/callback
or https://{host:port}/ui/oidc/callback
The “host:port” must be correct for the Consul agent serving the Consul UI.
CLI
If you plan to support authentication via consul login -type=oidc -method=<name>
, a localhost redirect URI must be set (usually this is http://localhost:8550/oidc/callback
). Logins via the CLI may specify a different host and/or listening port if needed, and a URI with this host/port must match one of the configured redirected URIs. These same “localhost” URIs must be added to the provider as well.
OIDC Login
Consul UI
- Click the “Log in” link at the top right of the menu bar.
- Click one of the “Continue with…” buttons for your OIDC auth method of choice.
- Complete the authentication with the configured provider.
CLI
$ consul login -method=oidc -type=oidc -token-sink-file=consul.token
Complete the login via your OIDC provider. Launching browser to:
https://myco.auth0.com/authorize?redirect_uri=http%3A%2F%2Flocalhost%3A8550%2Foidc%2Fcallback&client_id=r3qXc2bix9eF...
$ consul login -method=oidc -type=oidc -token-sink-file=consul.token
Complete the login via your OIDC provider. Launching browser to:
https://myco.auth0.com/authorize?redirect_uri=http%3A%2F%2Flocalhost%3A8550%2Foidc%2Fcallback&client_id=r3qXc2bix9eF...
The browser will open to the generated URL to complete the provider’s login. The URL may be entered manually if the browser cannot be automatically opened.
The callback listener may be customized with the following optional parameters. These are typically not required to be set:
The callback listener defaults to listen on localhost:8550
. If you want to customize that use the optional flag -oidc-callback-listen-addr=
OIDC Configuration Troubleshooting
The amount of configuration required for OIDC is relatively small, but it can be tricky to debug why things aren’t working. Some tips for setting up OIDC:
Monitor the log output for the Consul servers. Important information about OIDC validation failures will be emitted.
Ensure Redirect URIs are correct in Consul and on the provider. They need to match exactly. Check: http/https, 127.0.0.1/localhost, port numbers, whether trailing slashes are present.
BoundAudiences is optional and typically not required. OIDC providers will use the
client_id
as the audience and OIDC validation expects this.Check your provider for what scopes are required in order to receive all of the information you need. The scopes “profile” and “groups” often need to be requested, and can be added by setting
[OIDCScopes](#oidcscopes)="profile,groups"
on the auth method.If you’re seeing claim-related errors in logs, review the provider’s docs very carefully to see how they’re naming and structuring their claims. Depending on the provider, you may be able to construct a simple
curl
implicit grant request to obtain a JWT that you can inspect. An example of how to decode the JWT (in this case located in theaccess_token
field of a JSON response):cat jwt.json | jq --raw-output .access_token | cut -d. -f2 | base64 --decode
cat jwt.json | jq --raw-output .access_token | cut -d. -f2 | base64 --decode
The VerboseOIDCLogging option is available which will log the received OIDC token if debug level logging is enabled. This can be helpful when debugging provider setup and verifying that the received claims are what you expect. Since claims data is logged verbatim and may contain sensitive information, this option should not be used in production.
Trusted Identity Attributes via Claim Mappings
Data from JWT claims can be returned from the authentication step as trusted identity attributes for use in binding rule selectors and bind name interpolation.
Control of which claims are mapped to which identity attributes is governed by the ClaimMappings and ListClaimMappings. These are both maps of items to copy with elements of the form: "<JWT claim>":"<attribute suffix>"
.
The only difference between these two types of mappings is that ClaimMappings
is used to map singular values (such as a name, department, or team) while ListClaimMappings
is used to map lists of values.
The singular values mapped by ClaimMappings
can be interpolated in a binding rule, and the lists of values mapped by ListClaimMappings
cannot.
Assume this is your config snippet:
{ ...other fields...
"ClaimMappings": {
"givenName": "first_name",
"surname": "last_name"
},
"ListClaimMappings": {
"groups": "groups"
}
}
{ ...other fields...
"ClaimMappings": {
"givenName": "first_name",
"surname": "last_name"
},
"ListClaimMappings": {
"groups": "groups"
}
}
This specifies that the values in the JWT claims "givenName"
and "surname"
should be copied to attributes named "value.first_name"
and "value.last_name"
respectively. Additionally the list of values in the JWT claim "groups"
should be copied to an attribute named "list.groups"
.
The following table shows the resulting attributes that will be extracted, and the ways they may be used in Rule Bindings:
Attributes | Supported Selector Operations | Can be Interpolated |
---|---|---|
value.first_name | Equal, Not Equal, In, Not In, Matches, Not Matches | yes |
value.last_name | Equal, Not Equal, In, Not In, Matches, Not Matches | yes |
list.groups | In, Not In, Is Empty, Is Not Empty | no |
Claim Specifications and JSON Pointer
The ClaimMappings and ListClaimMappings fields are used to point to data within the JWT. If the desired key is at the top of level of the JWT, the name can be provided directly. If it is nested at a lower level, a JSON Pointer may be used.
Assume the following JWT claims are decoded:
{
"division": "North America",
"groups": {
"primary": "Engineering",
"secondary": "Software"
},
"iss": "https://my-corp-app-name.auth0.com/",
"sub": "auth0|eiw7OWoh5ieSh7ieyahC3ief0uyuraphaengae9d",
"aud": "V1RPi2MYptMV1RPi2MYptMV1RPi2MYpt",
"iat": 1589224148,
"exp": 1589260148,
"nonce": "eKiihooH3Fah8Ieshah4leeti6ien3"
}
{
"division": "North America",
"groups": {
"primary": "Engineering",
"secondary": "Software"
},
"iss": "https://my-corp-app-name.auth0.com/",
"sub": "auth0|eiw7OWoh5ieSh7ieyahC3ief0uyuraphaengae9d",
"aud": "V1RPi2MYptMV1RPi2MYptMV1RPi2MYpt",
"iat": 1589224148,
"exp": 1589260148,
"nonce": "eKiihooH3Fah8Ieshah4leeti6ien3"
}
A parameter of "division"
will reference "North America"
, as this is a top level key. A parameter "/groups/primary"
uses JSON Pointer syntax to reference "Engineering"
at a lower level. Any valid JSON Pointer can be used as a selector. Refer to the JSON Pointer RFC for a full description of the syntax