Skip to content

Optional compression for bearer tokens #705

@bogbert

Description

@bogbert

When using enable-compress-token: true without encryption (enable-encrypted-token: false,
force-encrypted-cookie: false), bearer tokens obtained directly from Keycloak
(e.g. via Authorization: Bearer <token>) are rejected by gatekeeper (gatekeeper expects compressed token)

Configuration to reproduce

enable-compress-token: true
enable-encrypted-token: false
force-encrypted-cookie: false

What happens

  1. Client obtains an access token directly from Keycloak
  2. Client sends request with Authorization: Bearer <raw_token>
  3. Gatekeeper calls DecompressToken on the raw (uncompressed) bearer token
  4. Error: gzip: invalid header → request rejected

Root cause

pkg/proxy/session/token.go, GetIdentity, the compressedOnly branch does not distinguish between bearer tokens and cookie tokens:

if enableEncryptedToken || forceEncryptedCookie && !isBearer {
    // decrypt path ( applied to cookie tokens when forceEncryptedCookie is used)
} else if enableCompressToken {
    // applied to ALL tokens including bearer tokens from Keycloak
    token, err = DecompressToken(token)
    if err != nil {
        return "", errors.Join(apperrors.ErrDecompressToken, err)
    }
}

Proposed fix

Add && !isBearer to the else if enableCompressToken condition, mirroring the encryption path:

} else if enableCompressToken && !isBearer {
    // Only decompress cookie tokens, never bearer tokens
    token, err = DecompressToken(token)
    if err != nil {
        return "", errors.Join(apperrors.ErrDecompressToken, err)
    }
}

Note on operator precedence (reported by Claude)

The existing test

if enableEncryptedToken || forceEncryptedCookie && !isBearer {

is evaluated as enableEncryptedToken || (forceEncryptedCookie && !isBearer) due to Go operator precedence (&& binds tighter than ||). This means when enableEncryptedToken=true, bearer tokens enter the decrypt block of
!isBearer. The enableOptionalEncryption fallback masks this for the encryption case. The intended expression is likely:

if (enableEncryptedToken || forceEncryptedCookie) && !isBearer {

Metadata

Metadata

Assignees

Type

No type

Projects

Status

To do

Relationships

None yet

Development

No branches or pull requests

Issue actions