oauth2-proxy/oauth2-proxy · error
failed to decode encryption secret
Error message
failed to decode encryption secret
What it means
Tickets carry the cookie secret used to encrypt the session as a base64url segment (ticketParts[2]). decodeTicketSecret decodes that segment; this error means the secret part is not valid base64 RawURL encoding, or the ticket encoding version is unrecognized so the default branch returns the bare error.
Source
Thrown at pkg/sessions/persistence/ticket.go:114
// to decode the ticket secret part based on the encoding version, or lack of it.
func decodeTicketSecret(ticketParts []string) ([]byte, error) {
switch {
case len(ticketParts) == 2:
// old ticket encoding
secret, err := base64.RawURLEncoding.DecodeString(ticketParts[1])
if err != nil {
return nil, fmt.Errorf("failed to decode encryption secret: %v", err)
}
return secret, nil
case len(ticketParts) == 3 && ticketParts[0] == "v2":
// new ticket encode
secret, err := base64.RawURLEncoding.DecodeString(ticketParts[2])
if err != nil {
return nil, fmt.Errorf("failed to decode encryption secret: %v", err)
}
return secret, nil
default:
return nil, errors.New("failed to decode encryption secret")
}
}
// decodeTicket decodes an encoded ticket string
func decodeTicket(encTicket string, cookieOpts *options.Cookie) (*ticket, error) {
ticketParts := strings.Split(encTicket, ".")
if len(ticketParts) != 2 && len(ticketParts) != 3 {
return nil, errors.New("failed to decode ticket")
}
ticketID, errTicketID := decodeTicketID(ticketParts)
if errTicketID != nil {
return nil, fmt.Errorf("failed to decode ticket: %v", errTicketID)
}
secret, errSecret := decodeTicketSecret(ticketParts)
if errSecret != nil {
return nil, fmt.Errorf("failed to decode ticket: %v", errSecret)
}
return &ticket{View on GitHub (pinned to 33c2eb92de)
Solutions
- Discard the corrupt ticket cookie and log in again to mint a new ticket.
- Verify the full 3-part ticket is intact (two dots, all segments non-empty).
- Check base64 segments are unpadded and URL-safe ('-'/'_' alphabet, no '=').
- Align oauth2-proxy versions across deployments so the ticket encoding format matches.
- If using Redis persistence, inspect the stored key for partial writes or encoding damage.
Defensive patterns
Strategy: validation
Validate before calling
func ticketSecretDecodable(v string) bool {
parts := strings.Split(v, ".")
if len(parts) != 3 {
return false
}
_, err := base64.RawURLEncoding.DecodeString(parts[2])
return err == nil
} Try / catch
t, err := decodeTicket(encTicket, cookieOpts)
if err != nil {
log.Printf("invalid ticket (%v); clearing session", err)
return nil, sessions.ErrInvalidSession
} Prevention
- Treat ticket cookies as opaque; don't inspect or modify them between write and read.
- Check storage backends (Redis/cookies) for truncation on write.
- Pin oauth2-proxy versions during rolling upgrades to avoid format mismatches.
When it happens
Trigger: decodeTicket is called with a 3-part ticket whose third segment fails base64.RawURLEncoding.DecodeString, or a ticket with an unknown version prefix falls into the default case.
Common situations: Cookie truncated or corrupted in transit/storage; ticket value altered by manual copy/paste; version mismatch between the oauth2-proxy that wrote and the one reading the ticket (e.g. upgrade/downgrade mixing v1 format with legacy 2-part format).
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to decode ticket Id
- failed to decode ticket Id: %v
- failed to decode encryption secret: %v
- failed to decode ticket
- failed to base64 decode value %s
AI-assisted analysis of oauth2-proxy/oauth2-proxy@33c2eb92de (2026-09-06).
Data as JSON: /api/errors/67ecf230e30c934c.
Report an issue: GitHub.