cloudfoundry / uaa

CloudFoundry User Account and Authentication (UAA) Server
Apache License 2.0
1.58k stars 826 forks source link

Support id_token_hint external oidc logout #3037

Closed mikeroda closed 2 weeks ago

mikeroda commented 1 month ago

When performing an RP-initiated logout with an external OIDC provider, UAA does not pass the id_token_hint. This is a required parameter for Okta so single logout does not work with Okta when using OIDC.

What version of UAA are you running?

v77.10.0

How are you deploying the UAA?

I am deploying the UAA

What did you do?

Configured UAA for external OIDC logins with Okta and enabled RP-initiated logout. Logged in to UAA using the Okta link and then did a logout.

What did you expect to see? What goal are you trying to achieve with the UAA?

Successful logout at Okta and redirect back to UAA on the post_logout_redirect_uri.

What did you see instead?

400 Bad Request

strehle commented 1 month ago

@mikeroda FYI. This GAP is known and more or less because we could keep the original id_token from Okta in session, but this token is expired after an hour and then I dont know if Okta ignores . Because doing a refresh flow only that we have a recent id_token to logout later on is somehow too much in my eyes

mikeroda commented 1 month ago

@strehle the Okta documentation says they will accept an expired id_token so this seems doable.

If the ID token is valid, but expired, and the subject matches the current Okta session, a logout request logs the user out and redirects the browser to the post_logout_redirect_uri.

https://developer.okta.com/docs/reference/api/oidc/#logout

strehle commented 1 month ago

Ok and thank you, so expired tokens accepted, similar then other IdPs do.

We can add the id_token to the HTTP session for such scenarios. Therefore the question to you. Do you use sessions in DB , means uaa.yml setting session-store: memory or database, e.g. https://github.com/cloudfoundry/uaa/blob/develop/scripts/cargo/uaa.yml#L2-L3 And do you have other settings here https://github.com/cloudfoundry/uaa/blob/develop/server/src/main/resources/spring/login-ui.xml#L163

mikeroda commented 1 month ago

We use sessions in memory but have session affinity enforced at ingress so it seems fine to store this in the HTTP session. Not sure what the current user cookie settings have to do with this.

strehle commented 1 month ago

We use sessions in memory but have session affinity enforced at ingress so it seems fine to store this in the HTTP session. Not sure what the current user cookie settings have to do with this.

ok, then this means you have the http session on backend only in memory (and this means only for 30 min in local tomcat session store)

I only wanted to know this to have a basis for further plannings and/or discussions.

mikeroda commented 1 month ago

I actually have the current user cookie stuff disabled because security scans were complaining about it.

strehle commented 1 month ago

I actually have the current user cookie stuff disabled because security scans were complaining about it.

sorry for the confusion on your side. to me I wanted to know only your session max-age and reference the wrong code. https://github.com/cloudfoundry/uaa/blob/develop/server/src/main/java/org/cloudfoundry/identity/uaa/web/beans/UaaSessionConfig.java#L32-L33 . interesting is/was what do you have in servlet.session-cookie.max-age and the idle-timeout

https://github.com/cloudfoundry/uaa/blob/0bbb8dcc8fc9faf406ecab509076890c482abfa8/server/src/main/java/org/cloudfoundry/identity/uaa/web/beans/UaaMemorySessionConfig.java#L33

mikeroda commented 1 month ago

I'm using 30 minute sessions as well.

mikeroda commented 1 month ago

I started to work on this and have something roughed out working but wanted to mention the approach before I get any further. Storing the id_token in the http session didn't work because the external logout happens after the local logout and the session is null in the request by the time we need it. But the authentication is still available so I was trying to figure out where would be a good place to put this. Since the UaaAuthenticationDetails has a field for UaaTokenHint, and this seems similar in purpose to the ID token hint, perhaps adding it there as an additional field (right now it just has origin). Let me know what you think.

strehle commented 1 month ago

I started to work on this and have something roughed out working but wanted to mention the approach before I get any further. Storing the id_token in the http session didn't work because the external logout happens after the local logout and the session is null in the request by the time we need it. But the authentication is still available so I was trying to figure out where would be a good place to put this. Since the UaaAuthenticationDetails has a field for UaaTokenHint, and this seems similar in purpose to the ID token hint, perhaps adding it there as an additional field (right now it just has origin). Let me know what you think.

I have created a draft change where I store it into UaaAuthentication . I see, you recently opened a PR to it. So I will push my and then we can compare