-
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
[Feature]: JWT validation only mode #2634
Comments
Sorry for the advertising, for this challenge I have published this tool. You might want to fork it and rebuild it locally |
Hi @jkroepke, can you put an example of token that you want to validate? The idea is that you set the client-id value as the same of the audience of the token ("aud" claim), disable the login page, activate the function to check bearer token and put a random value as client-secret(this will never be used). Let me know if this was helpful or not 😄 |
Hey @CesarStef thanks for your detailed answers. Yes, I want to valid JWT issued by Service Account and secondly I also want to validate tokens issued by Entra ID that are coming trough Managed Identity (like AWS Instance Roles, but the token is an OIDC compatible JWT), Ref: https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http In case you are not familiar with Azure Managed Identity, you can assume its the same concept as Kubernetes Service Accounts, but only for Virtual Machines and the token is available via http. The only difference here is that the aud claim is not fully free to choice. In the case, the audience claim must be pre-registered on the Entra ID first. Additionally, I also would like to authenticate JWT tokens from different sources. While I'm fully flexible at Kubernetes side, for Entra ID I have to use the same audience claim at Entra ID side. I'm also missing the client ID verification.
But not secure! The audience value at the ServiceAccount token volume projection is not validated. Any user could create a service account token with the "correct" audience value to successfully validate against oauth2-proxy. |
Hi @jkroepke, Sorry for the late response!
The audience check is only a part of all the process to validate a token. In my previous message I putted a condition as necessary to make the validation work:
Attackers can't simply put a valid clientId in the token because oauth2-proxy need to verify that the signature of the token is really made by the correct issuer. If somebody manipulate the token, the signature just change and the token is invaid. oauth2-proxy (at least for the oidc standard provider) follow the standard and checks three things to validate the token:
As I know this can't be done now but there are some PR in working to make this possible (maybe some of maintainers can help more then me on this point). |
This is true, but audience is a free-text value field at kubernetes. On kubernetes, you get signed a token with any aud value of your choice. For example: apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /var/run/secrets/tokens
name: vault-token
serviceAccountName: build-robot
volumes:
- name: vault-token
projected:
sources:
- serviceAccountToken:
path: vault-token
expirationSeconds: 7200
audience: vault In that case, the aud value is vault here. As I know, I can put any value of my choice here and it gets signed.
But Kubernetes isn't OIDC standard provider and doesn't want to be, maybe doesn't have to be. In terms of OAuth2, the aud claim has a different purpose (https://www.rfc-editor.org/rfc/rfc7519#section-4.1.3)
That the reason, why the aud claim in Kubernetes and Entra ID is free to choice (Note: Not talking about end-user token, more token about identity (machine) tokens). For example in Entra ID, the aud claim must be From OAuth2 point of view, there is link to the clientID. Based on your comment, A flag like |
Hi @jkroepke, I'm not a maintainer of this app but just an user so everything I will say can be completly wrong and/or not in line with their ideas on this topic :) Said so, I think that we are missing the point, because "aud" is not really so important as much the signature:
(This part is the reason that allow some OAuth2 Authorization Server to not use "aud" at all in their access token, for example: AWS Cognito)
It's just a common practice, but there a OAuth2 authorization Server like AWS Cognito that don't have "aud" at all in their access tokens (but have a custom claim called "client_id"...)
Sorry I misspoke, ".well-known" is part of the OAuth2 specification(s) (https://datatracker.ietf.org/doc/html/rfc8414#section-3.2) So in the end, if Kubernetes don't have a ".well-known" endpoint is theorically not OAuth2 complaint I think. But the meantime I found out that Kubernetes sign the token and theorically you can have the key: So theorically, the problem now is to make them accessible by URL from your oauh2-proxy istance.
No, because you still have the signature problem and to that you must add the problem that you can't know the "sub" value before that your authorization server generate at least one token for that "user". The idea behind having "aud" == "client_id" is to bind the audience to a client and tipically, a client is an application. |
Hey @CesarStef
I think, Kubernetes is compliant here. Only users with edit permissions are able to generate such tokens.
Common practice isn't a spec.
I can't find the quote you mention in that section, however the section clearly describes what the ident of the aud claim is. A URL is common for the aud name.
In that scenario, multiple clients from multiple issue would have the same aud claim value for my endpoint. I agree, that aud claim is optional. But nothing is mention here about a client ID. Kubernetes service accounts doesn't have a client ID.
Kubernetes has a .well-known endpoint + JWKS endpoints.
For Kubernetes, the subject value is the service account name + namespace.
That a good idea, but not mention in the spec. Other scenarios should be supported as well. The OIDC spec describes scenarios, where a end user needs to be authenticated. Mention that for machine based authentication, where non-human identities gets an issued token by default or can request one on demand. For example, in Github Actions having access to an token API to get an signed JWT token where is aud claim is free to choice. There is no client credential or code authorization flow to get an token with an registered client on behalf. Instead a non standardized/proprietary flow is used. It's just curl (in case of Github/Entra ID), cat (Kubernetes) or env variable (Gitlab CI) to get an signed token. In case of Github Action, there isn't a client id. because there is not client. sub claim is commonly used to get an stable identifier. |
Hi @jkroepke,
Perfect, so you can validate Kubernetes without problem.
I completly agree with you and if you look at But there are one big problems with You will still have the "clientID" problem, but if you want to use oauth2-proxy only as resource-server + reverse-proxy it's just a naming problem. I know that the "clientID" parameter name is missleading, but I can see why the maintainers had decided to not create another config parameter with the exactly same scope just for the resource-server only scenario. |
Motivation
I would like to use oauth2-proxy to validate OIDC compatible tokens only. (JWT auth)
Use-Case: Validate Service Account Tokens from Kubernetes
Currently, this is not possible, because client ID/client secret is mandatory.
Possible solution
No response
Provider
None
The text was updated successfully, but these errors were encountered: