Browse Source

Document SAML APIs (#45105)

* Document SAML APIs

This change adds documentation for the SAML APIs in Elasticsearch
and adds simple instructions on how these APIs can be used to
authenticate a user with SAML by a custom web application other
than Kibana.

Resolves: #40352

* typo

* fix links

* fix more links

* [DOCS] Fixes broken link

* Add metadata file with shorter names for docs, fix typos and mute tests

* [DOCS] Reformats the SAML APIs to match API template

* Apply suggestions from code review

Co-Authored-By: Lisa Cawley <lcawley@elastic.co>

* Address feedback and add small section on IdP-initiated SSO handling

* address feedback

* moar feedback

* Clarifications and addressing feedback

* properly resolve conflicts

* address feedback

* fix doc links

* minor fixes

* Fix reference
Ioannis Kakavas 6 years ago
parent
commit
f68b036a7b

+ 8 - 0
x-pack/docs/build.gradle

@@ -29,6 +29,7 @@ project.copyRestSpec.from(xpackResources) {
 
 testClusters.integTest {
     extraConfigFile 'op-jwks.json', xpackProject('test:idp-fixture').file("oidc/op-jwks.json")
+    extraConfigFile 'idp-docs-metadata.xml', xpackProject('test:idp-fixture').file("idp/shibboleth-idp/metadata/idp-docs-metadata.xml")
     extraConfigFile 'testClient.crt', xpackProject('plugin:security').file("src/test/resources/org/elasticsearch/xpack/security/action/pki_delegation/testClient.crt")
     setting 'xpack.security.enabled', 'true'
     setting 'xpack.security.authc.api_key.enabled', 'true'
@@ -52,6 +53,13 @@ testClusters.integTest {
     setting 'xpack.security.authc.realms.pki.pki1.order', '3'
     setting 'xpack.security.authc.realms.pki.pki1.certificate_authorities', '[ "testClient.crt" ]'
     setting 'xpack.security.authc.realms.pki.pki1.delegation.enabled', 'true'
+    setting 'xpack.security.authc.realms.saml.saml1.order', '4'
+    setting 'xpack.security.authc.realms.saml.saml1.idp.entity_id', 'https://my-idp.org'
+    setting 'xpack.security.authc.realms.saml.saml1.idp.metadata.path', 'idp-docs-metadata.xml'
+    setting 'xpack.security.authc.realms.saml.saml1.sp.entity_id', 'https://kibana.org'
+    setting 'xpack.security.authc.realms.saml.saml1.sp.acs', 'https://kibana.org/api/security/v1/saml'
+    setting 'xpack.security.authc.realms.saml.saml1.attributes.principal', 'uid'
+    setting 'xpack.security.authc.realms.saml.saml1.attributes.name', 'urn:oid:2.5.4.3'
     user username: 'test_admin'
 }
 

+ 17 - 1
x-pack/docs/en/rest-api/security.asciidoc

@@ -83,12 +83,24 @@ native realm:
 === OpenID Connect
 
 You can use the following APIs to authenticate users against an OpenID Connect
-authentication realm
+authentication realm when using a custom web application other than Kibana
 
 * <<security-api-oidc-prepare-authentication, Prepare an authentication request>>
 * <<security-api-oidc-authenticate, Submit an authentication response>>
 * <<security-api-oidc-logout, Logout an authenticated user>>
 
+[float]
+[[security-saml-apis]]
+=== SAML
+
+You can use the following APIs to authenticate users against a SAML authentication
+realm when using a custom web application other than Kibana
+
+* <<security-api-saml-prepare-authentication, Prepare an authentication request>>
+* <<security-api-saml-authenticate, Submit an authentication response>>
+* <<security-api-saml-logout, Logout an authenticated user>>
+* <<security-api-saml-invalidate, Submit a logout request from the IdP>>
+
 
 include::security/authenticate.asciidoc[]
 include::security/change-password.asciidoc[]
@@ -119,4 +131,8 @@ include::security/invalidate-tokens.asciidoc[]
 include::security/oidc-prepare-authentication-api.asciidoc[]
 include::security/oidc-authenticate-api.asciidoc[]
 include::security/oidc-logout-api.asciidoc[]
+include::security/saml-prepare-authentication-api.asciidoc[]
+include::security/saml-authenticate-api.asciidoc[]
+include::security/saml-logout-api.asciidoc[]
+include::security/saml-invalidate-api.asciidoc[]
 include::security/ssl.asciidoc[]

+ 93 - 0
x-pack/docs/en/rest-api/security/saml-authenticate-api.asciidoc

@@ -0,0 +1,93 @@
+[role="xpack"]
+[[security-api-saml-authenticate]]
+=== SAML authenticate API
+
+Submits a SAML `Response` message to {es} for consumption.
+
+NOTE: This API is intended for use by custom web applications other than {kib}.
+If you are using {kib}, see the <<saml-guide>>.
+
+[[security-api-saml-authenticate-request]]
+==== {api-request-title}
+
+`POST /_security/saml/authenticate`
+
+[[security-api-saml-authenticate-desc]]
+==== {api-description-title}
+
+The SAML message that is submitted can be:
+
+* a response to a SAML authentication request that was previously created using the
+<<security-api-saml-prepare-authentication, SAML prepare authentication API>>.
+* an unsolicited SAML message in the case of an IdP-initiated single sign-on (SSO) flow.
+
+In either cases, the SAML message needs to be a base64 encoded XML document with a root
+element of `<Response>`
+
+After successful validation, {es} responds with an
+{es} internal access token and refresh token that can be subsequently used for authentication.
+This API endpoint essentially exchanges SAML responses that
+indicate successful authentication in the IdP for {es} access and refresh tokens,
+which can be used for authentication against {es}.
+
+{es} exposes all the necessary SAML related functionality via the SAML APIs.
+These APIs are used internally by {kib} in order to provide SAML based
+authentication, but can also be used by other, custom web applications or other
+clients. See also
+<<security-api-saml-prepare-authentication,SAML prepare authentication API>>,
+<<security-api-saml-invalidate,SAML invalidate API>> and
+<<security-api-saml-logout,SAML logout API>>.
+
+
+[[security-api-saml-authenticate-request-body]]
+==== {api-request-body-title}
+
+`content`::
+  (Required, string) The SAML response as it was sent by the user's browser, usually a
+  Base64 encoded XML document.
+
+`ids`::
+  (Required, array) A json array with all the valid SAML Request Ids that the caller of
+  the API has for the current user.
+
+[[security-api-saml-authenticate-response-body]]
+==== {api-response-body-title}  
+
+`access_token`::
+  (string) The access token that was generated by {es}.
+`username`::
+  (string) The authenticated user's name.
+`expires_in`::
+  (integer) The amount of time (in seconds) left until the token expires.
+`refresh_token`::
+  (string) The refresh token that was generated by {es}.
+
+[[security-api-saml-authenticate-example]]
+==== {api-examples-title}
+
+The following example exchanges a SAML Response indicating a successful
+authentication at the SAML IdP for an {es} access token and refresh token to be
+used in subsequent requests:
+
+[source,console]
+--------------------------------------------------
+POST /_security/saml/authenticate
+{
+  "content" : "PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMD.....",
+  "ids" : ["4fee3b046395c4e751011e97f8900b5273d56685"]
+}
+--------------------------------------------------
+// TEST[skip:handled in IT]
+
+The API returns the following response:
+
+[source,js]
+--------------------------------------------------
+{
+  "access_token" : "46ToAxZVaXVVZTVKOVF5YU04ZFJVUDVSZlV3",
+  "username" : "Bearer",
+  "expires_in" : 1200,
+  "refresh_token": "mJdXLtmvTUSpoLwMvdBt_w"
+}
+--------------------------------------------------
+// NOTCONSOLE

+ 91 - 0
x-pack/docs/en/rest-api/security/saml-invalidate-api.asciidoc

@@ -0,0 +1,91 @@
+[role="xpack"]
+[[security-api-saml-invalidate]]
+=== SAML invalidate API
+
+Submits a SAML LogoutRequest message to {es} for consumption.
+
+NOTE: This API is intended for use by custom web applications other than {kib}.
+If you are using {kib}, see the <<saml-guide>>.
+
+[[security-api-saml-invalidate-request]]
+==== {api-request-title}
+
+`POST /_security/saml/invalidate`
+
+[[security-api-saml-invalidate-desc]]
+==== {api-description-title}
+
+The logout request comes from the SAML IdP during an IdP initiated Single Logout.
+The custom web application can use this API to have {es} process the `LogoutRequest`.
+After successful validation of the request, {es} invalidates the access token
+and refresh token that corresponds to that specific SAML principal and provides
+a URL that contains a SAML LogoutResponse message, so that the user can be
+redirected back to their IdP.
+
+{es} exposes all the necessary SAML related functionality via the SAML APIs.
+These APIs are used internally by {kib} in order to provide SAML based
+authentication, but can also be used by other custom web applications or other
+clients. See also <<security-api-saml-authenticate,SAML authenticate API>>,
+<<security-api-saml-prepare-authentication,SAML prepare authentication API>>,
+and <<security-api-saml-logout,SAML logout API>>.
+
+[[security-api-saml-invalidate-request-body]]
+==== {api-request-body-title}
+
+`acs`::
+  (Optional, string) The Assertion Consumer Service URL that matches the one of the SAML
+  realm in {es} that should be used. You must specify either this parameter or the `realm` parameter.
+
+`queryString`:: 
+  (Required, string) The query part of the URL that the user was redirected to by the SAML
+  IdP to initiate the Single Logout. This query should include a single
+  parameter named `SAMLRequest` that contains a SAML logout request that is
+  deflated and Base64 encoded. If the SAML IdP has signed the logout request, 
+  the URL should include two extra parameters named `SigAlg` and `Signature`
+  that contain the algorithm used for the signature and the signature value itself.
+In order for {es} to be able to verify the IdP's signature, the value of the queryString field must be an exact match to the string provided by the browser.
+The client application must not attempt to parse or process the string in any way.
+
+`realm`::
+  (Optional, string) The name of the SAML realm in {es} the configuration. You must specify
+  either this parameter or the `acs` parameter.
+
+[[security-api-saml-invalidate-response-body]]
+==== {api-response-body-title}  
+
+`invalidated`::
+  (integer) The number of tokens that were invalidated as part of this logout.
+
+`realm`:: 
+  (string) The realm name of the SAML realm in {es} that authenticated the user.
+
+`redirect`::
+  (string) A SAML logout response as a parameter so that the user can be
+  redirected back to the SAML IdP.
+
+
+[[security-api-saml-invalidate-example]]
+==== {api-examples-title}
+
+The following example invalidates all the tokens for realm `saml1` pertaining to
+the user that is identified in the SAML Logout Request:
+
+[source,console]
+--------------------------------------------------
+POST /_security/saml/invalidate
+{
+  "queryString" : "SAMLRequest=nZFda4MwFIb%2FiuS%2BmviRpqFaClKQdbvo2g12M2KMraCJ9cRR9utnW4Wyi13sMie873MeznJ1aWrnS3VQGR0j4mLkKC1NUeljjA77zYyhVbIE0dR%2By7fmaHq7U%2BdegXWGpAZ%2B%2F4pR32luBFTAtWgUcCv56%2Fp5y30X87Yz1khTIycdgpUW9kY7WdsC9zxoXTvMvWuVV98YyMnSGH2SYE5pwALBIr9QKiwDGpW0oGVUznGeMyJZKFkQ4jBf5HnhUymjIhzCAL3KNFihbYx8TBYzzGaY7EnIyZwHzCWMfiDnbRIftkSjJr%2BFu0e9v%2B0EgOquRiiZjKpiVFp6j50T4WXoyNJ%2FEWC9fdqc1t%2F1%2B2F3aUpjzhPiXpqMz1%2FHSn4A&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=MsAYz2NFdovMG2mXf6TSpu5vlQQyEJAg%2B4KCwBqJTmrb3yGXKUtIgvjqf88eCAK32v3eN8vupjPC8LglYmke1ZnjK0%2FKxzkvSjTVA7mMQe2AQdKbkyC038zzRq%2FYHcjFDE%2Bz0qISwSHZY2NyLePmwU7SexEXnIz37jKC6NMEhus%3D",
+  "realm" : "saml1"
+}
+--------------------------------------------------
+// TEST[skip:handled in IT]
+
+[source,js]
+--------------------------------------------------
+{
+  "redirect" : "https://my-idp.org/logout/SAMLResponse=....",
+  "invalidated" : 2,
+  "realm" : "saml1"
+}
+--------------------------------------------------
+// NOTCONSOLE

+ 79 - 0
x-pack/docs/en/rest-api/security/saml-logout-api.asciidoc

@@ -0,0 +1,79 @@
+[role="xpack"]
+[[security-api-saml-logout]]
+=== SAML logout API
+
+Submits a request to invalidate an access token and refresh token.
+
+NOTE: This API is intended for use by custom web applications other than {kib}.
+If you are using {kib}, see the <<saml-guide>>.
+
+[[security-api-saml-logout-request]]
+==== {api-request-title}
+
+`POST /_security/saml/logout`
+
+[[security-api-saml-logout-desc]]
+==== {api-description-title}
+
+This API invalidates the tokens that were generated for a user by the
+<<security-api-saml-authenticate,SAML authenticate API>>.
+
+If the SAML realm in {es} is configured accordingly and the SAML IdP supports
+this, the {es} response contains a URL to redirect the user to the IdP
+that contains a SAML logout request (starting an SP-initiated SAML Single Logout).
+
+{es} exposes all the necessary SAML related functionality via the SAML APIs.
+These APIs are used internally by {kib} in order to provide SAML based
+authentication, but can also be used by other custom web applications or other
+clients. See also <<security-api-saml-authenticate,SAML authenticate API>>,
+<<security-api-saml-prepare-authentication,SAML prepare authentication API>>,
+and <<security-api-saml-invalidate,SAML invalidate API>>.
+
+[[security-api-saml-logout-request-body]]
+==== {api-request-body-title}
+
+`token`::
+  (Required, string) The access token that was returned as a response to calling the
+  <<security-api-saml-authenticate,SAML authenticate API>>. Alternatively, the most
+  recent token that was received after refreshing the original one by using a
+  `refresh_token`.
+
+`refresh_token`::
+  (Optional, string) The refresh token that was returned as a response to calling the
+  <<security-api-saml-authenticate,SAML authenticate API>>. Alternatively, the
+  most recent refresh token that was received after refreshing the original access token.
+
+[[security-api-saml-logout-response-body]]
+==== {api-response-body-title}  
+
+`redirect`::
+  (string) A URL that contains a SAML logout request as a parameter. The user
+  can use this URL to be redirected back to the SAML IdP and to initiate Single
+  Logout.
+
+[[security-api-saml-logout-example]]
+==== {api-examples-title}
+
+The following example invalidates the pair of tokens that were generated by
+calling the <<security-api-saml-authenticate,SAML authenticate API>>
+with a successful SAML response:
+
+[source,console]
+--------------------------------------------------
+POST /_security/saml/logout
+{
+  "token" : "46ToAxZVaXVVZTVKOVF5YU04ZFJVUDVSZlV3",
+  "refresh_token" : "mJdXLtmvTUSpoLwMvdBt_w"
+}
+--------------------------------------------------
+// TEST[skip:can't test this without a valid SAML Response]
+
+The API returns the following response:
+
+[source,js]
+--------------------------------------------------
+{
+  "redirect" : "https://my-idp.org/logout/SAMLRequest=...."
+}
+--------------------------------------------------
+// NOTCONSOLE

+ 98 - 0
x-pack/docs/en/rest-api/security/saml-prepare-authentication-api.asciidoc

@@ -0,0 +1,98 @@
+[role="xpack"]
+[[security-api-saml-prepare-authentication]]
+=== SAML prepare authentication API
+
+Creates a SAML authentication request (`<AuthnRequest>`) as a URL string, based on the configuration of the respective SAML realm in {es}.
+
+NOTE: This API is intended for use by custom web applications other than {kib}.
+If you are using {kib}, see the <<saml-guide>>.
+
+[[security-api-saml-prepare-authentication-request]]
+==== {api-request-title}
+
+`POST /_security/saml/prepare`
+
+[[security-api-saml-prepare-authentication-desc]]
+==== {api-description-title}
+
+This API returns a URL pointing to the SAML Identity
+Provider. You can use the URL to redirect the browser of the user in order to
+continue the authentication process. The URL includes a single parameter named `SAMLRequest`,
+which contains a SAML Authentication request that is deflated and
+Base64 encoded. If the configuration dictates that SAML authentication requests
+should be signed, the URL has two extra parameters named `SigAlg` and
+`Signature`. These parameters contain the algorithm used for the signature and
+the signature value itself.
+It also returns a random string that uniquely identifies this SAML Authentication request. The
+caller of this API needs to store this identifier as it needs to used in a following step of
+the authentication process (see <<security-api-saml-authenticate,SAML authenticate API>>).
+
+{es} exposes all the necessary SAML related functionality via the SAML APIs.
+These APIs are used internally by {kib} in order to provide SAML based
+authentication, but can also be used by other custom web applications or other
+clients. See also <<security-api-saml-authenticate,SAML authenticate API>>,
+<<security-api-saml-invalidate,SAML invalidate API>>, and
+<<security-api-saml-logout,SAML logout API>>.
+
+[[security-api-saml-prepare-authentication-request-body]]
+==== {api-request-body-title}
+
+`acs`::
+  (Optional, string) The Assertion Consumer Service URL that matches the one of the SAML
+  realms in {es}. The realm is used to generate the authentication request.
+  You must specify either this parameter or the `realm` parameter.
+
+`realm`::
+  (Optional, string) The name of the SAML realm in {es} for which the configuration is
+  used to generate the authentication request. You must specify either this parameter or the `acs`
+  parameter.
+
+[[security-api-saml-prepare-authentication-response-body]]
+==== {api-response-body-title}  
+
+`id`::
+  (string) A unique identifier for the SAML Request to be stored by the caller
+  of the API.
+
+`realm`::
+  (string) The name of the {es} realm that was used to construct the
+  authentication request.
+
+`redirect`::
+  (string) The URL to redirect the user to.
+
+[[security-api-saml-prepare-authentication-example]]
+==== {api-examples-title}
+
+The following example generates a SAML authentication request for the SAML realm with name `saml1`
+
+[source,console]
+--------------------------------------------------
+POST /_security/saml/prepare
+{
+  "realm" : "saml1"
+}
+--------------------------------------------------
+
+The following example generates a SAML authentication request for the SAML realm with an Assertion
+Consuming Service URL matching `https://kibana.org/api/security/v1/saml
+
+[source,console]
+--------------------------------------------------
+POST /_security/saml/prepare
+{
+  "acs" : "https://kibana.org/api/security/v1/saml"
+}
+--------------------------------------------------
+
+This API returns the following response:
+
+[source,js]
+-------------------------------------------------
+{
+  "redirect": "https://my-idp.org/login?SAMLRequest=fVJdc6IwFP0rmbwDgUKLGbFDtc462%2B06FX3Yl50rBJsKCZsbrPbXL6J22hdfk%2FNx7zl3eL%2BvK7ITBqVWCfVdRolQuS6k2iR0mU2dmN6Phgh1FTQ8be2rehH%2FWoGWdESF%2FPST0NYorgElcgW1QG5zvkh%2FPfHAZbwx2upcV5SkiMLYzmqsFba1MAthdjIXy5enhL5a23DPOyo6W7kGBa7cwhZ2gO7G8OiW%2BR400kORt0bag7fzezAlk24eqcD2OxxlsNN5O3MdsW9c6CZnbq7rntF4d3s0D7BaHTZhIWN52P%2BcjiuGRbDU6cdj%2BEjJbJLQv4N4ADdhxBiEZbQuWclY4Q8iABbCXczCdSiKMAC%2FgyO2YqbQgrIJDZg%2FcFjsMD%2Fzb3gUcBa5sR%2F9oWR%2BzuJBqlPG14Jbn0DIf2TZ3Jn%2FXmSUrC5ddQB6bob37uZrJdeF4dIDHV3iuhb70Ptq83kOz53ubDLXlcwPJK0q%2FT42AqxIaAkVCkqm2tRgr49yfJGFU%2FZQ3hy3QyuUpd7obPv97kb%2FAQ%3D%3D"}",
+  "realm": "saml1",
+  "id": "_989a34500a4f5bf0f00d195aa04a7804b4ed42a1"
+}
+-------------------------------------------------
+// NOTCONSOLE

+ 2 - 2
x-pack/docs/en/security/authentication/oidc-guide.asciidoc

@@ -659,8 +659,8 @@ POST /_security/oidc/authenticate
 // 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].
+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:
 +

+ 164 - 0
x-pack/docs/en/security/authentication/saml-guide.asciidoc

@@ -855,3 +855,167 @@ A conscious effort has been made to mask this complexity with sane defaults and
 documentation above but in case you encounter issues while configuring a SAML realm, you can
 look through our <<trb-security-saml,SAML troubleshooting documentation>> that has
 suggestions and resolutions for common issues.
+
+[[saml-no-kibana]]
+=== SAML without {kib}
+
+The SAML realm in {es} 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 SAML
+REST APIs in order to authenticate the users to {es} with SAML.
+
+NOTE: This section assumes that the reader is familiar with the SAML 2.0 standard
+and more specifically with the SAML 2.0 Web Browser Single Sign On profile.
+
+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.
+
+[[saml-no-kibana-realm]]]
+==== SAML realm
+
+You must create a SAML realm and configure it accordingly
+in {es}. See <<saml-guide-authentication>>
+
+[[saml-no-kibana-user]]
+==== 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 SAML Identity Provider ). The SAML related
+APIs require authentication and the necessary authorization level for the authenticated
+user. For this reason, you must create a Service Account user and assign it a role
+that gives it the `manage_saml` cluster privilege. The use of the `manage_token`
+cluster privilege will be necessary after the authentication takes place, so that the
+the service account user can maintain access in order refresh access tokens on
+behalf of the authenticated users or to subsequently log them out.
+
+[source,console]
+--------------------------------------------------
+POST /_security/role/saml-service-role
+{
+  "cluster" : ["manage_saml", "manage_token"]
+}
+--------------------------------------------------
+
+[source,console]
+--------------------------------------------------
+POST /_security/user/saml-service-user
+{
+  "password" : "<somePasswordHere>",
+  "roles"    : ["saml-service-role"]
+}
+--------------------------------------------------
+
+[[saml-no-kibana-sp-init-sso]]
+==== Handling the SP-initiated authentication flow
+
+On a high level, the custom web application would need to perform the
+following steps in order to authenticate a user with SAML against {es}:
+
+. Make an HTTP POST request to `_security/saml/prepare`, authenticating as
+the `saml-service-user` user. Use either the name of the SAML realm in the {es} configuration or the value for
+the Assertion Consumer Service URL in the request body.
+See the <<security-api-saml-prepare-authentication,SAML prepare authentication API>> for more details.
++
+[source,console]
+--------------------------------------------------
+POST /_security/saml/prepare
+{
+  "realm" : "saml1"
+}
+--------------------------------------------------
+
+. Handle the response from `/_security/saml/prepare`. The response from {es} will contain 3 parameters:
+  `redirect`, `realm' and `id`. The custom web application would need to store the value for `id`
+ in the user's session (client side in a cookie or server side if session information is
+persisted this way). It must also redirect the user's browser to the URL that  was returned in the 
+  `redirect` parameter. The `id` value should not be disregarded as it is used as a nonce in SAML in
+order to mitigate against replay attacks.
+. Handle a subsequent response from the SAML IdP. After the user is successfully authenticated with the
+Identity Provider they will be redirected back to the Assertion Consumer Service URL. This `sp.acs` needs to be
+defined as a URL which the custom web application handles. When it receives this HTTP POST request, the
+custom web application must parse it and make an HTTP POST request itself to the
+`_security/saml/authenticate` API. It must authenticate as the `saml-service-user` user and pass
+the Base64 encoded SAML Response that was sent as the body of the request. It must also pass the value for `id` that it had saved in the user's session previously.
++
+See <<security-api-saml-authenticate,SAML authenticate API>> for more details.
++
+[source,console]
+-----------------------------------------------------------------------
+POST /_security/saml/authenticate
+{
+  "content" : "PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMD.....",
+  "ids" : ["4fee3b046395c4e751011e97f8900b5273d56685"]
+}
+-----------------------------------------------------------------------
+// TEST[skip:handled in IT]
++
+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. It also supplies a refresh token that can be later used to refresh the given
+access token as described in <<security-api-get-token,get token API>>.
+. The response to calling `/_security/saml/authenticate` will contain only the username of the authenticated
+user. If you need to get the values for the SAML Attributes that were contained in the SAML
+Response for that user, you can call the Authenticate API `/_security/_authenticate/` using the access token as a `Bearer` token
+and the SAML attribute values will be contained in the response as part of the <<saml-user-metadata>>.
+
+[[saml-no-kibana-idp-init-sso]]
+==== Handling the IdP-initiated authentication flow
+
+{es} can also handle the IdP-initiated Single Sign On flow of the SAML 2 Web Browser SSO profile. In this
+case the authentication starts with an unsolicited authentication response from the SAML Identity
+Provider. The difference with the <<saml-no-kibana-sp-init-sso, SP initiated SSO>> is that the web application needs to handle
+requests to the `sp.acs` that will not come as responses to previous redirections. As such, it will not have a session
+for the user already, and it will not have any stored values for the `id` parameter. The request to the
+`_security/saml/authenticate` API will look like the one below in this case:
+
+
+[source,console]
+-----------------------------------------------------------------------
+POST /_security/saml/authenticate
+{
+  "content" : "PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMD.....",
+  "ids" : []
+}
+-----------------------------------------------------------------------
+// TEST[skip:handled in IT]
+
+[[saml-no-kibana-slo]]
+==== Handling the logout flow
+. At some point, if necessary, the custom web application can log the user out by using the
+  <<security-api-saml-logout,SAML logout API>> and passing the access token and refresh token as parameters. For example:
++
+[source,console]
+--------------------------------------------------
+POST /_security/saml/logout
+{
+  "token" : "46ToAxZVaXVVZTVKOVF5YU04ZFJVUDVSZlV3",
+  "refresh_token": "mJdXLtmvTUSpoLwMvdBt_w"
+}
+--------------------------------------------------
+// TEST[skip:handled in IT]
++
+If the SAML realm is configured accordingly and the IdP supports it (see <<saml-logout>>), this request will trigger a SAML
+SP-initiated Single Logout. In this case, the response will include a `redirect`
+parameter indicating where the user needs to be redirected at the IdP in order to complete the logout.
+. Alternatively, the IdP might initiate the Single Logout flow at some point. In order to handle this, 
+the Logout URL (`sp.logout`) needs to be handled by the custom web app. The query part of the URL that the
+user will be redirected to will contain a SAML Logout request and this query part needs to be relayed to {es}
+using the <<security-api-saml-invalidate,SAML invalidate API>> 
++
+[source,console]
+--------------------------------------------------
+POST /_security/saml/invalidate
+{
+  "query" : "SAMLRequest=nZFda4MwFIb%2FiuS%2BmviRpqFaClKQdbvo2g12M2KMraCJ9cRR9utnW4Wyi13sMie873MeznJ1aWrnS3VQGR0j4mLkKC1NUeljjA77zYyhVbIE0dR%2By7fmaHq7U%2BdegXWGpAZ%2B%2F4pR32luBFTAtWgUcCv56%2Fp5y30X87Yz1khTIycdgpUW9kY7WdsC9zxoXTvMvWuVV98YyMnSGH2SYE5pwALBIr9QKiwDGpW0oGVUznGeMyJZKFkQ4jBf5HnhUymjIhzCAL3KNFihbYx8TBYzzGaY7EnIyZwHzCWMfiDnbRIftkSjJr%2BFu0e9v%2B0EgOquRiiZjKpiVFp6j50T4WXoyNJ%2FEWC9fdqc1t%2F1%2B2F3aUpjzhPiXpqMz1%2FHSn4A&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=MsAYz2NFdovMG2mXf6TSpu5vlQQyEJAg%2B4KCwBqJTmrb3yGXKUtIgvjqf88eCAK32v3eN8vupjPC8LglYmke1ZnjK0%2FKxzkvSjTVA7mMQe2AQdKbkyC038zzRq%2FYHcjFDE%2Bz0qISwSHZY2NyLePmwU7SexEXnIz37jKC6NMEhus%3D",
+  "realm" : "saml1"
+}
+--------------------------------------------------
+// TEST[skip:handled in IT]
++
+The custom web application will then need to also handle the response, which will include a `redirect`
+parameter with a URL in the IdP that contains the SAML Logout response. The application should redirect the user
+there to complete the logout. 

+ 105 - 0
x-pack/test/idp-fixture/idp/shibboleth-idp/metadata/idp-docs-metadata.xml

@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<EntityDescriptor  xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:shibmd="urn:mace:shibboleth:metadata:1.0" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui" xmlns:req-attr="urn:oasis:names:tc:SAML:protocol:ext:req-attr" entityID="https://my-idp.org">
+    <IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+        <KeyDescriptor use="signing">
+            <ds:KeyInfo>
+                <ds:X509Data>
+                    <ds:X509Certificate>
+                        MIIEUjCCArqgAwIBAgIVALjpmEEY4k5+2/JXwk5y+MoDnWiAMA0GCSqGSIb3DQEB
+                        CwUAMCgxJjAkBgNVBAMMHXRlc3Quc2hpYmJvbGV0aC5lbGFzdGljLmxvY2FsMB4X
+                        DTE5MDMwODEzMTg1OVoXDTM5MDMwODEzMTg1OVowKDEmMCQGA1UEAwwddGVzdC5z
+                        aGliYm9sZXRoLmVsYXN0aWMubG9jYWwwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAw
+                        ggGKAoIBgQC98CVCuq4MBwBGia77i7tdUMFql+KbY5mY/eENspY59aPZbI6/oMSU
+                        v4Uu3iJux8gGlBmkzxoefhuIA93lE+RS3k1iezxtS0fQW8drYCtJRT9j8xuEdzo9
+                        hHV3wa4lhnC8Mfn6K79jzj0Y6PkDCSS3wn80YYAQpI0sV6baxGuRByL7BMjHITFw
+                        EbFYsph6zQ/3SZu1OWocVdgZkF+n3zraUDuj87M+Tn6RRhWF0Jq/vFAUNCTWr7Iw
+                        GTUib9LWx3v5IqXttu9NBMSd5Q5mIoPWW+/RA3mpcsN51rVRa2od6HABpiEv7I7B
+                        yEtBVNPkYfOPF2TIxefeyIl3UCD5sF/2nDAZfe/ENnJFQwqnPAXwXrlPlLCoWsOl
+                        OOHfyE7tbORkVXNuWYq9TcTNLEIuB081Utxsoa+iiWGyn0/uYDg2NGxJ2V2/PISf
+                        LhUilCJSmNbMUFirVSUJD8mntn8VRidn1/Wx7RCphPGmMmJtAN080/+zCOJVE4/G
+                        6JnRMFpNZO0CAwEAAaNzMHEwHQYDVR0OBBYEFH9wTxThSEj7nswt0sIjbpw86itt
+                        MFAGA1UdEQRJMEeCHXRlc3Quc2hpYmJvbGV0aC5lbGFzdGljLmxvY2FshiZodHRw
+                        czovL3Rlc3Quc2hpYmJvbGV0aC5lbGFzdGljLmxvY2FsLzANBgkqhkiG9w0BAQsF
+                        AAOCAYEApBpPTKvKUwcZ8Tfm3TZPINmSXI05OWU1Xu8gdFB0EoUDFE9/uHTJgfmS
+                        5ZjUT8YGhHH883XKNq9JhmyCb5V5ZSjONzMGplcsTAkk0guU0DqKvabyVsQuyne6
+                        nCkbAr/srtJFutiFJDGmfAmhTSFTVmpI4stpyC+y5Y0PhcUQa6Ytz8wGTMJvftv5
+                        2S5zhX9IDaWo4C97WWnSXaFepi5n1i4wlCj5HgDkEhoeEt5byJMxzDdN9whEI5Ju
+                        VPMUcRcJNajnSKA1SVAznUpJbHSu0WAfM/MQ9ucX3o3A5J/bA9xlknsEWtugtvRK
+                        KCwuibrOddrv/cQQbpPjDhWk/VF7tOA1kuSHHdYICB+WjWU463bv0rLm6QXqkDU4
+                        f3XuG2zJTmVQEzBdmv9ATlqQ+sADV216Vyy5I/delW0WnmePGTuxBj+Xm7VrbYNi
+                        WOveqK14343Bpbo8H/V2UvTPGF+oICnmw0fgG7SChtcDY9won6mRVCcy+01TeOua
+                        TSYuiKRN
+                    </ds:X509Certificate>
+                </ds:X509Data>
+            </ds:KeyInfo>
+        </KeyDescriptor>
+        <KeyDescriptor use="signing">
+            <ds:KeyInfo>
+                <ds:X509Data>
+                    <ds:X509Certificate>
+                        MIIEUjCCArqgAwIBAgIVAMo/bS4nTf4TlWhmWu7auvJhceTMMA0GCSqGSIb3DQEB
+                        CwUAMCgxJjAkBgNVBAMMHXRlc3Quc2hpYmJvbGV0aC5lbGFzdGljLmxvY2FsMB4X
+                        DTE5MDMwODEzMTg1OVoXDTM5MDMwODEzMTg1OVowKDEmMCQGA1UEAwwddGVzdC5z
+                        aGliYm9sZXRoLmVsYXN0aWMubG9jYWwwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAw
+                        ggGKAoIBgQCGXWD/YD5VD52S6vmy1iRzYI7ZxAsyiDSOP3qQgRtcHssgNluTae6r
+                        GIoj5m3tfQayHmh7ctI3zLhwReD9GlLZuV2JxaIfn/4e1N2dsLFvgYMmao9g41DE
+                        /RG2Zjl/K9Ux3v0xUx5uoK0p68GR3ykYjf/Ea0AIJCx+SfRt6uOQ0nlAC19/gffJ
+                        G1pzcbWxZMxx5jJ8bULtxbAgC7tW21V9kq6fBKwTpJS7XVC4xwou8Vi5NnoPwjbv
+                        f9Agg1TuLI+Loa0+gK3exh0jGlHfvBZMobX8fZI7yDkt60hFe5g97R2yJuVekHR3
+                        VUyAG1xYWcS2l6tJ7XVQKRrwlwUumG0bsnBfa918p6V7pOsS5quKTCQpWkxpXO37
+                        BSbd3TrlpSde0ncFHg3bAxIPtlxbJe87CA4y9JuyrjqCqw8WC5clNCvlGBx5aKgu
+                        986/TWK8neeJZTQRpo+Nwf+Q8tuNb21tYA7B04h2MMumdRcVJ5IXDuVuVZJecNZp
+                        LZODW3bHiGECAwEAAaNzMHEwHQYDVR0OBBYEFGtVRTYHCuBUetx2T2KF8MkvAcwQ
+                        MFAGA1UdEQRJMEeCHXRlc3Quc2hpYmJvbGV0aC5lbGFzdGljLmxvY2FshiZodHRw
+                        czovL3Rlc3Quc2hpYmJvbGV0aC5lbGFzdGljLmxvY2FsLzANBgkqhkiG9w0BAQsF
+                        AAOCAYEAe5fL8bstZsj6p1lZ3fIMjeRcz60BmDyIobQFTQu9PkRa3hcLZdCRtuNL
+                        BfQbNr4Kymo8GP9c/RkmjIxl32cyCrt7kLWLurUptfYO8IgXpvnQ8EfdSO9PBDag
+                        x5WVg8SHVJ+IeL2k+D/EnyQUisQPau0JmJCNQsAuzGrg8FmHa7IBDvWtAmO4BRRd
+                        pZgyC/mfEwF8mbGoRJt7oHs30a+5RVHUhRDLhQD0+L3efgEvq+9lsDKIQHzG2ITg
+                        Z5qqLkYP6nlNlMHU+xS9by4DT4u9IOOsQJ2DS/PNrYFRLNUwDKkdBFrhy3uM0UYl
+                        e8Gvcow0paET4e1i50Urk7Yrnadcr7B9nNqHCrqW6QyuZmurhxyhAIiwYlc+fCVy
+                        BUM9IlZ9yuQNRmTLr9irWbajfKSTtfzJDwid9ZKmKCDzDMci3oobVc8xTOGckoyB
+                        QEyPGpCHu0JACjMUt/qqt/qD0xJTIibRrwPEOBKrxrCFwMfzdKnlmVUGNhI4cA88
+                        TvpYlz3p
+                    </ds:X509Certificate>
+                </ds:X509Data>
+            </ds:KeyInfo>
+        </KeyDescriptor>
+        <KeyDescriptor use="encryption">
+            <ds:KeyInfo>
+                <ds:X509Data>
+                    <ds:X509Certificate>
+                        MIIEUTCCArmgAwIBAgIUcpV0WDMWve6/1FPqzjYJnMLDLRIwDQYJKoZIhvcNAQEL
+                        BQAwKDEmMCQGA1UEAwwddGVzdC5zaGliYm9sZXRoLmVsYXN0aWMubG9jYWwwHhcN
+                        MTkwMzA4MTMxODU5WhcNMzkwMzA4MTMxODU5WjAoMSYwJAYDVQQDDB10ZXN0LnNo
+                        aWJib2xldGguZWxhc3RpYy5sb2NhbDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCC
+                        AYoCggGBAI4haOiDT0q1eBqwKWbOUfxTVQ2d3nC4wpPekB8YixcePBHu1GEKnCmO
+                        E1/EHyhc5EA0p+IV4GRfwEC4bwWOFt5xY2XJREeXg21G1pQ0R2aHIb9cmJWuHHBt
+                        4pIaEiOw1se4zfiTNgcO2WOc6ixmx/cJYjd+FvMPP3Y96JFycVt7f4DTUZ/IGUTO
+                        jOjwRet9vpBHBzIIN+MEnarwd3mPt3FLhsMU09Q/C3Jfw9x+HcSrCQn7d/3ucvZL
+                        iRdYfGxr6YVapwij5eRkVDx6pRi4jTWgNy7BGieWJLElDoPTapmPZxhTIkxnv9/A
+                        HqZmOc2hErU/aPKe/H5doC9Sfj9jEhXURVYeK7Rsmq8IVW6WnVxODjO62/mS58Uu
+                        slkLiNBd0GDx+PRm7YG1k3khJFihtL1xfKIE8PUEqemYIvoHY3/xTujplUDTdHlC
+                        VRaf5/QhT+vgcn7JEXnWtgW1SzSg//lmN1htfOlPb4pXa/Y/Gg2JrsMXXgu098X8
+                        u++qOorK2QIDAQABo3MwcTAdBgNVHQ4EFgQUUxIigNlOHt4GZvE4XwmwPq0H2xsw
+                        UAYDVR0RBEkwR4IddGVzdC5zaGliYm9sZXRoLmVsYXN0aWMubG9jYWyGJmh0dHBz
+                        Oi8vdGVzdC5zaGliYm9sZXRoLmVsYXN0aWMubG9jYWwvMA0GCSqGSIb3DQEBCwUA
+                        A4IBgQB3V3QLkSEnix65cZVH1x4ayZfkyYUeXqQEpjsnz4wGPmWXQp/vJ313mWsV
+                        dtA6uCEHAhAi1It8QpOw0DkQQ39GYLANkra1skjGqOgqjsqCsEX9haaIVvRrG1YP
+                        GA5C6nq88C4KgAYzhfzmOTkDvCLeM/adSV9q8y4juPsrOod81zBjp5GhLfraVUXq
+                        6gwMjRqE+eEgX1RGiYDNl3oar4WB6+cCiTsbkJwHsmGc2LviHxlkPRSIPkJtTUAW
+                        bTCN38FxQda9Ao6ZavSn2Da/HhQm1yxpOdEfTeBSFS5e6NSqj+X1Mc8y0L5cLUyZ
+                        kqQ+q2xhMap2WyDxUm5db9OR5VkrpejR7+f+CYVD7CTt7bqoHQZgaOrGJLje0ZQX
+                        cAeMgEFja4nK0TY8+eD+ijEZ3y/LRMsIl5Hetxaw1atgoVKociuhoF5wZSK0OsDQ
+                        Qx/AEkhqDaSUfSZvSJlD645k/E20NGiK/a8nsquJ3Tkl8rQDEk8r/IKJVmo+vkuX
+                        NgQpDdo=
+                    </ds:X509Certificate>
+                </ds:X509Data>
+            </ds:KeyInfo>
+        </KeyDescriptor>
+        <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" req-attr:supportsRequestedAttributes="true"
+                             Location="https://my-idp.org/login"/>
+        <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" req-attr:supportsRequestedAttributes="true"
+                             Location="https://my-idp.org/login"/>
+    </IDPSSODescriptor>
+</EntityDescriptor>