Skip to content
Mahesh Kumar Chopker edited this page Jan 21, 2022 · 24 revisions

TL;DR

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

Overview

mod_auth_openidc leverages 2 types of cookies:

  1. a short-lived "state" cookie that correlates the authentication request and response
  2. 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.

Common Settings

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>

SameSite

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=;

State Cookie

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.

Session 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.

Issues

State cookies are piling up

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 default OIDCUnAuthAction 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 adding true 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...

Cookie exceeds size limit

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)

Fixes

  • use a configuration that obtains only a minimal set of claims from the OpenID Connect provider by:

    1. make the provider minimize the set of claims returned in the ID token and from the user info endpoint, and/or
    2. 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

    1. the size of your cookies may easily become very large and the cookie gets truncated leading to cookie decryption errors
    2. alternatively use a version of mod_auth_openidc >= 2.0.0 so it supports chunked cookies