-
Notifications
You must be signed in to change notification settings - Fork 40
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
Session cookies never expires #316
Comments
On a 401 the client should re-attempt authentication and get a new cookie, not sure why that would not be working. |
I am currently testing another hypothesis, I had set the |
I was wrong again, the cause of the 401 is that the credentials made available in
Is there something my application should do to renew them? The credentials on the client still had a lifetime of 59536s when the delegated credential on the server was found expired and the 401 was returned. Could it be that using sessions prevents the client from renewing the delegated credential on the server? Or are sessions unrelated? I'm not sure what's going on here, and what I'm missing. |
Ideally you have a session key has a shorter expiration than credentials, when using sessions the client will just try to send a session cookie, however upon receiving a 401 the client should simply try a new gssapi authentication, did the client simply send back the session cookie and not try to perform an actual authentication ? The web server log may have some good pointers if you enable the debug level. |
The server code checks the ticket lifetime of the credentials that mod_auth_gssapi makes available in Is there a way for my server python code to trigger a proper 401 response from mod_auth_gssapi with the Negotiate header when the delegated credentials are expired? |
I think 401 with Negotiate header is the regular way to ask a client to authenticate, why is the client not trying is the question ... |
Hmm no I'm not sending a |
If mod_auth_gssapi sees that the creds expiration has been reached in mag_check_session() then it will not proceed to the application at all and will return a 401 negotiate. However if you return 401 directly from the application then mod_auth_gssapi is not involved anymore and you will have to return the Negotiate header yourself, alternatively you could return a Redirect error to the client where you also tell the client to invalidate the cookie. This will caus an additional rountrip in the client but will allow mod_auth_gssapi to send the 401 itself with the correct negotiate headers. What is odd is that it seem there is a disagreement between mod_auth_gssapi and your application on the expiration time of the creds?? |
Oh good idea, I'll try that.
Indeed! Here's the delegated credentials that mod_auth_gssapi provides my application with:
I had to restart the client this morning because the authentication was expired again, but if it unfolds as before this time around again, I can tell that at |
OK I did manage to workaround the issue by having the server return a 302 to the same address with the HTTP header that I had set in |
See gssapi/mod_auth_gssapi#316 Signed-off-by: Aurélien Bompard <[email protected]>
This is made harder by Yelp/bravado#494 It is necessary because of gssapi/mod_auth_gssapi#316 Signed-off-by: Aurélien Bompard <[email protected]>
Perhaps I need to cross check the cache liftime with the lifetime claimed in the cookie. |
Ah but I thik I know how something like that can happen now that I think about your situation. That could cause a client that is configured to obtain a shorter lived credentials to overwrite the cache creds with ones that are shorter lived than the creds another client originally used to obtain their cookie. Like:
Can you confirm if this is a scenario that may be happening in your environment? |
When I looked at the cookie that the client receives, I didn't see any expiration date set. This is the received header:
I don't think so, the credential comes from a keytab that only this app is using, and there's only one concurrent pod running. I've managed to reproduce it on my local dev env and I can easily test it by setting |
The expiration is one of the data points in the encrypted part (MagBearerToken). Can you detail better how you reproduced? Are you preforming constrained delegation on the server? |
Ah, that makes sense :-) If I understand correctly, the mod_session cookie is shared with other applications on the Apache instance, so it's not really possible to have it expire with the creds, right? Is there a way for me to look into this expiration date in the encrypted token?
This is the relevant apache config part:
I've also set This is the client: from time import sleep
from fasjson_client import Client
c = Client("https://fasjson.tinystage.test/fasjson/")
for i in range(10):
print(c.whoami()) # This makes the authenticated HTTP call
sleep(2) The client class initialization code is here: https://github.com/fedora-infra/fasjson-client/blob/dev/fasjson_client/gss_http.py
Yes! It's the delegated credentials that expire before the |
Ok, it seems to me the problem is that you have a shorter ticket_lifetime on the server than on clients, therefore when the server take a delegated ticket it will have a shorter expiration time even if the client ticket is still valid. A simple way to fix this is to make the lifetime on the server as long as a the longest ticket lifetime on any client (I expect 24h to be a common value). Other than that I need to think if it is possible to better handle this on the server side. |
On the actual servers the ticket_lifetime is 24h for each, I've set it short on my testing env because I didn't want to wait a day to see if my attempts to workaround this were successful. But on the actual server and client it's 24h. As I wrote in #316 (comment) the client ticket was still valid for a long time when the delegated credentials expired on the server. |
Can you klist /run/fasjson/krb5ccache as well as the user specific ccache ? I am not sure yet how to handle this situation, ut I want to figure out the cause before I can suggest a) a workaround and then b) a solution I can implement in actual code |
I think you may be right, because I've seen the delegated credentials lifetime be shorter than 24h even right after they were obtained.
and this is on the client:
So the client did obtain a ticket for |
Ok, so I am surprise that the client would even get back a 401 in this scenario, as the delegate credentials are not something mod_auth_gssapi would check during authentication, is your application itself returning the 401 to the client after a failure to use those credentials ? |
Yes, my server checks the lifetime of the delegated credentials and returns 401 if they are expired. |
I have been thinking about this for a while, and I do not see a very clean solution yet, I think one way would be for you to remove the expired ccache, drop the session cookie and set the negotiate headers in the 401 response. This will force the client to try to re-authenticate and mod_auth_gssapi will re-create the needed tickets. |
(edited the comment above as I fat fingered a send mid-typing :) |
Thanks for looking at it!
OK, can the application behind
Understood. It would work if the application behind |
You cn easily set the Negotiate headers, the first header is quite standard and is literally just: |
Oh! I didn't realize that :-) |
…cting See gssapi/mod_auth_gssapi#316 Signed-off-by: Aurélien Bompard <[email protected]>
Great news! |
According to the
GssapiUseSessions
documentation, the session cookies should expire according to the lifetime of the GSSAPI session established at authentication. I don't see the expiration beeing set in the cookie header:My config file includes:
If I look at the
ipa_session
cookie header sent back to curl, I don't see any Expires attribute.I think that may be why my long-running http client end up getting 401's: they keep the session cookie around when they should drop it.
The text was updated successfully, but these errors were encountered: