Skip to content
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

SAML _security/saml/prepare API should allow consumer to specify RelayState #46232

Closed
azasypkin opened this issue Sep 2, 2019 · 9 comments · Fixed by #46534
Closed

SAML _security/saml/prepare API should allow consumer to specify RelayState #46232

azasypkin opened this issue Sep 2, 2019 · 9 comments · Fixed by #46534
Assignees
Labels
>enhancement :Security/Authentication Logging in, Usernames/passwords, Realms (Native/LDAP/AD/SAML/PKI/etc)

Comments

@azasypkin
Copy link
Member

Currently Kibana heavily relies on URL fragments to navigate between the apps and store applied filters. And since URL fragments are never sent to the server Kibana didn't preserve them during SAML handshake. Moreover URL fragments used in Kibana can be pretty large so we can't store them in the session cookie like we do for SAML request ID. We're planning to change this in 7.5 (see elastic/kibana#44513) and store full URL in the RelayState query string parameter we send to IdP and receive back once user is authenticated.

As we discussed with @jkakavas in elastic/kibana#18392 (comment) it'd make sense for _security/saml/prepare API to accept the arbitrary string as an additional argument with that will eventually be used as RelayState query string parameter in the IdP redirect URL this API returns.

cc @kobelb

@azasypkin azasypkin added >enhancement :Security/Authentication Logging in, Usernames/passwords, Realms (Native/LDAP/AD/SAML/PKI/etc) labels Sep 2, 2019
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-security

@tvernum
Copy link
Contributor

tvernum commented Sep 11, 2019

Moreover URL fragments used in Kibana can be pretty large so we can't store them in the session cookie like we do for SAML request ID.

We're planning to [...] store full URL in the RelayState

This isn't going to work. Per the specs RelayState may not exceed 80 bytes.
SAML binding spec, section 3.4.3

RelayState data MAY be included with a SAML protocol message transmitted with this binding.
The value MUST NOT exceed 80 bytes in length and SHOULD be integrity protected by the
entity creating the message, either via a digital signature (see Section 3.4.4.1) or by some
independent means.

@jkakavas
Copy link
Member

Good catch Tim ! Link to the aforementioned spec: https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf

@azasypkin
Copy link
Member Author

That's a bummer, 80 byte RelayState isn't super useful. Looks like some (many?) IdPs (e.g. Auth0) don't enforce this limit though.

@jkakavas
Copy link
Member

Okta doesn't and AFAIK shibboleth will only print a warning about it. The downside of this is that we will be building functionality that explicitly violates the spec and depends on other implementers current leniency which is not to be taken for granted and is not future-proof.

I was digging up some old mailing list threads and it seems that (At least one of) the reason this size limit was added was to discourage SPs from sharing the entire return URL in the relaystate, in order to protect users' privacy

@azasypkin
Copy link
Member Author

Okta doesn't and AFAIK shibboleth will only print a warning about it. The downside of this is that we will be building functionality that explicitly violates the spec and depends on other implementers current leniency which is not to be taken for granted and is not future-proof.

Yeah, I agree. We have 80 bytes limit for RelayState and ~4KB limit for all cookies per domain Kibana server relies on. The correct and future-proof solution would probably be to store full URL in ES somehow (option 3 here). But the question here is whether Kibana or ES would be the best candidate to do that and how to automatically clean it up in case of SAML auth attempts that are never completed. It's not always obvious where to put that functionality in case of such a composite SP :)

If ES does that it could include some opaque token in RelayState instead of actual content and return that content only in saml/authenticate response. But as far as I understand ES doesn't store anything related to SAML request right now and doing so would be problematic/not-desirable?

Kibana can emulate that too via some dedicated Saved Object in .kibana-* index. We can put ID of such object to the cookie together with SAML Request ID and retrieve it later. The only problematic thing here is to somehow remove this object automatically after some period of time if it's not used. I can dig deeper into this option if the the option above is a no-go for ES.

I was digging up some old mailing list threads and it seems that (At least one of) the reason this size limit was added was to discourage SPs from sharing the entire return URL in the relaystate, in order to protect users' privacy

Interesting, I see Auth0 proposes to use URL in RelayState for the IdP initiated logins.

@tvernum
Copy link
Contributor

tvernum commented Sep 11, 2019

The reason I looked up the spec is because web servers have varying limits on the length of a request line, some as low as 4k.
So, putting aside the spec limit, once you include the rest of the path, and the signature etc, I'm not sure that a 4k redirect URL gives you a lot more space than you had with the cookie.

Have you considered using localStorage instead of a cookie? I know Kibana doesn't do that now, but it seems like a reasonable fit for this.

@jkakavas
Copy link
Member

jkakavas commented Sep 11, 2019

If ES does that it could include some opaque token in RelayState instead of actual content and return that content only in saml/authenticate response. But as far as I understand ES doesn't store anything related to SAML request right now and doing so would be problematic/not-desirable?

We don't keep state at all ( we rely on the caller of the APIs to maintain the request IDs also ) so it would definitely not be preferable to store this in ES.

Interesting, I see Auth0 proposes to use URL in RelayState for the IdP initiated logins.

This is a different use case and this destination URL would be a generic app URL , which is fine. The problem with SP initiated SSO and deep links is that the IDP gets to know potentially private browsing behaviors of the user ( i.e. relayState=https://medicalforums.org?category=thisspecificidthatcorrespondstoaspecificdesease )

@azasypkin
Copy link
Member Author

I'm not sure that a 4k redirect URL gives you a lot more space than you had with the cookie.

It depends, we always encrypt cookie content that quite significantly affects the amount of info we can store there and 4k limit is for all cookies per domain (Kibana uses just one right now, but it can easily be hosted behind a custom path in a domain that is shared with other apps that also can use cookies).

Have you considered using localStorage instead of a cookie? I know Kibana doesn't do that now, but it seems like a reasonable fit for this.

Yes, we considered sessionStorage and it's an option, but not really the best one as it makes solution even more complex (additional redirect and additional type of storage we'll have to spread SAML auth knowledge over).

We don't keep state at all ( we rely on the caller of the APIs to maintain the request IDs also ) so it would definitely not be preferable to store this in ES.

I see, thanks. So RelayState would be the only way for the caller of the APIs to know if response corresponds to a request (since it can't decrypt SAML response and extract request ID) in case there is a need for that.

This is a different use case and this destination URL would be a generic app URL , which is fine.

Right, right. I just meant that if we don't use RelayState we won't be able to support custom URLs for IdP initiated logins.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>enhancement :Security/Authentication Logging in, Usernames/passwords, Realms (Native/LDAP/AD/SAML/PKI/etc)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants