-
Notifications
You must be signed in to change notification settings - Fork 326
Cookies
If your state cookies are piling up:
- upgrade to version >= 2.4.10
- protect Javascript paths with
OIDCUnAuthAction 401
- configure a customized expression/algorithm to
OIDCUnAuthAction
to detect requests that will never complete a full authentication flow
mod_auth_openidc leverages 2 types of cookies:
- a short-lived "state" cookie that correlates the authentication request and response
- a long-lived "session" cookie that maintains session state after successful authentication
Both cookies are non-persistent session cookies that will be discarded on a browser restart.
The cookie path and cookie domain settings are shared between the "state" and "session" cookies and can be controlled with the following configuration primitives:
# (Optional)
# Define the cookie path for the "state" and "session" cookies.
# When not defined the default is a server-wide "/".
#OIDCCookiePath <cookie-path>
# (Optional)
# Specify the domain for which the "state" and "session" cookies will be set.
# This must match the OIDCRedirectURI and the URL on which you host your protected
# application. When not defined the default is the server name.
#OIDCCookieDomain <cookie-domain>
The default SameSite=None
cookie appendix on Set-Cookie
response headers (configured by OIDCCookieSameSite
) can be overridden using an environment variable as in:
SetEnvIf User-Agent ".*IOS.*" OIDC_SET_COOKIE_APPEND=;
The "state" cookie is created when the user is redirected away to the OpenID Connect Provider for authentication and is used to correlate (possibly parallel) outgoing authentication requests and incoming authentication responses.
It is a cookie with unique name (prefixed with a string which can be configured with the OIDCStateCookiePrefix
primitive, the default is mod_auth_openidc_state_
) that is tied to the state
parameter that is sent in the authentication request. It is deleted when the user returns to the Apache server with an authentication response (indicating either success or failure). It is (should be) short-lived and its lifetime can be configured with the OIDCStateTimeout
configuration primitive for which the default is 5 minutes. This timeout effectively denotes how much time the user is given to authenticate, i.e. the interval between initializing a login request and actually logging in and returning with an(y) authentication response.
Note that the lifetime of the state cookie is enforced at the server by mod_auth_openidc, not by any lifetime in the Set-Cookie
header itself, because it is a so-called session cookie that is removed when an authentication response is received or the browser exits/restarts.
In addition to correlating requests and responses, this cookie is used to prevent Denial of Service attacks. This is because server side state (and a session) will only be created after exchanging a correlated request/response pair. This means that no unnecessary temporary server side resources are allocated for non-completing, mis-configured, fake or fraudulent requests, nor can such requests overload the server (memory/cache) at any time. The only resources allocated during the login process reside on the client ie. the browser in the form of a cookie.
The "session" cookie is created after the user returns from the OpenID Connect provider with a successful authentication response (note that the state cookie is deleted at the same time). The name of the session cookie can be configured with the OIDCCookie
primitive, the default is mod_auth_openidc_session
.
Multiple state cookies can be created in the same browser when multiple (unauthenticated) requests are fired off in parallel or several requests are being fired sequentially without ever completing/resulting into a successful authentication response.
For example, in the case where a user hits the login page 10x in different browser tabs but never actually logs in. This can lead to an HTTP header size overflow and often occurs for Single Page Applications that automatically refresh pages when not (yet) authenticated. When dealing with an SPA, the first counter measure would be to use OIDCUnAuthAction 401
on those paths that are only ever accessed through XHR requests (which would never be able to complete a login flow anyhow).
Recent versions of mod_auth_openidc implement an auto-detection algorithm so that non-browser requests are automatically responded to with a 401 without redirecting them to a Provider and creating a state cookie. Since version 2.4.4 mod_auth_openidc allows complete flexibility and control over the action to be taken upon unauthenticated requests by adding an (optional) expression parameter to the OIDCUnAuthAction
primitive that specifies a matching filter for clients. See: https://github.com/zmartzone/mod_auth_openidc/blob/v2.4.9.4/auth_openidc.conf#L802-L835
Fixes
-
Configure Javascript/XML Request/XHR/non-browser paths with
OIDCUnAuthAction 401
instead of redirecting users away to the OpenID Connect provider with the defaultOIDCUnAuthAction auth
, possibly using a customized detection algorithm as described above. -
Since version 2.3.10.1 mod_auth_openidc can also be configured to delete the oldest state cookie when overrunning the
OIDCStateMaxNumberOfCookies
limit by addingtrue
after the size value e.g.OIDCStateMaxNumberOfCookies 5 true
Notice that the last option does not really fix anything (because the underlying problem lies within the application itself), it just implements a different type of erroneous situation handling: instead of aborting because the number of cookies gets too large, the browser will now get into a - possible endless - loop, depending on what triggers the unauthenticated requests...
There are a number of circumstances that may lead to a message on the browser or the server that indicated that the cookie size has exceeded the size limit. This is often the case for unauthenticated or expired sessions when either a large number of pages are opened in the same browser simultaneously and/or pages loaded in the browser make a large number of parallel Javascript calls to the server. Typically this indicates a configuration issue that should be solved by reconfiguring the way in which your application is protected.
Version 2.0.0 adds chunked session cookies that give a lot more room for storing data in cookies.
Symptoms
-
Set-Cookie may exceed size limit:
-
size of session cookie is too large when
OIDCSessionType client-cookie
is used[warn] [client <ip>] oidc_util_set_cookie: the length of the cookie value (<size>) is greater than 4093(!) bytes, this may not work with all browsers/server combinations: consider switching to a server side caching!
-
-
Cookie is corrupted
[warn] [client <ip>] oidc_session_load_cookie: cookie value possibly corrupted [error] [client <ip>] oidc_crypto_aes_decrypt: EVP_DecryptFinal_ex failed: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
-
Cookie may exceed size limit
- size of session cookie combined with other cookies is too large when
OIDCSessionType client-cookie
is used - number of state cookies may exceed size limit
- size of state cookie may exceed size limit when combined with other cookies (unlikely, only when using very long URLs)
- size of session cookie combined with other cookies is too large when
Fixes
-
use a configuration that obtains only a minimal set of claims from the OpenID Connect provider by:
- make the provider minimize the set of claims returned in the ID token and from the user info endpoint, and/or
- don't specify the user info endpoint in the mod_auth_openidc configuration for the provider so that only claims from the ID token will be present in the session
-
don't use
OIDCSessionType client-cookie
- the size of your cookies may easily become very large and the cookie gets truncated leading to cookie decryption errors
- alternatively use a version of mod_auth_openidc >= 2.0.0 so it supports chunked cookies