-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
fix(server): Switch to using access token for SSO. Fixes #4027 #4035
Conversation
@@ -19,7 +19,7 @@ import ( | |||
"github.com/argoproj/argo/server/auth/jws" | |||
) | |||
|
|||
const Prefix = "Bearer id_token:" | |||
const Prefix = "Bearer v2:" |
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.
this magic string could be anything, but lets expose a little less info
Hoping I'm understanding this PR correctly, and do have some feedback:
For some context, the intent is also that the access_token in OAuth2 systems itself should also be short lived. Instead, you usually have some sort of refresh_token or credentials which can be given to a provider for a newly minted access & id token. Or at least that's how it works in OIDC land usually. So the app or session manager would either reactively (in response to a
Correct me if I'm wrong, but encrypting it does nothing, no? It just means an interceptor can't read the jwt, but it doesn't prevent them from actually using it. It sounds like what you're trying to accomplish might be better accomplished via setting |
This prevents someone from taking the cookie and using to speak directly to another system that accepts the access token - because it is encrypted and they cannot decrypt it. In additional, this token would only have |
This is one way to solve that, but usually this is also solved by requesting the |
Moved from slack to github: So I did take a look at this and it looks like an Authorization Code flow from the server that you are then storing the access token in an encrypted cookie, I have seen this done in a few projects such as https://github.com/oauth2-proxy/oauth2-proxy the one downside to this is that cookie can get very large when encrypted with some access tokens such is the case generally with jwt’s and azure comes to mind here (also jwt’s with group scopes) oauth2-proxy actually implements a cookie splitting but actually recommend using their redis backend instead to store the token and then they just store a short session cookie https://oauth2-proxy.github.io/oauth2-proxy/auth-configuration#azure-auth-provider notice the note at the bottom
But other than that from a security perspective nothing jumps out at me, but I didn’t spend a lot of time looking at how the cookie encryption was done. |
I will say the one area I think PKCE might make sense and I kind of alluded a bit to this is with people that have a k8s cluster setup for oauth logins already then you don't really need any server component you just need to get a token from the same oauth provider that k8s is using and use that token then communicate to kubernetes directly from the client say a local argo server command. |
Is there any consideration of implementing token_refresh in this PR as well? Azure access tokens will still be limited to 3600 seconds without it. I believe it would require using a second cookie to store the refresh_token, adding a handler for an 'oauth2/refresh' endpoint, and then updating the UI to try and hit that endpoint on a 401 error before redirecting to the login page. |
After discussion with corp experts - this is wrong approach. |
Superseded by #4095 |
Checklist:
"fix(controller): Updates such and such. Fixes #1234"
.Fixes #4027
@jessesuen and @edlee2121 this changes how
argo-server
authenticates users. Previously, we stored theirid_token
as a cookie. This token was adequate because we need only to verify their identity. This is similar to Argo CD. However, ID tokens are not intended as long lived and expire after 5m, forcing users to re-login.This PR switches to use the access token instead of the ID token. We should not store an access token in a cookie the same way you could an ID token, because if the access token is stolen, the token could be used to make API requests with other system. So now, access token is AES-GCM-256 encrypted when saved as a cookie. It is useless apart from speaking to Argo Workflows.
The encryption key is cryptographically secure random generated string. It is saved into a Kubernetes secret on first start up, so it can then be used any
argo-server
replica.The access token is opaque, unlike the ID token so each
argo-server
must make an API request to validate it. Each time a request is made, we decrypt the cookie, and make a OIDCUserInfo
request.The cookie has a 10h expiry, secure and same-site-strict, so not accessible to HTTP or other apps. This is unchanded.
If the cookie is compromised, we are in the same situation as today (which is acceptable).
If the encryption key is compromised, the operator should delete it and restart the service. All users will be logged out, and must log back in.