679 lines
35 KiB
Plaintext
679 lines
35 KiB
Plaintext
[role="xpack"]
|
|
[[oidc-guide]]
|
|
|
|
== Configuring single sign-on to the {stack} using OpenID Connect
|
|
|
|
The Elastic Stack supports single sign-on (SSO) using OpenID Connect via {kib} using
|
|
{es} as the backend service that holds most of the functionality. {kib} and {es}
|
|
together represent an OpenID Connect Relying Party (RP) that supports the authorization code flow and implicit flow as these are defined in the OpenID Connect specification.
|
|
|
|
This guide assumes that you have an OpenID Connect Provider where the
|
|
Elastic Stack Relying Party will be registered.
|
|
|
|
NOTE: The OpenID Connect realm support in {kib} is designed with the expectation that it
|
|
will be the primary authentication method for the users of that {kib} instance. The
|
|
<<oidc-kibana>> section describes what this entails and how you can set it up to support
|
|
other realms if necessary.
|
|
|
|
[[oidc-guide-op]]
|
|
=== The OpenID Connect Provider
|
|
|
|
The OpenID Connect Provider (OP) is the entity in OpenID Connect that is responsible for
|
|
authenticating the user and for granting the necessary tokens with the authentication and
|
|
user information to be consumed by the Relying Parties.
|
|
|
|
In order for the Elastic Stack to be able use your OpenID Connect Provider for authentication,
|
|
a trust relationship needs to be established between the OP and the RP. In the OpenID Connect
|
|
Provider, this means registering the RP as a client. OpenID Connect defines a dynamic client
|
|
registration protocol but this is usually geared towards real-time client registration and
|
|
not the trust establishment process for cross security domain single sign on. All OPs will
|
|
also allow for the manual registration of an RP as a client, via a user interface or (less often)
|
|
via the consumption of a metadata document.
|
|
|
|
The process for registering the Elastic Stack RP will be different from OP to OP and following
|
|
the provider's relevant documentation is prudent. The information for the
|
|
RP that you commonly need to provide for registration are the following:
|
|
|
|
- `Relying Party Name`: An arbitrary identifier for the relying party. Neither the specification
|
|
nor the Elastic Stack implementation impose any constraints on this value.
|
|
- `Redirect URI`: This is the URI where the OP will redirect the user's browser after authentication. The
|
|
appropriate value for this will depend on your setup and whether or not {kib} sits behind a proxy or
|
|
load balancer. It will typically be +$\{kibana-url}/api/security/v1/oidc+ (for the authorization code flow) or +$\{kibana-url}/api/security/v1/oidc/implicit+ (for the implicit flow) where _$\{kibana-url}_ is the base URL for your {kib} instance. You might also see this
|
|
called `Callback URI`.
|
|
|
|
At the end of the registration process, the OP will assign a Client Identifier and a Client Secret for the RP ({stack}) to use.
|
|
Note these two values as they will be used in the {es} configuration.
|
|
|
|
[[oidc-guide-authentication]]
|
|
=== Configure {es} for OpenID Connect authentication
|
|
|
|
The following is a summary of the configuration steps required in order to enable authentication
|
|
using OpenID Connect in {es}:
|
|
|
|
. <<oidc-enable-http,Enable SSL/TLS for HTTP>>
|
|
. <<oidc-enable-token,Enable the Token Service>>
|
|
. <<oidc-create-realm,Create one or more OpenID Connect realms>>
|
|
. <<oidc-role-mapping,Configure role mappings>>
|
|
|
|
[[oidc-enable-http]]
|
|
==== Enable TLS for HTTP
|
|
|
|
If your {es} cluster is operating in production mode, then you must
|
|
configure the HTTP interface to use SSL/TLS before you can enable OpenID Connect
|
|
authentication.
|
|
|
|
For more information, see
|
|
{ref}/configuring-tls.html#tls-http[Encrypting HTTP Client Communications].
|
|
|
|
[[oidc-enable-token]]
|
|
==== Enable the token service
|
|
|
|
The {es} OpenID Connect implementation makes use of the {es} Token Service. This service
|
|
is automatically enabled if you configure TLS on the HTTP interface, and can be
|
|
explicitly configured by including the following in your `elasticsearch.yml` file:
|
|
|
|
[source, yaml]
|
|
------------------------------------------------------------
|
|
xpack.security.authc.token.enabled: true
|
|
------------------------------------------------------------
|
|
|
|
[[oidc-create-realm]]
|
|
==== Create an OpenID Connect realm
|
|
|
|
OpenID Connect based authentication is enabled by configuring the appropriate realm within
|
|
the authentication chain for {es}.
|
|
|
|
This realm has a few mandatory settings, and a number of optional settings.
|
|
The available settings are described in detail in the
|
|
{ref}/security-settings.html#ref-oidc-settings[Security settings in {es}]. This
|
|
guide will explore the most common settings.
|
|
|
|
Create an OpenID Connect (the realm type is `oidc`) realm in your `elasticsearch.yml` file
|
|
similar to what is shown below:
|
|
|
|
NOTE: The values used below are meant to be an example and are not intended to apply to
|
|
every use case. The details below the configuration snippet provide insights and suggestions
|
|
to help you pick the proper values, depending on your OP configuration.
|
|
|
|
[source, yaml]
|
|
-------------------------------------------------------------------------------------
|
|
xpack.security.authc.realms.oidc.oidc1:
|
|
order: 2
|
|
rp.client_id: "the_client_id"
|
|
rp.response_type: code
|
|
rp.redirect_uri: "https://kibana.example.org:5601/api/security/v1/oidc"
|
|
op.issuer: "https://op.example.org"
|
|
op.authorization_endpoint: "https://op.example.org/oauth2/v1/authorize"
|
|
op.token_endpoint: "https://op.example.org/oauth2/v1/token"
|
|
op.jwkset_path: oidc/jwkset.json
|
|
op.userinfo_endpoint: "https://op.example.org/oauth2/v1/userinfo"
|
|
op.endsession_endpoint: "https://op.example.org/oauth2/v1/logout"
|
|
rp.post_logout_redirect_uri: "https://kibana.example.org:5601/logged_out"
|
|
claims.principal: sub
|
|
claims.groups: "http://example.info/claims/groups"
|
|
-------------------------------------------------------------------------------------
|
|
|
|
The configuration values used in the example above are:
|
|
|
|
xpack.security.authc.realms.oidc.oidc1::
|
|
This defines a new `oidc` authentication realm named "oidc1".
|
|
See <<realms>> for more explanation of realms.
|
|
|
|
order::
|
|
You should define a unique order on each realm in your authentication chain.
|
|
It is recommended that the OpenID Connect realm be at the bottom of your authentication
|
|
chain (that is, that it has the _highest_ order).
|
|
|
|
rp.client_id::
|
|
This, usually opaque, arbitrary string, is the Client Identifier that was assigned to the Elastic Stack RP by the OP upon
|
|
registration.
|
|
|
|
rp.response_type::
|
|
This is an identifier that controls which OpenID Connect authentication flow this RP supports and also
|
|
which flow this RP requests the OP should follow. Supported values are
|
|
- `code`, which means that the RP wants to use the Authorization Code flow. If your OP supports the
|
|
Authorization Code flow, you should select this instead of the Implicit Flow.
|
|
- `id_token token` which means that the RP wants to use the Implicit flow and we also request an oAuth2
|
|
access token from the OP, that we can potentially use for follow up requests ( UserInfo ). This
|
|
should be selected if the OP offers a UserInfo endpoint in its configuration, or if you know that
|
|
the claims you will need to use for role mapping are not available in the ID Token.
|
|
- `id_token` which means that the RP wants to use the Implicit flow, but is not interested in getting
|
|
an oAuth2 token too. Select this if you are certain that all necessary claims will be contained in
|
|
the ID Token or if the OP doesn't offer a User Info endpoint.
|
|
|
|
rp.redirect_uri::
|
|
The redirect URI where the OP will redirect the browser after authentication. This needs to be
|
|
_exactly_ the same as the one <<oidc-guide-op, configured with the OP upon registration>> and will
|
|
typically be +$\{kibana-url}/api/security/v1/oidc+ where _$\{kibana-url}_ is the base URL for your {kib} instance
|
|
|
|
op.issuer::
|
|
A verifiable Identifier for your OpenID Connect Provider. An Issuer Identifier is usually a case sensitive URL.
|
|
The value for this setting should be provided by your OpenID Connect Provider.
|
|
|
|
op.authorization_endpoint::
|
|
The URL for the Authorization Endpoint in the OP. This is where the user's browser
|
|
will be redirected to start the authentication process. The value for this setting should be provided by your
|
|
OpenID Connect Provider.
|
|
|
|
op.token_endpoint::
|
|
The URL for the Token Endpoint in the OpenID Connect Provider. This is the endpoint where
|
|
{es} will send a request to exchange the code for an ID Token. This setting is optional when
|
|
you use the implicit flow. The value for this setting should be provided by your OpenID Connect Provider.
|
|
|
|
op.jwkset_path::
|
|
The path to a file or a URL containing a JSON Web Key Set with the key material that the OpenID Connect
|
|
Provider uses for signing tokens and claims responses. If a path is set, it is resolved relative to the {es}
|
|
config directory.
|
|
{es} will automatically monitor this file for changes and will reload the configuration whenever
|
|
it is updated. Your OpenID Connect Provider should provide you with this file or a URL where it is available.
|
|
|
|
op.userinfo_endpoint::
|
|
(Optional) The URL for the UserInfo Endpoint in the OpenID Connect Provider. This is the endpoint of the OP that
|
|
can be queried to get further user information, if required. The value for this setting should be provided by your
|
|
OpenID Connect Provider.
|
|
|
|
op.endsession_endpoint::
|
|
(Optional) The URL to the End Session Endpoint in the OpenID Connect Provider. This is the endpoint where the user's
|
|
browser will be redirected after local logout, if the realm is configured for RP initiated Single Logout and
|
|
the OP supports it. The value for this setting should be provided by your OpenID Connect Provider.
|
|
|
|
rp.post_logout_redirect_uri::
|
|
(Optional) The Redirect URL where the OpenID Connect Provider should redirect the user after a
|
|
successful Single Logout (assuming `op.endsession_endpoint` above is also set). This should be set to a value that
|
|
will not trigger a new OpenID Connect Authentication, such as +$\{kibana-url}/logged_out+ where _$\{kibana-url}_ is
|
|
the base URL for your {kib} instance.
|
|
|
|
claims.principal:: See <<oidc-claims-mapping>>.
|
|
claims.groups:: See <<oidc-claims-mapping>>.
|
|
|
|
A final piece of configuration of the OpenID Connect realm is to set the `Client Secret` that was assigned
|
|
to the RP during registration in the OP. This is a secure setting and as such is not defined in the realm
|
|
configuration in `elasticsearch.yml` but added to the {ref}/secure-settings.html[elasticsearch keystore].
|
|
For instance
|
|
|
|
|
|
[source,sh]
|
|
----
|
|
bin/elasticsearch-keystore add xpack.security.authc.realms.oidc.oidc1.rp.client_secret
|
|
----
|
|
|
|
|
|
NOTE: According to the OpenID Connect specification, the OP should also make their configuration
|
|
available at a well known URL, which is the concatenation of their `Issuer` value with the
|
|
`.well-known/openid-configuration` string. For example: `https://op.org.com/.well-known/openid-configuration`
|
|
That document should contain all the necessary information to configure the OpenID Connect realm in {es}.
|
|
|
|
|
|
[[oidc-claims-mapping]]
|
|
==== Claims mapping
|
|
|
|
===== Claims and scopes
|
|
|
|
When authenticating to {kib} using OpenID Connect, the OP will provide information about the user
|
|
in the form of OpenID Connect Claims, that can be included either in the ID Token, or be retrieved from the
|
|
UserInfo endpoint of the OP. The claim is defined as a piece of information asserted by the OP
|
|
for the authenticated user. Simply put, a claim is a name/value pair that contains information about
|
|
the user. Related to claims, we also have the notion of OpenID Connect Scopes. Scopes are identifiers
|
|
that are used to request access to specific lists of claims. The standard defines a set of scope
|
|
identifiers that can be requested. The only mandatory one is `openid`, while commonly used ones are
|
|
`profile` and `email`. The `profile` scope requests access to the `name`,`family_name`,`given_name`,`middle_name`,`nickname`,
|
|
`preferred_username`,`profile`,`picture`,`website`,`gender`,`birthdate`,`zoneinfo`,`locale`, and `updated_at` claims.
|
|
The `email` scope requests access to the `email` and `email_verified` claims. The process is that
|
|
the RP requests specific scopes during the authentication request. If the OP Privacy Policy
|
|
allows it and the authenticating user consents to it, the related claims are returned to the
|
|
RP (either in the ID Token or as a UserInfo response).
|
|
|
|
The list of the supported claims will vary depending on the OP you are using, but you can expect
|
|
the https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims[Standard Claims] to be
|
|
largely supported.
|
|
|
|
[[oidc-claim-to-property]]
|
|
===== Mapping claims to user properties
|
|
|
|
The goal of claims mapping is to configure {es} in such a way as to be able to map the values of
|
|
specified returned claims to one of the <<oidc-user-properties, user properties>> that are supported
|
|
by {es}. These user properties are then utilized to identify the user in the {kib} UI or the audit
|
|
logs, and can also be used to create <<oidc-role-mapping, role mapping>> rules.
|
|
|
|
The recommended steps for configuring OpenID Claims mapping are as follows:
|
|
|
|
. Consult your OP configuration to see what claims it might support. Note that
|
|
the list provided in the OP's metadata or in the configuration page of the OP
|
|
is a list of potentially supported claims. However, for privacy reasons it might
|
|
not be a complete one, or not all supported claims will be available for all
|
|
authenticated users.
|
|
|
|
. Read through the list of <<oidc-user-properties, user properties>> that {es}
|
|
supports, and decide which of them are useful to you, and can be provided by
|
|
your OP in the form of claims. At a _minimum_, the `principal` user property
|
|
is required.
|
|
|
|
. Configure your OP to "release" those claims to your {stack} Relying
|
|
party. This process greatly varies by provider. You can use a static
|
|
configuration while others will support that the RP requests the scopes that
|
|
correspond to the claims to be "released" on authentication time. See
|
|
{ref}/security-settings.html#ref-oidc-settings[`rp.requested_scopes`] for details about how
|
|
to configure the scopes to request. To ensure interoperability and minimize
|
|
the errors, you should only request scopes that the OP supports, and which you
|
|
intend to map to {es} user properties.
|
|
|
|
. Configure the OpenID Connect realm in {es} to associate the {es} user properties (see
|
|
<<oidc-user-properties, the listing>> below), to the name of the claims that your
|
|
OP will release. In the example above, we have configured the `principal` and
|
|
`groups` user properties as follows:
|
|
|
|
.. `claims.principal: sub` : This instructs {es} to look for the OpenID Connect claim named `sub`
|
|
in the ID Token that the OP issued for the user ( or in the UserInfo response ) and assign the
|
|
value of this claim to the `principal` user property. `sub` is a commonly used claim for the
|
|
principal property as it is an identifier of the user in the OP and it is also a required
|
|
claim of the ID Token, thus offering guarantees that it will be available. It is, however,
|
|
only used as an example here, the OP may provide another claim that is a better fit for your needs.
|
|
|
|
.. `claims.groups: "http://example.info/claims/groups"` : Similarly, this instructs {es} to look
|
|
for the claim with the name `http://example.info/claims/groups` (note that this is a URI - an
|
|
identifier, treated as a string and not a URL pointing to a location that will be retrieved)
|
|
either in the ID Token or in the UserInfo response, and map the value(s) of it to the user
|
|
property `groups` in {es}. There is no standard claim in the specification that is used for
|
|
expressing roles or group memberships of the authenticated user in the OP, so the name of the
|
|
claim that should be mapped here, will vary greatly between providers. Consult your OP
|
|
documentation for more details.
|
|
|
|
[[oidc-user-properties]]
|
|
===== {es} user properties
|
|
|
|
The {es} OpenID Connect realm can be configured to map OpenID Connect claims to the
|
|
following properties on the authenticated user:
|
|
|
|
principal:: _(Required)_
|
|
This is the _username_ that will be applied to a user that authenticates
|
|
against this realm.
|
|
The `principal` appears in places such as the {es} audit logs.
|
|
|
|
NOTE: If the principal property fails to be mapped from a claim, the authentication fails.
|
|
|
|
groups:: _(Recommended)_
|
|
If you wish to use your OP's concept of groups or roles as the basis for a
|
|
user's {es} privileges, you should map them with this property.
|
|
The `groups` are passed directly to your <<oidc-role-mapping, role mapping rules>>.
|
|
|
|
name:: _(Optional)_ The user's full name.
|
|
mail:: _(Optional)_ The user's email address.
|
|
dn:: _(Optional)_ The user's X.500 _Distinguished Name_.
|
|
|
|
|
|
===== Extracting partial values from OpenID Connect claims
|
|
|
|
There are some occasions where the value of a claim may contain more information
|
|
than you wish to use within {es}. A common example of this is one where the
|
|
OP works exclusively with email addresses, but you would like the user's
|
|
`principal` to use the _local-name_ part of the email address.
|
|
For example if their email address was `james.wong@staff.example.com`, then you
|
|
would like their principal to simply be `james.wong`.
|
|
|
|
This can be achieved using the `claim_patterns` setting in the {es}
|
|
realm, as demonstrated in the realm configuration below:
|
|
|
|
[source, yaml]
|
|
-------------------------------------------------------------------------------------
|
|
xpack.security.authc.realms.oidc.oidc1:
|
|
order: 2
|
|
rp.client_id: "the_client_id"
|
|
rp.response_type: code
|
|
rp.redirect_uri: "https://kibana.example.org:5601/api/security/v1/oidc"
|
|
op.authorization_endpoint: "https://op.example.org/oauth2/v1/authorize"
|
|
op.token_endpoint: "https://op.example.org/oauth2/v1/token"
|
|
op.userinfo_endpoint: "https://op.example.org/oauth2/v1/userinfo"
|
|
op.endsession_endpoint: "https://op.example.org/oauth2/v1/logout"
|
|
op.issuer: "https://op.example.org"
|
|
op.jwkset_path: oidc/jwkset.json
|
|
claims.principal: email_verified
|
|
claim_patterns.principal: "^([^@]+)@staff\\.example\\.com$"
|
|
-------------------------------------------------------------------------------------
|
|
|
|
In this case, the user's `principal` is mapped from the `email_verified` claim, but a
|
|
regular expression is applied to the value before it is assigned to the user.
|
|
If the regular expression matches, then the result of the first group is used as the
|
|
effective value. If the regular expression does not match then the claim
|
|
mapping fails.
|
|
|
|
In this example, the email address must belong to the `staff.example.com` domain,
|
|
and then the local-part (anything before the `@`) is used as the principal.
|
|
Any users who try to login using a different email domain will fail because the
|
|
regular expression will not match against their email address, and thus their
|
|
principal user property - which is mandatory - will not be populated.
|
|
|
|
IMPORTANT: Small mistakes in these regular expressions can have significant
|
|
security consequences. For example, if we accidentally left off the trailing
|
|
`$` from the example above, then we would match any email address where the
|
|
domain starts with `staff.example.com`, and this would accept an email
|
|
address such as `admin@staff.example.com.attacker.net`. It is important that
|
|
you make sure your regular expressions are as precise as possible so that
|
|
you do not inadvertently open an avenue for user impersonation attacks.
|
|
|
|
[[third-party-login]]
|
|
==== Third party initiated single sign-on
|
|
|
|
The Open ID Connect realm in {es} supports 3rd party initiated login as described in the
|
|
https://openid.net/specs/openid-connect-core-1_0.html#ThirdPartyInitiatedLogin[relevant specification].
|
|
|
|
This allows the OP itself or another, third party other than the RP, to initiate the authentication
|
|
process while requesting the OP to be used for the authentication. Please note that the Elastic
|
|
Stack RP should already be configured for this OP, in order for this process to succeed.
|
|
|
|
|
|
[[oidc-logout]]
|
|
==== OpenID Connect Logout
|
|
|
|
The OpenID Connect realm in {es} supports RP-Initiated Logout Functionality as
|
|
described in the
|
|
https://openid.net/specs/openid-connect-session-1_0.html#RPLogout[relevant part of the specification]
|
|
|
|
In this process, the OpenID Connect RP (the Elastic Stack in this case) will redirect the user's
|
|
browser to predefined URL of the OP after successfully completing a local logout. The OP can then
|
|
logout the user also, depending on the configuration, and should finally redirect the user back to the
|
|
RP. The `op.endsession_endpoint` in the realm configuration determines the URL in the OP that the browser
|
|
will be redirected to. The `rp.post_logout_redirect_uri` setting determines the URL to redirect
|
|
the user back to after the OP logs them out.
|
|
|
|
When configuring `rp.post_logout_redirect_uri`, care should be taken to not point this to a URL that
|
|
will trigger re-authentication of the user. For instance, when using OpenID Connect to support
|
|
single sign-on to {kib}, this could be set to +$\{kibana-url}/logged_out+, which will show a user-
|
|
friendly message to the user.
|
|
|
|
[[oidc-ssl-config]]
|
|
==== OpenID Connect Realm SSL Configuration
|
|
|
|
OpenID Connect depends on TLS to provide security properties such as encryption in transit and endpoint authentication. The RP
|
|
is required to establish back-channel communication with the OP in order to exchange the code for an ID Token during the
|
|
Authorization code grant flow and in order to get additional user information from the UserInfo endpoint. Furthermore, if
|
|
you configure `op.jwks_path` as a URL, {es} will need to get the OP's signing keys from the file hosted there. As such, it is
|
|
important that {es} can validate and trust the server certificate that the OP uses for TLS. Since the system truststore is
|
|
used for the client context of outgoing https connections, if your OP is using a certificate from a trusted CA, no additional
|
|
configuration is needed.
|
|
|
|
However, if the issuer of your OP's certificate is not trusted by the JVM on which {es} is running (e.g it uses a organization CA), then you must configure
|
|
{es} to trust that CA. Assuming that you have the CA certificate that has signed the certificate that the OP uses for TLS
|
|
stored in the /oidc/company-ca.pem` file stored in the configuration directory of {es}, you need to set the following
|
|
property in the realm configuration:
|
|
|
|
[source, yaml]
|
|
-------------------------------------------------------------------------------------
|
|
xpack.security.authc.realms.oidc.oidc1:
|
|
order: 1
|
|
...
|
|
ssl.certificate_authorities: ["/oidc/company-ca.pem"]
|
|
-------------------------------------------------------------------------------------
|
|
|
|
[[oidc-role-mapping]]
|
|
=== Configuring role mappings
|
|
|
|
When a user authenticates using OpenID Connect, they are identified to the Elastic Stack,
|
|
but this does not automatically grant them access to perform any actions or
|
|
access any data.
|
|
|
|
Your OpenID Connect users cannot do anything until they are assigned roles. This can be done
|
|
through either the
|
|
{ref}/security-api-put-role-mapping.html[add role mapping API], or with
|
|
<<authorization_realms, authorization realms>>.
|
|
|
|
NOTE: You cannot use {stack-ov}/mapping-roles.html#mapping-roles-file[role mapping files]
|
|
to grant roles to users authenticating via OpenID Connect.
|
|
|
|
This is an example of a simple role mapping that grants the `kibana_user` role
|
|
to any user who authenticates against the `oidc1` OpenID Connect realm:
|
|
|
|
[source,console]
|
|
--------------------------------------------------
|
|
PUT /_security/role_mapping/oidc-kibana
|
|
{
|
|
"roles": [ "kibana_user" ],
|
|
"enabled": true,
|
|
"rules": {
|
|
"field": { "realm.name": "oidc1" }
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
|
|
|
|
The user properties that are mapped via the realm configuration are used to process
|
|
role mapping rules, and these rules determine which roles a user is granted.
|
|
|
|
The user fields that are provided to the role
|
|
mapping are derived from the OpenID Connect claims as follows:
|
|
|
|
- `username`: The `principal` user property
|
|
- `dn`: The `dn` user property
|
|
- `groups`: The `groups` user property
|
|
- `metadata`: See <<oidc-user-metadata>>
|
|
|
|
For more information, see <<mapping-roles>> and
|
|
{ref}/security-api.html#security-role-mapping-apis[role mapping APIs].
|
|
|
|
If your OP has the ability to provide groups or roles to RPs via tha use of
|
|
an OpenID Claim, then you should map this claim to the `claims.groups` setting in
|
|
the {es} realm (see <<oidc-claim-to-property>>), and then make use of it in a role mapping
|
|
as per the example below.
|
|
|
|
This mapping grants the {es} `finance_data` role, to any users who authenticate
|
|
via the `oidc1` realm with the `finance-team` group membership.
|
|
|
|
[source,console]
|
|
--------------------------------------------------
|
|
PUT /_security/role_mapping/oidc-finance
|
|
{
|
|
"roles": [ "finance_data" ],
|
|
"enabled": true,
|
|
"rules": { "all": [
|
|
{ "field": { "realm.name": "oidc1" } },
|
|
{ "field": { "groups": "finance-team" } }
|
|
] }
|
|
}
|
|
--------------------------------------------------
|
|
|
|
If your users also exist in a repository that can be directly accessed by {es}
|
|
(such as an LDAP directory) then you can use
|
|
<<authorization_realms, authorization realms>> instead of role mappings.
|
|
|
|
In this case, you perform the following steps:
|
|
1. In your OpenID Connect realm, assign a claim to act as the lookup userid,
|
|
by configuring the `claims.principal` setting.
|
|
2. Create a new realm that can lookup users from your local repository (e.g. an
|
|
`ldap` realm)
|
|
3. In your OpenID Connect realm, set `authorization_realms` to the name of the realm you
|
|
created in step 2.
|
|
|
|
[[oidc-user-metadata]]
|
|
=== User metadata
|
|
|
|
By default users who authenticate via OpenID Connect will have some additional metadata
|
|
fields. These fields will include every OpenID Claim that is provided in the authentication response
|
|
(regardless of whether it is mapped to an {es} user property). For example,
|
|
in the metadata field `oidc(claim_name)`, "claim_name" is the name of the
|
|
claim as it was contained in the ID Token or in the User Info response. Note that these will
|
|
include all the https://openid.net/specs/openid-connect-core-1_0.html#IDToken[ID Token claims]
|
|
that pertain to the authentication event, rather than the user themselves.
|
|
|
|
This behaviour can be disabled by adding `populate_user_metadata: false` as
|
|
a setting in the oidc realm.
|
|
|
|
[[oidc-kibana]]
|
|
=== Configuring {kib}
|
|
|
|
OpenID Connect authentication in {kib} requires a small number of additional settings
|
|
in addition to the standard {kib} security configuration. The
|
|
{kibana-ref}/using-kibana-with-security.html[{kib} security documentation]
|
|
provides details on the available configuration options that you can apply.
|
|
|
|
In particular, since your {es} nodes have been configured to use TLS on the HTTP
|
|
interface, you must configure {kib} to use a `https` URL to connect to {es}, and
|
|
you may need to configure `elasticsearch.ssl.certificateAuthorities` to trust
|
|
the certificates that {es} has been configured to use.
|
|
|
|
OpenID Connect authentication in {kib} is also subject to the
|
|
`xpack.security.sessionTimeout` setting that is described in the {kib} security
|
|
documentation, and you may wish to adjust this timeout to meet your local needs.
|
|
|
|
The three additional settings that are required for OpenID Connect support are shown below:
|
|
|
|
[source, yaml]
|
|
------------------------------------------------------------
|
|
xpack.security.authc.providers: [oidc]
|
|
xpack.security.authc.oidc.realm: "oidc1"
|
|
server.xsrf.whitelist: [/api/security/v1/oidc]
|
|
------------------------------------------------------------
|
|
|
|
The configuration values used in the example above are:
|
|
|
|
`xpack.security.authc.providers`::
|
|
Set this to `[ oidc ]` to instruct {kib} to use OpenID Connect single sign-on as the
|
|
authentication method. This instructs Kibana to attempt to initiate an SSO flow
|
|
everytime a user attempts to access a URL in Kibana, if the user is not already
|
|
authenticated. If you also want to allow users to login with a username and password,
|
|
you must enable the `basic` authentication provider too. For example:
|
|
|
|
[source, yaml]
|
|
------------------------------------------------------------
|
|
xpack.security.authc.providers: [oidc, basic]
|
|
------------------------------------------------------------
|
|
|
|
This will allow users that haven't already authenticated with OpenID Connect to
|
|
navigate directly to the `/login` page in {kib} in order to use the login form.
|
|
|
|
`xpack.security.authc.oidc.realm`::
|
|
The name of the OpenID Connect realm in {es} that should handle authentication
|
|
for this Kibana instance.
|
|
|
|
`server.xsrf.whitelist`::
|
|
{kib} has in-built protection against _Cross Site Request Forgery_ attacks, which
|
|
is designed to prevent the {kib} server from processing requests that
|
|
originated from outside the {kib} application.
|
|
If you use the authorization code flow, {kib} needs to support unsolicited messages that originate from your
|
|
OP or a third party (see <<third-party-login>>). In order to do so, you must explicitly _whitelist_ the
|
|
OpenID Connect authentication endpoint within {kib}, so that the {kib} server will
|
|
not reject these external messages.
|
|
|
|
|
|
=== OpenID Connect without {kib}
|
|
|
|
The OpenID Connect realm is designed to allow users to authenticate to {kib} and as
|
|
such, most of the parts of the guide above make the assumption that {kib} is used.
|
|
This section describes how a custom web application could use the relevant OpenID
|
|
Connect REST APIs in order to authenticate the users to {es}, with OpenID Connect.
|
|
|
|
Single sign-on realms such as OpenID Connect and SAML make use of the Token Service in
|
|
{es} and in principle exchange a SAML or OpenID Connect Authentication response for
|
|
an {es} access token and a refresh token. The access token is used as credentials for subsequent calls to {es}. The
|
|
refresh token enables the user to get new {es} access tokens after the current one
|
|
expires.
|
|
|
|
NOTE: The {es} Token Service can be seen as a minimal oAuth2 authorization server
|
|
and the access token and refresh token mentioned above are tokens that pertain
|
|
_only_ to this authorization server. They are generated and consumed _only_ by {es}
|
|
and are in no way related to the tokens ( access token and ID Token ) that the
|
|
OpenID Connect Provider issues.
|
|
|
|
==== Register the RP with an OpenID Connect Provider
|
|
|
|
The Relying Party ( {es} and the custom web app ) will need to be registered as
|
|
client with the OpenID Connect Provider. Note that when registering the
|
|
`Redirect URI`, it needs to be a URL in the custom web app.
|
|
|
|
==== OpenID Connect Realm
|
|
|
|
An OpenID Connect realm needs to be created and configured accordingly
|
|
in {es}. See <<oidc-guide-authentication>>
|
|
|
|
==== Service Account user for accessing the APIs
|
|
|
|
The realm is designed with the assumption that there needs to be a privileged entity
|
|
acting as an authentication proxy. In this case, the custom web application is the
|
|
authentication proxy handling the authentication of end users ( more correctly,
|
|
"delegating" the authentication to the OpenID Connect Provider ). The OpenID Connect
|
|
APIs require authentication and the necessary authorization level for the authenticated
|
|
user. For this reason, a Service Account user needs to be created and assigned a role
|
|
that gives them the `manage_oidc` cluster privilege. The use of the `manage_token`
|
|
cluster privilege will be necessary after the authentication takes place, so that the
|
|
the user can maintain access or be subsequently logged out.
|
|
|
|
[source,console]
|
|
--------------------------------------------------
|
|
POST /_security/role/facilitator-role
|
|
{
|
|
"cluster" : ["manage_oidc", "manage_token"]
|
|
}
|
|
--------------------------------------------------
|
|
|
|
|
|
[source,console]
|
|
--------------------------------------------------
|
|
POST /_security/user/facilitator
|
|
{
|
|
"password" : "<somePasswordHere>",
|
|
"roles" : [ "facilitator-role"]
|
|
}
|
|
--------------------------------------------------
|
|
|
|
|
|
==== Handling the authentication flow
|
|
|
|
On a high level, the custom web application would need to perform the following steps in order to
|
|
authenticate a user with OpenID Connect:
|
|
|
|
. Make an HTTP POST request to `_security/oidc/prepare`, authenticating as the `facilitator` user, using the name of the
|
|
OpenID Connect realm in the {es} configuration in the request body. See the
|
|
{ref}/security-api-oidc-prepare-authentication.html[OIDC Prepare Authentication API] for more details
|
|
+
|
|
[source,console]
|
|
--------------------------------------------------
|
|
POST /_security/oidc/prepare
|
|
{
|
|
"realm" : "oidc1"
|
|
}
|
|
--------------------------------------------------
|
|
+
|
|
. Handle the response to `/_security/oidc/prepare`. The response from {es} will contain 3 parameters:
|
|
`redirect`, `state`, `nonce`. The custom web application would need to store the values for `state`
|
|
and `nonce` in the user's session (client side in a cookie or server side if session information is
|
|
persisted this way) and redirect the user's browser to the URL that will be contained in the
|
|
`redirect` value.
|
|
. Handle a subsequent response from the OP. After the user is successfully authenticated with the
|
|
OpenID Connect Provider, they will be redirected back to the callback/redirect URI. Upon receiving
|
|
this HTTP GET request, the custom web app will need to make an HTTP POST request to
|
|
`_security/oidc/authenticate`, again - authenticating as the `facilitator` user - passing the URL
|
|
where the user's browser was redirected to, as a parameter, along with the
|
|
values for `nonce` and `state` it had saved in the user's session previously. If more than one
|
|
OpenID Connect realms are configured, the custom web app can specify the name of the realm to be
|
|
used for handling this, but this parameter is optional.
|
|
See {ref}/security-api-oidc-authenticate.html[OIDC Authenticate API] for more details
|
|
+
|
|
[source,console]
|
|
-----------------------------------------------------------------------
|
|
POST /_security/oidc/authenticate
|
|
{
|
|
"redirect_uri" : "https://oidc-kibana.elastic.co:5603/api/security/v1/oidc?code=jtI3Ntt8v3_XvcLzCFGq&state=4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I",
|
|
"state" : "4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I",
|
|
"nonce" : "WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM",
|
|
"realm" : "oidc1"
|
|
}
|
|
-----------------------------------------------------------------------
|
|
// TEST[catch:unauthorized]
|
|
+
|
|
Elasticsearch will validate this and if all is correct will respond with an access token that can be used
|
|
as a `Bearer` token for subsequent requests and a refresh token that can be later used to refresh the given
|
|
access token as described in {ref}/security-api-get-token.html[get token API].
|
|
. At some point, if necessary, the custom web application can log the user out by using the
|
|
{ref}/security-api-oidc-logout.html[OIDC Logout API] passing the access token and refresh token as parameters. For example:
|
|
+
|
|
[source,console]
|
|
--------------------------------------------------
|
|
POST /_security/oidc/logout
|
|
{
|
|
"token" : "dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvbmx5IHRlc3QgZGF0YS4gZG8gbm90IHRyeSB0byByZWFkIHRva2VuIQ==",
|
|
"refresh_token": "vLBPvmAB6KvwvJZr27cS"
|
|
}
|
|
--------------------------------------------------
|
|
// TEST[catch:unauthorized]
|
|
+
|
|
If the realm is configured accordingly, this may result in a response with a `redirect` parameter indicating where
|
|
the user needs to be redirected in the OP in order to complete the logout process.
|