-
Notifications
You must be signed in to change notification settings - Fork 25.2k
JWT support #72060
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
Comments
Pinging @elastic/es-security (Team:Security) |
In my view, the options that would be close to satisfying the use cases I've seen while making sense technically are the two first ones: run-as and a jwt realm.
Would it be worth to add a summary of the use cases that we know of for how this solution would be used in order to help us come to a conclusion? |
I think historically we (at least it is my impression that this is shared) held the right stance that we cannot validate a JWT, outside of a protocol, as a credential, hence JWT support is not an authentication method. JWT support is about trusting authorization decisions. But, pragmatically, I think the ask is clear: pass a value in a request header (which discounts the JWT / Access Token Exchange option) to let the caller access the resource on ES. Assuming this, I think the best we can do is to try to distinguish the JWT support, where ES acts as the Resource Server, from the authentication role that ES can otherwise take. Concretely, I can think of:
I'm getting a bit extreme, but my overarching point is separation from authentication in terms of configuration, usage and documentation. |
My expectation was that we would absolutely do that validation in ES (I make no presumptions about whether they are validated before they're passed to ES - though I would expect that they should be). The issue is that JWTs fall into 3 rough categories:
A realm is reasonable for (1), but has no real way to know distinguish between those cases, other than indirectly by signing key (that is, an admin knows that a key is only used to generate keys that are intended for authc, and configures the realm to trust that key). Category (2) is really a run-as scenario. I am this system identity (logically equivalent to an OAuth client) authenticated by this credential (e.g. PKI cert/key), and I have a JWT that authorizes me to do something on behalf of this user. Category (3) should be entirely avoided. Trusting a JWT that is neither an authc credential nor an authz token is always going to be a problem. In the realm case the only protection you have against that is the keys that you trust. In the run-as case you have a second layer of protection because you validate that the request came from an authorized client (system account) and your trust model assumes that the client is restrictive about which JWTs it passes through. |
I'd like to propose another option which is a variant of JWT Realm. Instead of just using the JWT as the bearer token, we could configure a secret value for the JWT realm and requires it to be passed along with the JWT. So the bearer header would be something like:
The secret value basically acts as a system password, which prevents malicious usages of arbitrary JWTs. I think it has all the advantages of the JWT Realm while adding extra protection like the run-as option. I'd also assume that this header variant is something that the customer side can easily handle with its current setup. |
From a user perspective, I see the JWT realm as the best option for various reasons. It's simple to communicate, it is more consistent with other authentication/authorization options we already provide, and it would be more complete. Said that, I'm +1 to evaluate security implications and protect our users from common misconfiguration cases. What Yang proposed could be a good option. |
@ywangd Since JWT already assumes a secret that the server knows what is the function of the additional secret in your suggestion? Personally I am in favour of the run-as option. It makes it clear that we intend JWTs to be used for Authorization and enforces that the client sending the request is a genuine client allowed to connect to that Elasticsearch Cluster. For me this option is the easiest for users to ensure they are implementing correctly and not leaving themselves open to unknown clients connecting |
@colings86 The extra secret is to prevent authentication using an arbitrary JWT signed by the same issuer. Specifically this is to solve the following problem listed for the JWT Realm option:
You can think of this additional secret as the actual credential used for authentication and the JWT is for run-as. So it is kinda a cross between the Run As option and the JWT Realm option. Its advantages compared to the pure Run As option are:
|
Hello, since elasticsearch has moved on in minor versions since this was released, is this feature still considered beta? If not, is there a rough timescale as to when it will become a GA feature? |
Hi @owainrutherford, the feature is still in beta even if we haven't got negative feedback so far. |
Thank you for the quick response. Just to clarify, would this be a future minor version of elasticsearch 8, and there are no (planned) breaking changes to this feature? |
We're planning to release improved support in one of the next few minor releases for 8.x. However, our plans may change because of other factors so we cannot commit to any specific version at the moment.
Currently we don't have any planned breaking changes on the table. However, since it's still a beta feature, it may be subject to breaking changes before it goes GA. |
Hi there, I see with elasticsearch 8.8 the beta warning is removed from the documentation. As of 8.8 is the jwt feature now considered GA? |
Yes, the JWT realm is now GA. |
Hello, [Update] |
Hi @miriam-orion, the JWT realm is included in the Platinum and Enterprise subscriptions and it's not available in the Basic tier. You can see it listed along with other Platinum SSO realms in the subscriptions page. |
Thanks for the reply. |
Overview
We would like to offer some form of support for JSON Web Tokens in Elasticsearch Security.
JWTs are a JSON representation of security claims, typically (in practice, universally) about a User (where the term "user" covers any concept of identity, include systems).
JWTs are frequently used as a means of passing a representation of a user's identity between layers or services in an application. For example, a micro services based architecture may authenticate a user at the periphery (e.g on the server side of a web application), and then use JWT as the container for attaching the authenticated user's identity to subsequent service calls. Encapsulating the user's claims in a JWT avoids the need for each service to connect to a central identity store (which may not exist), and the use of JWS provides some degree of security between the layers, and reduces1 the extent to which each service must trust the caller.
JWTs can also be the basis for a distributed authentication protocol - OpenID Connect uses JWTs as the structure in which claims pass from the authentication service to the relying party.
However, JWTs are not, by default, an authentication protocol. They are simply a structure for representing (usually verifiable) claims about an entity. Possession of a JWT does not, on its own, imply that the holder is the user in question, any more than a certified copy of a birth certificate proves that the holder is the person named on that certificate.
This is not simply a theoretical issue - OAuth2 is a JWT based authorization protocol, that is explicitly not an authentication protocol, and treating OAuth JWTs as proof of identity (rather than a means of access) has led to security vulnerabilities in other applications.
That said, there is wide spread use of JWT as the underlying structure of a Bearer Tokens within OAuth and more generally. This is not inherently bad. Elasticsearch Security supports Bearer Tokens that are not implemented using JWT, but could have been - the design and implementation of Elasticsearch's access tokens would not have been compromised if we have elected to build them on top of a JWT format.
If a JWT is issued to a client with the express purpose of being used as a Bearer Token, then using it for that purpose is sound (subject to design/implementation flaws). But an arbitrary JWT may not have been intended as a Bearer Token, and treating it as one (even if it is signed by a trusted party) could result in significant security vulnerabilities.
Consequently, there is value in enhancing Elasticsearch Security to allow user identity to be provided in the form of a JWT, but there are risks with accepting externally generated JWTs as proof of identity.
Options
The following options have been proposed as possibly ways that Elasticsearch Security could support JWT based identity
Run as JWT
Elasticsearch Security has a feature to allow a request to "run as" another user. In current versions of Elasticsearch, this user must exist in a user store (natively within Elasticsearch, or in an external store such as an LDAP directory) and be able to be "looked up" by username from a configured realm.
Permission to "run as" another user is granted via the
run_as
privilege within a role, which grants access by username.This model could be extended to support "run as" with JWTs instead of usernames. The behaviour would resemble the following:
es-security-runas-jwt
), the value of which would be a JWT (possibly base64 encoded).Conceptually this reflect the fact that a JWT, absent any additional context, is a description of a security entity (a user) rather than a credential for that user. Thus it is analogous to looking up a user record in an LDAP directory, rather than authenticating against that directory.
JWT Realm
It is technically possible to implement JWT Bearer Token authentication as a new realm type. Since it is not possible to know whether an arbitrary JWT is intended to be used as a Bearer Token, the onus would be on the Elasticsearch cluster administrator to only configure trust against issuers (keys) that exclusively issue Bearer Tokens. If an administrator configured a realm that trusted an key that was used to sign non-bearer tokens, then this would introduce a security vulnerability in their cluster, but Elasticsearch would have no way of detecting the problem, since it is impossible to distinguish Bearer JWTs from other JWT usage.
Implementation wise, this option would require:
Authorization: Bearer
headersJWTs in the Token Service
Since Elasticsearch Security already has Bearer token support, it would be possible to implement JWT Bearer Tokens as an extension to the token service, rather than a new realm.
However, the implementation (and risks) would be roughly equivalent.
External tokens
Elasticsearch supports OAuth-style access tokens (which are self issued) and Service Account Tokens.
We could extend this to also support "externally validated tokens". These would be tokens that are passed to Elasticsearch using an
Authorization: Bearer
header, but where the validation of the token is delegated to an external service.Strictly speaking this would not add JWT support to Elasticsearch, but it would provide the foundation that allows users of Elasticsearch to relatively easily implement JWT support themselves, using their own validation rule.
This could be implemented by:
This solution allows us to support any sort of bearer token that administrators need, but has some downsides:
JWT / Access Token Exchange
This option is described here: #69996
It is based on the premise that another application is performing a full OIDC authentication process, and Elasticsearch is simply a downstream consumer of that OIDC JWT.
This assumption has the following consequences:
Footnotes
(1) "Reduces" because there is no guarantee that the user who is described in the JWT actually initiated the operation in question.
Assume that there are 3 processes: WebServer, AuthcService & BackendService, all connected using mutual-TLS.
A user provides some set of credentials to the WebServer. WebServer passes those credentials to AuthcService which validates them and returns a signed JWT. WebServer then makes a call to BackendService and provides this JWT as the identity of the originating user on which the call should operate. The BackendService can verify that such as user exists (by validating the JWT signature) and can verify that the request originated from the WebServer (by virtue of the mTLS connection) but it required to trust the WebServer's assertion that this operation was triggered by the User. It has no way of verifying that this is the case.
The text was updated successfully, but these errors were encountered: