-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Token claims customization with Jsonnet #1748
Comments
@tacurran , before starting, I'd like to get some general thumbs up on the idea. Then there are implementation details worth discussing:
|
I'm not sure if this is the best approach to take here. If you have access to the token, you have access to the subject (in the case of It sounds to me like you want to use tokens as a substitute for sessions, which is the wrong approach to take. I understand that some limited information might make sense to mint into the token, but the scope should be really narrow. Adding something that executes arbitrary code on a per-client basis (which is a possibly public-facing API for OIDC Dynamic Client Registration) is pretty dangerous. It would also (potentially) allow attackers to mint tokens with data that can lead to privilege escalation. We do have an open issue (I think) which wants to set extra token data similar to what we do with the |
@redbaron the consensus today is that implementing the changes you request in this issue would potentially weaken token and hydra security. While we admittedly have done limited research into the keycloak "flexible token" approach you mention in the issue, we would rather keep to today's token structure, while keeping options open for the future. You wanted to compare keycloak to hydra, I think. Perhaps you can find other developers that have a similar requirement? This would be one way to get something on the future roadmap. Therefore, we will leave this issue open. Should it become stale, we would then close it. While we really value your input and ideas, we hope you can accept this approach. @aeneasr please chime in here. |
I probably started with too many details, while idea of token customization should have been discussed first. I don't want to divert discussion on the reason of such discussion as it is not the point, it exists in other products, used by many companies and if ORY stack wants to be competitive on this fields it should offer similar feature. All big players in this market allow tokens customization Here are few:
These customizations are expressed either using convoluted UI (Keycloak, WSO2) or unsafe scripting, thus requiring sandboxing (Auth0), declarative rules "DSL" (OKTA), or set as a static values (Firebase) All these products check that customization doesn't touch "protected" claims, therefore do not compromise security of issued tokens. @tacurran , @aeneasr , you gave conflicting responses on whether even minimal form of token customization is something you'd be happy to see in Hydra. Do you think, that case presented is strong enough to entertain idea that hydra should support token customization? UXIf answer to above is yes, then next point of discussion is how to express them? It is important to reiterate, that once customization engine produces desired state of the token, it is then to be verified to not have any protected claims, thus making customizations safe. Existing products on the market picked various approaches. Static set of claimsSimple object ( UIOut of the question for Hydra, so no point discussing pros and cons Scripting languageCustomizations might be expressed as a program in one of scripting languages (Lua, Javascript, anything else). For safe operation it requires either Go interpreter or external process with sandboxing. Feels too heavyweight for this task, but definitely most expressive and easy to adopt by users. Rules DSLSome kind of rules engine, where step by step changes to token accumulated and then final result produced. IMHO it is least ergonomic option. Example of this approach is OKTA. Declarative DSL producing JSONThere many DSL very well suited to produce JSON as it's output. Think of IMHO it is a sweet spot for this task. These DSLs are geared for generating JSON, they are not imperative languages, so no infinite loops, they are pure and as a result safe to run on a server side. They are expressive enough to cover complicated cases your users might have. Out of these I personally would vote for Jsonnet, but I'd take any of them over any other option. |
Hydra supports token customization for all grants except client_credentials already. Are you looking specifically for customization of tokens issued by the client_credentials grant? |
yes and no.there is a way to customize tokens , yes, but customization is not configured on a authorization server side, therefore is "optional" and not enforced. In the same way Hydra already capable of limiting audience and scope per client, there are use cases where custom, user-defined claims should also be controlled by hydra, not client.
This is what prompted me to open this issue, yes, but I dont think this feature should be limited to client_credentials grant only |
Sorry, I don't understand what you mean. Did you read the docs? This is of course enforced on your login app. You have absolute control over the logic and thus over the flow and thus over the token payloads. And yes, this works per client, per user, per day, per IP, per user agent, per whatever - you have absolute control. Please consult the documentation again.
As stated previously, OAuth2 Clients are actually throwaway things. They are generated by third parties not under your control - sometimes in automated ways - with payloads you don't control. While some providers like GitHub have a some type of server-side validation going on, other's that implement OIDC Dynamic Client Registration (we do) do not. This leaves a huge attack surface open for developers that do not know about this feature or the effect that it can have, and that leave the The only thing we have come up so far would be an RPC call for the I don't have exhaustive experience with WSO2, Okta, and so on but as far as I know and have observed, these "custom claims" are actually for the ID Tokens and Access Tokens issued as part of user-facing flows (authorization_code, implicit, ...). I know that Auth0 offers this capabilities (as you mentioned) by executing JavaScript in their WebWorker VMs (I think that's what they call it) but that's basically equivalent to an RPC call. |
Am I correct in assuming that this can be merged with #1383 ? |
Yes I did, even before opening this question. I'd appreciate if you give benefit of a doubt to community members offering help both in providing feedback and writing code. This issue is about token customization applied/enforced by authorization server. Unless I am mistaken you are talking about
As with any authorization server, there are multiple deployment strategies, some of which may not allow dynamic client registration, plus as per docs
All other products on the market allow this customization and don't see it as a security threat. Could you elaborate what's your concern allowing client specifying customizations applied to it's own tokens, provided that claims can only be added, not modified?
At least Keycloak and OKTA 100% can apply these customizations to tokens issued for client_credentials grants. |
Revisiting my comment, I have chosen an overly harsh tone which was not my intention and I am sorry about that (please keep in mind that I’m not a native speaker and Germans are known for their direct language ;) ) comments are thoughtful and with research and that is greatly appreciated, even if there is disagreement!
The assumption is not correct from our viewpoint. The login (authn) consent (authz) app/endpoint is part of the authorization server. It controls who, scope, audiences, and more and should of course be controlled by the same team and audited using the same process. Therefore my previous comments / misunderstanding.
Audience and scope are enforced by the consent endpoint and can be locked down. One problem you uncover here though is that many developers use scope as permissions, which they are not. The token scope could say „admin privileges have been granted“ even if you’re not an admin user in the system. Given this situation and also that we don’t issue client access tokens for modifications on that client we should probably have a public endpoint that specifically does OIDC DCR. This would also allow the admin endpoint to have the ability to specify claim customization although I’d really like to avoid scripting languages - maybe though via go templates?
If misconfiguration allows attackers to customize claim tokens, we are in deep shit as you would be if session cookies were just unencrypted/unsigned json strings. Other products do not allow this on their public facing APIs but as part of an admin flow. What do you think? |
I think it is important to clarify, that I view Authorization server as a internal component of a bigger company infrastructure, where there are multiple first-party services using it's tokens to make calls to each other. Authorization server applies coarse control by limiting allowed audiences per client, so that individual teams developing services cannot silently grant themselves elevated access other than issuing PR to reconfigure Hydra. I realise it is a different model from a "Github-like" setup, where there is a main application and multiple, possibly dynamically generated, clients all use tokens to call that "main" app and never call each other. This can be a source of misunderstanding as we see role of Hydra differently.
Consent app is a unique feature of Hydra, it allows consent screen to be integrated into a client application itself. IMHO integrating consent doesn't make app an inherit part of authorization server, because moving where consent UI is rendered from shouldn't move trust. App implementing consent flow remains a separate entity and should be treated as such, for instance should still be subject to any imposed limits on what tokens it can issue. From this POV, unrestricted What I'd like to get instead is to be able to create customized tokens, while leaving Hydra to be an ultimate authority.
Audience and scope limits are configured during client registration. Can consent endpoint override them, or must use a subset of client's allowed audience and scopes? My understanding, is that complete unrestricted override is not possible, which means that Hydra remains in full control and trust was not shifted to application.
OK, lets scope this change to clients configured via admin flow only.
I'd like to avoid scripts as well, that's why I suggested to use Jsonnet or any other DSL well suited to generate structured data. Great thing about CUE and Jsonnet is that simple JSON is a valid "program", therefore users can start using this feature without much effort. Go templates operate on text and writing templates using it are very error prone, plus it is very cumbersome (or plain impossible without introducing helper functions via template.FuncMap) to express things like list/object comprehensions, basically it fails anywhere outside of |
That may be true for your understanding of an Authorization Server, but it is not true for OAuth2. The scope of OAuth2 is very clearly defined in the abstract of RFC 6749:
The GitHub model is OAuth2, your understanding is not this protocol nor is it OpenID Connect. I think it is very important to clarify this because there are many sharlatans out there that try to sell you OAuth2 as the cure for everything but let me be as clear as I can: It is not. Google, Microsoft, GitHub, Netflix, whoever has serious security engineers in place does not use OAuth2 for first-party authn nor authz. It is a protocol for third parties and that’s all it is really good for.
I understand your point but that’s not the design we chose and I believe this is clarified in the docs and from the privileged rights the login/consent app have (you can literally impersonate someone if you have access to the login app).
I want to clarify that Hydra is an OAuth2 server and not a „token for session“ service. You may be better advised to use AWS KMS or something similar if you want to create/mint tokens from a central authority for internal use. You may be disappointed by this reply but a guiding principle of our ecosystem is that we solve problems well within a clear defined boundary. If you need OAuth2, Hydra is a pretty good choice but if you need mTLS protected IPC with granular and tight employee control over a large network, you need to pick another solution. For example something like SAML for interoperability and flexibility. Hydra can and will not replace an internal „enterprise“ zero trust network because OAuth2 is the wrong protocol to achieve that and if you follow the RFCs and real-world OAuth2 use you will probably come to the same conclusion. Having said that, custom claims for client_credentials are still a good idea as is offering an additional endpoint for OIDC DCR! |
I intentionally tried to avoid reasons of these customizations. Clearly they are in demand by clients and clearly their use can be seen as misuse by some (or all) experts in the field. Nevertheless, it is an opportunity for Hydra not only match feature, but also get ahead of the game by making it much more ergonomic.
Lets discuss implementation details then. Public OIDC DCRI suggest use existing admin registration code as is, but reject certain fields from client definition when invoked via public DCR. Initially only token customization configuration is to be rejected. Token customization configurationWhat's you stance on how configuration might look like? Did you give a thought about proposed DSLs for this task? other flowsDo I understand it right, that you'd prefer token client's customization to be applied only in |
Sorry for the late reply!
Makes sense!
I would like to keep it as simple as possible. Maybe we just include the metadata in the token or add another client field called
Yes because we already have custom claims for all other flows as explained in previous comments and adding another possibility to modify the same behavior is confusing. |
On another thought, to register client with DCR one already have to have a client credentials. Maybe make it a property of the client instead? Something like
This covers my use-case, but does not allow applying any logic, where claims added conditionally. |
No, typically registration is open and a bearer token (not an access token, I think it's called registration token) is needed to make modifications to the client. Alternatively, the client id and secret could be used to make these modifications. Additionally, having valid client credentials does not mean that you should have any authority whatsoever over anything related to the claims of the issued access tokens.
I know but we usually do these things in incremental changes. If there is indeed logic required and the benefits outweigh the downsides of e.g. implementing JSONET then we'll consider the best path to add that feature! |
Hi, I noticed this ticket is listed on the roadmap for 1.11; can you confirm if you're going to be implementing this as described? I've been evaluating Hydra for use in some of our infrastructure and have a very similar scenario to what @redbaron described. I'm interested in the timeline for being able to manage claims like this. |
While I understand that a date of delivery is helpful when planning, we stopped giving out due dates for features or milestones. It puts maintainers in an unfair spot as
When we do give out due dates, we often encounter people who are pissed off because something was promised and not delivered "on time" (as free software ;) ). Unfortunately that is the sad truth of many interactions in this context which is why we stopped doing it altogether. Having said that, you are in the privileged position of being part in a global open source community! If you think that you can contribute towards the particular feature, maintainers will do their best to give you the right pointers and review PRs. If that's not an option, you can consider to become a Ory Sponsor on Open Collective or Patreon. This helps us to employ more maintainers and technical staff - increasing velocity in development, community, interaction, and other areas! All collected money goes directly into this. |
Sorry, I wasn't trying to grill you on a date; I understand your point and appreciate all the work you are doing! I was mostly just interested in an update on where you were at mentally with a solution to this problem, and what to do about the client_credentials claim. I really like Hydra and it fits our needs much, much better than Keycloak, etc. The one thing I'm wrestling with is the service accounts scenario, similar to what the OP described. |
What is the current state of this issue? This feature is mission critical for me to use ORY hydra. If you want I could try to implement this - but I will need guidance and assistance here because I'm new to go lang. |
For anyone looking, a good place to start for the client credentials flow is here: Lines 590 to 627 in 0a73d8b
As you can see we are setting some values in this block: Lines 604 to 605 in 0a73d8b
And basically running that through JsonNet |
I have some questions regarding to the feature specification:
|
We usually allow these files to be loaded from the filesystem (
Absolutely! But keep in mind that the metadata might be changed by the client themselves and it does not represent privileged information.
We can add it as a default dependency :) |
Hello contributors! I am marking this issue as stale as it has not received any engagement from the community or maintainers for a year. That does not imply that the issue has no merit! If you feel strongly about this issue
Throughout its lifetime, Ory has received over 10.000 issues and PRs. To sustain that growth, we need to prioritize and focus on issues that are important to the community. A good indication of importance, and thus priority, is activity on a topic. Unfortunately, burnout has become a topic of concern amongst open-source projects. It can lead to severe personal and health issues as well as opening catastrophic attack vectors. The motivation for this automation is to help prioritize issues in the backlog and not ignore, reject, or belittle anyone. If this issue was marked as stale erroneously you can exempt it by adding the Thank you for your understanding and to anyone who participated in the conversation! And as written above, please do participate in the conversation if this topic is important to you! Thank you 🙏✌️ |
Is your feature request related to a problem? Please describe.
Migrating from Keycloak requires flexible token customization capabilities
Describe the solution you'd like
To keep it flexible, yet lightweight, I am thinking of having a jsonnet snippet as part of a client description. It will be given some rich enough context as an input and would produce additional fields to be added to a token.
Example of jsonnet snippet configured for the client:
At the start, snippet wont be able to alter any existing properties, only introduce new ones.
Describe alternatives you've considered
Additional context
I am mainly focusing on
client_credentials
grant for issuing tokens for service to service communication.How does it fit into token introspect for non-JWT tokens?
I'll be able to work on this feature provided we agree on design details upfront
The text was updated successfully, but these errors were encountered: