-
Notifications
You must be signed in to change notification settings - Fork 25.6k
Rest spec and documentation #54664
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Rest spec and documentation #54664
Changes from 3 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
16d4334
Rest spec and documentation
jkakavas fa717bd
Merge remote-tracking branch 'origin/master' into rest-spec-idp-master
jkakavas 8ae0bfb
Adjust metadata API docs
jkakavas ff35089
Apply suggestions from code review
jkakavas 1103e58
address feedback
jkakavas 8506582
Merge remote-tracking branch 'origin/master' into rest-spec-idp-master
jkakavas 3216f31
Address feedback
jkakavas 465ef8f
Merge branch 'master' into rest-spec-idp-master
elasticmachine File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
48 changes: 48 additions & 0 deletions
48
x-pack/plugin/identity-provider/docs/en/rest-api/idp-saml-delete-sp.asciidoc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| [role="xpack"] | ||
| [[idp-saml-delete-sp]] | ||
| === Remove a SAML service provider | ||
| ++++ | ||
| <titleabbrev>Remove a SAML service provider</titleabbrev> | ||
| ++++ | ||
| Removes a SAML service provider definition from this identity provider. | ||
|
|
||
| [[idp-saml-delete-sp-request]] | ||
| ==== {api-request-title} | ||
|
|
||
| `DELETE /_idp/saml/sp/{sp_entity_id}` | ||
|
|
||
| [[idp-saml-delete-sp-prereqs]] | ||
| ==== {api-prereq-title} | ||
|
|
||
| * To use this API, you must have a role that grants the `cluster:admin/idp/saml/sp/delete` privilege. | ||
|
|
||
| [[idp-saml-delete-desc]] | ||
| ==== {api-description-title} | ||
|
|
||
| This API removes a service provider from the identity provider by deleting the underlying document that stores | ||
| the service provider definition. | ||
|
|
||
| [[idp-saml-delete-sp-path-params]] | ||
| ==== {api-path-parms-title} | ||
|
|
||
| `sp_entity_id:: | ||
| (string) The SAML entity Id of the service provider to be removed. In case the entity Id is a URL, it should be urlencoded. | ||
|
|
||
| [[idp-saml-delete-sp-params]] | ||
| ==== {api-query-parms-title} | ||
|
|
||
| `refresh`:: | ||
| (Optional, string) One of `true`, `false`, or `wait_for`. | ||
| These values have the same meaning as in the <<docs-refresh, Index API>>, | ||
| but the default value for this API is `false`. | ||
|
|
||
| [[idp-saml-delete-example]] | ||
| ==== {api-examples-title} | ||
|
|
||
| The following example deletes a service provider definition from the identity provider | ||
|
|
||
| [source, console] | ||
| -------------------------------------------------------------------- | ||
| DELETE /_idp/saml/sp/https%3A%2F%2Fsome.sp.org%2F | ||
| -------------------------------------------------------------------- | ||
| // TEST[skip:Do not enable identity provider for the docs cluster, at least not yet] |
122 changes: 122 additions & 0 deletions
122
x-pack/plugin/identity-provider/docs/en/rest-api/idp-saml-init.asciidoc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| [role="xpack"] | ||
| [[idp-saml-init]] | ||
| === Generate a SAML authentication response message | ||
| ++++ | ||
| <titleabbrev>Generate SAML response</titleabbrev> | ||
| ++++ | ||
| Generates a SAML Response message to be sent to a Service Provider | ||
|
|
||
| [[idp-saml-init-request]] | ||
| ==== {api-request-title} | ||
|
|
||
| `POST /_idp/saml/init` | ||
|
|
||
| [[idp-saml-init-prereqs]] | ||
| ==== {api-prereq-title} | ||
|
|
||
| * To use this API, you must have a role that grants the `cluster:admin/idp/saml/init` privilege. | ||
|
|
||
| [[idp-saml-init-desc]] | ||
| ==== {api-description-title} | ||
|
|
||
| This API generates a SAML Response message that should be sent to a Service Provider as part of an | ||
| IDP initiated or SP initiated SAML Single Sign On. This API expects the caller to present | ||
| credentials for the user that the SAML Response will be created for as "Secondary Authentication" | ||
| using the `es-secondary-authorization` HTTP Request header. | ||
|
|
||
| The SAML response is returned as an XML String and the caller of the API is responsible to instruct | ||
jkakavas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| the end user's browser to make an HTTP Post request to the Service Provider with the SAML response | ||
| Base64 encoded. | ||
|
|
||
| [[idp-saml-init-body]] | ||
| ==== {api-request-body-title} | ||
|
|
||
| The following parameters can be specified in the body of a POST request: | ||
|
|
||
| `entity_id`:: | ||
| (Required, string) The SAML entity Id of the service provider that will be the recipient of the SAML Response. | ||
|
|
||
| `acs`:: | ||
| (Required, string) The assertion consumer service URL of the service provider that will be the recipient of the SAML Response. | ||
|
|
||
| `authn_state`:: | ||
| (Optional, object) The JSON structure that <<idp-saml-validate>> returns. This should only be | ||
| provided when calling this API as part of an SP initiated Single Sign On. | ||
|
|
||
|
|
||
| [[idp-saml-init-example]] | ||
| ==== {api-examples-title} | ||
|
|
||
| The following example generates a SAML Response for an IDP initiated SAML Single Sign On to the Service Provider with entity Id | ||
| `https://sp1.kibana.org` and an assertion consumer service URL that is `https://sp1.kibana.org/saml/acs` | ||
|
|
||
| [source, sh] | ||
| -------------------------------------------------------------------- | ||
| curl -u idp_admin:idp_admin_pwd <1> -H 'Content-Type: application/json' \ | ||
jkakavas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| -H 'es-secondary-authorization: ApiKey dVhmUDBuQUJERWhZWEZaQVg5S0k6WUJubmZwNEtRZ1d4cGRxdXBzZmFDUQ==' <2> \ | ||
| localhost:9200/_idp/saml/init -d '{"entity_id":"https://sp1.kibana.org","acs":"https://sp1.kibana.org/saml/acs"}' | ||
| -------------------------------------------------------------------- | ||
| // NOTCONSOLE | ||
| <1> The credentials of the user that has the necessary privileges to call this API | ||
| <2> The credentials of the end user for which the SAML Response will be generated. These can be in the form of a Basic authentication | ||
| header, an elasticsearch access token, or an API key. | ||
jkakavas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| The following example generates a SAML Response for an SP initiated SAML Single Sign On to the Service Provider with entity Id | ||
| `https://sp1.kibana.org` that would have originally sent an authentication request and which has been validated with the | ||
| use of <<idp-saml-validate>> | ||
|
|
||
| [source, sh] | ||
| -------------------------------------------------------------------- | ||
| curl -u idp_admin:idp_admin_pwd <1> -H 'Content-Type: application/json' \ | ||
| -H 'es-secondary-authorization: ApiKey dVhmUDBuQUJERWhZWEZaQVg5S0k6WUJubmZwNEtRZ1d4cGRxdXBzZmFDUQ==' <2>\ | ||
| localhost:9200/_idp/saml/init -d '{"entity_id":"https://sp1.kibana.org","acs":"https://sp1.kibana.org/saml/acs", | ||
| "authn_state":{"authn_request_id":"_3243243243fdwfsd34r2f32f23","nameid_format":"urn:oasis:names:tc:SAML:2.0:nameid-format:transient"}<3>}' | ||
| -------------------------------------------------------------------- | ||
| // NOTCONSOLE | ||
| <1> The credentials of the user that has the necessary privileges to call this API | ||
| <2> The credentials of the end user for which the SAML Response will be generated. These can be in the form of a Basic authentication | ||
| header, an elasticsearch access token, or an API key. | ||
| <3> The `authn_state` JSON structure as it was returned by <<idp-saml-validate>> | ||
|
|
||
|
|
||
| A successful call returns the SAML Response as an XML String, the URL to post this SAML Response to, and information about the Service | ||
| Provider that should receive this SAML Response. | ||
|
|
||
| [source, console-result] | ||
| -------------------------------------------------------------------- | ||
| { | ||
| "post_url" : "https://sp1.kibana.org/saml/acs", | ||
| "saml_response" : "<?xml version="1.0" encoding="UTF-8"?><saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Destination="https://sp.some.org/api/security/v1/saml" ID="_845fbfc9f3254162ce1e161c91b07d85311d65cd" IssueInstant="2020-03-19T15:45:00.158Z" ...removed for brevity ... </saml2p:Response>", | ||
| "saml_status" : "urn:oasis:names:tc:SAML:2.0:status:Success", | ||
| "error" : null, | ||
| "service_provider" : { | ||
| "entity_id" : "https://sp1.kibana.org" | ||
| } | ||
| } | ||
| -------------------------------------------------------------------- | ||
| // TESTRESPONSE[skip:Do not enable identity provider for the docs cluster, at least not yet] | ||
|
|
||
| A failed call, in the case of an SP initiated SSO returns a SAML Response as an XML String with its status set to the appropriate error | ||
| code indicating that the authentication request failed and the reason for that failure. A `saml_status` of | ||
| `urn:oasis:names:tc:SAML:2.0:status:Requester` indicates that the error is on the side of the SP or the user, while a `saml_status` of | ||
| `urn:oasis:names:tc:SAML:2.0:status:Responder` indicates that something went wrong in the IDP side. The `error` field contains a short | ||
| human friendly interpretation of the error that is outside the SAML standard and is meant to be communicated to the user, especially | ||
| if the user is not redirected back the SP with the `saml_response` | ||
|
|
||
| [source, console-result] | ||
| -------------------------------------------------------------------- | ||
| { | ||
| "post_url" : "https://sp1.kibana.org/saml/acs", | ||
| "saml_response" : "?xml version="1.0" encoding="UTF-8"?><saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Destination="https://sp1.kibana.org/api/saml/acs" ID="_845fbfc9f3254162ce1e161c91b07d85311d65cd" IssueInstant="2020-03-19T15:45:00.158Z" Version="2.0"><saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://idp.cloud.elastic.co</saml2:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">...removed for brevity...</ds:Signature><saml2p:Status><saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Requester"><samlp:StatusCode xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Value="urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy"/></saml2p:StatusCode></saml2p:Status></saml2p:Response>", | ||
| "saml_status" : "urn:oasis:names:tc:SAML:2.0:status:Requester", | ||
| "error" : "User [user1] is not permitted to access service [https://sp1.kibana.org]", | ||
| "service_provider" : { | ||
| "entity_id" : "https://sp1.kibana.org" | ||
| } | ||
| } | ||
| -------------------------------------------------------------------- | ||
| // TESTRESPONSE[skip:Do not enable identity provider for the docs cluster, at least not yet] | ||
|
|
||
| A failed call, in the case of an IDP initiated SSO returns an error with the appropriate HTTP Status code. i.e. if the value of the | ||
| `es-secondary-authorization` is wrong, the IDP will respond with `403` | ||
lloydmeta marked this conversation as resolved.
Show resolved
Hide resolved
|
||
55 changes: 55 additions & 0 deletions
55
x-pack/plugin/identity-provider/docs/en/rest-api/idp-saml-metadata.asciidoc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| [role="xpack"] | ||
| [[idp-saml-metadata]] | ||
| === Generate SAML metadata for the IDP | ||
| ++++ | ||
| <titleabbrev>Generate SAML metadata for the IDP</titleabbrev> | ||
| ++++ | ||
| Generates a SAML metadata document for the Identity Provider, describing its configuration and capabilities. | ||
|
|
||
| [[idp-saml-metadata-request]] | ||
| ==== {api-request-title} | ||
|
|
||
| `GET /_idp/saml/metadata/{sp_entity_id}` | ||
|
|
||
| [[idp-saml-metadata-prereqs]] | ||
| ==== {api-prereq-title} | ||
|
|
||
| * To use this API, you must have a role that grants the `cluster:admin/idp/saml/metadata` privilege. | ||
|
|
||
| [[idp-saml-metadata-desc]] | ||
| ==== {api-description-title} | ||
|
|
||
| This API generates a SAML metadata XML Document that can be consumed by a service provider in order | ||
| to be configured to work with this identity provider | ||
|
|
||
| [[idp-saml-metadata-path-params]] | ||
| ==== {api-path-parms-title} | ||
|
|
||
| `sp_entity_id:: | ||
| (string) The SAML entity Id of the service provider that will consume this SAML metadata document. | ||
|
|
||
| `acs`:: | ||
| (string) The SAML Assertion Consumer Service URL of the service provider that will consume this SAML | ||
jkakavas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| metadata document. | ||
|
|
||
| [[idp-saml-metadata-example]] | ||
| ==== {api-examples-title} | ||
|
|
||
| The following example generates a SAML metadata document to be consumed by the service provider with | ||
| entity Id `https://some.sp.org/`. | ||
|
|
||
| [source, console] | ||
| -------------------------------------------------------------------- | ||
| GET /_idp/saml/metadata/https%3A%2F%2Fsome.sp.org%2F?acs=https%3A%2F%2Fsome.sp.org%2Fsaml%2Facs | ||
| -------------------------------------------------------------------- | ||
| // TEST[skip:Do not enable identity provider for the docs cluster, at least not yet] | ||
|
|
||
| a successful call returns the SAML metadata as an XML String | ||
|
|
||
| [source, console-result] | ||
| -------------------------------------------------------------------- | ||
| { | ||
| "metadata" : "<?xml version="1.0" encoding="UTF-8"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://idp.org"><md:IDPSSODescriptor WantAuthnRequestsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><md:KeyDescriptor use="signing"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>MIIDYzCCAkugAwIBAgIVAITQVqXYYUT0w04Z2gWAZ6pv7gwbMA0GCSqGSIb3DQEBCwUAMDQxMjAwBgNVBAMTKUVsYXN0aWMgQ2VydGlmaWNhdGUgVG9vbCBBdXRvZ2VuZXJhdGVkIENBMCAXDTIwMDEyODA2MzczNloYDzIxNjgxMDE5MDYzNzM2WjBRMRMwEQYKCZImiZPyLGQBGRYDb3JnMR0wGwYKCZImiZPyLGQBGRYNZWxhc3RpY3NlYXJjaDEMMAoGA1UECxMDaWRwMQ0wCwYDVQQDEwR0ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAujk+mVzI+qmf4gSJZdVVDdhFTi06kikb7FxG5JPu+gmU9Ke0LVEpP7Jp3gmhwsa18JUuvaepL1jnKmbbepKkEsvqUj4FuI/gImvFwb7X+xUwzNTYZAEvnZ4n16k0sBPuDuDibF0MGniVeLG3bD2VF3crFQrphFr+GZSXbVk5zIcSf6D6nSDcKmCNpVAK3jX9iV0nkr8cPtHOgprv1Y7mZgk5jwli9to0QD7r7OG5Db34R06JTMGTji+RULPISH1bc8FHdurRASkGmsei5GlJqPSuKdViuaKPmDrvKR8OK6gMzUd3pikJgD8veLxEuZ640FHPndPlvwJrSLwhitRgPQIDAQABo00wSzAdBgNVHQ4EFgQUD87H31WVQNfCc85/H2qhpzs3XfowHwYDVR0jBBgwFoAUVenAN+T06rqNDxjMcvgimnTw+FgwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEAIvHYxT30cvoHWUE2saDVJ4qs/e0G3WusDyem3e4HkqwLEah06RDSgVCaOfW3ey5Q6CIQW3HHGUYqO0nU8JVCWdAk3+bUYJJOeLnwD+SbDxxKBhxLdx+BjWata85lfJTR9+dXs0RXAAN8dSiIaj9NSgnwiJqQQZf7i66S7XB58TDTdZlV3d26STLy5h7Uy6vyCka8Xu8HFQ4hH2qf2L6EhBbzVTB6tuyPQOQwrlLE65nhUNkfBbjZlre45UMc9GuxzHkbvd3HEQaroMHZxnu+/n/JDlgsrCYUEXnZnOXvgUPupPynoRdDN1F6r95TLyU9pYjDf/6zNPE854VF6y1TqQ==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://idp.org/slo/post"/><md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat><md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat><md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://idp.org/sso/redirect"/></md:IDPSSODescriptor></md:EntityDescriptor>" | ||
| } | ||
| -------------------------------------------------------------------- | ||
| // TESTRESPONSE[skip:Do not enable identity provider for the docs cluster, at least not yet] | ||
101 changes: 101 additions & 0 deletions
101
x-pack/plugin/identity-provider/docs/en/rest-api/idp-saml-register-sp.asciidoc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,101 @@ | ||||||||||||||||||
| [role="xpack"] | ||||||||||||||||||
| [[idp-saml-register-sp]] | ||||||||||||||||||
| === Register or update a SAML service provider | ||||||||||||||||||
| ++++ | ||||||||||||||||||
| <titleabbrev>Register or update a SAML service provider</titleabbrev> | ||||||||||||||||||
| ++++ | ||||||||||||||||||
| Registers a SAML service provider for use with this Identity Provider or updates the configuration of an existing one. | ||||||||||||||||||
|
|
||||||||||||||||||
| [[idp-saml-register-sp-request]] | ||||||||||||||||||
| ==== {api-request-title} | ||||||||||||||||||
|
|
||||||||||||||||||
| `POST /_idp/saml/sp/{sp_entity_id} + | ||||||||||||||||||
| PUT /_idp/saml/sp/{sp_entity_id}` | ||||||||||||||||||
jkakavas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||
|
|
||||||||||||||||||
| [[idp-saml-register-sp-prereqs]] | ||||||||||||||||||
| ==== {api-prereq-title} | ||||||||||||||||||
|
|
||||||||||||||||||
| * To use this API, you must have a role that grants the `cluster:admin/idp/saml/sp` privilege. | ||||||||||||||||||
|
|
||||||||||||||||||
| [[idp-saml-register-desc]] | ||||||||||||||||||
| ==== {api-description-title} | ||||||||||||||||||
|
|
||||||||||||||||||
| This API registers a Service Provider with the Identity Provider and sets the necessary configuration options for that SP. | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| [[idp-saml-register-sp-path-params]] | ||||||||||||||||||
| ==== {api-path-parms-title} | ||||||||||||||||||
|
|
||||||||||||||||||
| `sp_entity_id:: | ||||||||||||||||||
jkakavas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||
| (string) The SAML entity Id of the service provider to be registered or updated. In case the entity Id is a URL, it should be urlencoded. | ||||||||||||||||||
|
|
||||||||||||||||||
| [[idp-saml-register-sp-params]] | ||||||||||||||||||
| ==== {api-query-parms-title} | ||||||||||||||||||
|
|
||||||||||||||||||
| `refresh`:: | ||||||||||||||||||
| (Optional, string) One of `true`, `false`, or `wait_for`. | ||||||||||||||||||
| These values have the same meaning as in the <<docs-refresh, Index API>>, | ||||||||||||||||||
| but the default value for this API is `false`. | ||||||||||||||||||
|
|
||||||||||||||||||
| [[idp-saml-register-sp-body]] | ||||||||||||||||||
| ==== {api-request-body-title} | ||||||||||||||||||
|
|
||||||||||||||||||
| The following parameters can be specified in the body of a POST or PUT request: | ||||||||||||||||||
|
|
||||||||||||||||||
| `name`:: | ||||||||||||||||||
| (Required, string) A name to identify this service provider. Used only for informational purposes | ||||||||||||||||||
|
|
||||||||||||||||||
| `entity_id`:: | ||||||||||||||||||
| (Required, string) The SAML entity Id of the service provider. | ||||||||||||||||||
|
||||||||||||||||||
| if (document.entityId == null) { | |
| document.setEntityId(entityId); | |
| } else if (entityId != null) { | |
| if (entityId.equals(document.entityId) == false) { | |
| throw new ElasticsearchParseException( | |
| "Entity id [{}] inside request body and entity id [{}] from parameter do not match", document.entityId, entityId); | |
| } | |
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, @lcawl is working on some generic docs for secondary authentication, which we can link to when they're ready.