-
-
Notifications
You must be signed in to change notification settings - Fork 328
Cookies
If your state cookies are piling up:
-
protect Javascript paths with
OIDCUnAuthAction 401
(really, no really...) or, if it is not possible to make a split between HTML and Javascript paths - provide a
X-Requested-With: XMLHttpRequest
header in the Javascript call - provide an
Accept: application/json
header in the Javascript call - set
OIDCStateMaxNumberOfCookies 7 true
so the oldest state cookie is deleted
and:
- don't use
OIDCSessionType client-cookie
on versions older than 2.0.0 or minimize the number of claims obtained from the provider
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 since version 1.8.8rc4 (in versions before that, the "state" cookie was a persistent cookie with a limited expiry time).
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=;
(since version 2.4.1)
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 initialing 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. The module will look for a header with the name X-Requested-With
and when that is present it will return a HTTP 401 response instead of creating a state cookie and redirecting the Javascript client to the OpenID Connect Provider (which will not terminate); the X-Requested-With
header is set by default by JQuery; if your Javascript code doesn't set it, you can add it manually as described in: http://stackoverflow.com/questions/12533435/xmlhttprequest-not-adding-header-x-requested-with-xmlhttprequest
Since version 2.1.6 the X-Requested-With
header will need to have the specific value XMLHttpRequest
to trigger the 401 behavior.
Since version 2.3.8 the Accept
header is also inspected for content types that are not HTML i.e. if it finds a value that has only application/json
in it, it will assume it is a non-browser request and will return HTTP 401 by default.
Since version 2.3.8 mod_auth_openidc limits the number of state cookies - i.e. the number of outstanding authentication request - to 7 by default, controlled by the OIDCStateMaxNumberOfCookies
setting.
Since version 2.4.4 mod_auth_openidc allows more 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.4/auth_openidc.conf#L771-L793
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
. -
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