Issuing address does not match for refresh token after Okapi ip address change
Description
CSP Request Details
CSP Rejection Details
Potential Workaround
relates to
Checklist
hideActivity

Craig McNally January 31, 2025 at 8:47 PM
I see the privacy and gdpr labels have been removed from this issue. I think that’s because OKAPI encrypts the refresh token, so there isn’t a privacy issue here.
the address being stored appears to be the address of the requesting client – i.e. Okapi.
This is a good clarification; thank you . In earlier discussions I was in, it was assumed that this would be the end user’s IP. Given your observation, this really isn’t achieving the desired effect anyway. I’m personally fine with removing this claim altogether from the refresh token. However, if we were to keep it, we should probably have mod-authtoken look at the X-Forwarded-For header to get the appropriate IP, not Okapi’s. To be clear, that still doesn’t solve the problem entirely as end user’s IPs still change from time to time.
It’s also worth noting that even if we remove this claim and related processing, a stolen RT is of limited use. RTR is implemented such that RTs can only be used once. If an RT is attempted to be used a 2nd time the session and all related ATs are invalidated. Yet another reason why having short AT TTLs is recommended. The longer the AT TTL, the longer the window of opportunity is for an attacker to use a stolen RT.

Wayne Schneider January 31, 2025 at 3:14 PM
Thanks, Julian, updated. That “affected institutions” list is kind of out of date! With the workaround to just not use RTR, we would be fine with waiting for Ramsons. I’m not sure what others think.
I would not want to delay beyond Ramsons, as legacy token support is meant to be removed in Sunflower.

Julian Ladisch January 31, 2025 at 8:02 AM
For which release do you need the fix, Ramsons or Quesnelia? Please fill “Affected Institutions”.

Jason Root January 30, 2025 at 6:15 PMEdited
In a K8s environment, where requesting clients (Okapi, Kong) are pods - this is very bad. K8s dynamically assigns random IPs from the cluster internal private network pool. If a pod re-spins for what ever reason (re-deployment, upgrade, failure/recovery, scaling) it will get a new IP from this address space. If the service is clustered - the default MO for K8s is round-robin load-balancing, so chances are that a different Okapi/Kong instance (pod) will be servicing up the request.
Sidebar: I assume Kong can also be ran clustered - which you would want for HA, multi-region and performance reasons.
IP addresses being relied upon for this feature/functionality, and changing even “just” a few times a day will break a lot of automated processes, as well as provide a poor UX for the staff person/FOLIO customer.
Is there a way to not rely on an IP address here but rather a DNS name? Services in K8s and elsewhere usually retain the same DNS name in the cluster/virtual environment even if the pod/container IP addresses change. I’m not as familiar with the tech stack backing the RTR feature set…

Wayne Schneider January 30, 2025 at 5:32 PM
In my testing, the address being stored appears to be the address of the requesting client – i.e. Okapi. If Okapi is clustered, the instance making the request is not necessarily consistent, and repeated calls to /authn/refresh
in a loop will fail erratically. If Okapi is not clustered, I cannot reproduce an error.
Details
Details
Assignee

Reporter

A token should not be tied to an ip address (or hostname) because the ip is not static for some clients:
https://www.akamai.com/blog/developers/why-you-shouldn-t-tie-ip-addresses-to-tokens
https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html#token-sidejacking
mod-authtoken rejects a refresh token if the ip has changed:
https://github.com/folio-org/mod-authtoken/blob/v2.16.1/src/main/java/org/folio/auth/authtokenmodule/tokens/RefreshToken.java#L80
HTTP supports the Forwarded and the X-Forwarded-Host headers that may forward the user’s IP address.
However, Vert.x Web disables forward support by default: https://vertx.io/docs/vertx-web/java/#_forward_support
Neither mod-authtoken nor Okapi use
allowForward
to enable it: https://github.com/search?q=org%3Afolio-org%20allowForward&type=codeTherefore the end-user IP address can never be put into the tokens.
Okapi’s IP address is put into the token.
Okapi’s IP address can change if multiple Okapi instances serve requests, for example when using round-robin.
This bug is a regression because an installation with multiple Okapi instances no longer works when enabling refresh tokens because users gets logged out after 10 minutes (or whatever the access token expiration is).
Fix: Remove IP storage and IP check for the refresh token.