mirror of
https://github.com/zitadel/zitadel.git
synced 2025-01-06 13:57:41 +00:00
b58956ba8a
# Which Problems Are Solved Some IdP callbacks use HTTP form POST to return their data on callbacks. For handling CSRF in the login after such calls, a 302 Found to the corresponding non form callback (in ZITADEL) is sent. Depending on the size of the initial form body, this could lead to ZITADEL terminating the connection, resulting in the user not getting a response or an intermediate proxy to return them an HTTP 502. # How the Problems Are Solved - the form body is parsed and stored into the ZITADEL cache (using the configured database by default) - the redirect (302 Found) is performed with the request id - the callback retrieves the data from the cache instead of the query parameters (will fallback to latter to handle open uncached requests) # Additional Changes - fixed a typo in the default (cache) configuration: `LastUsage` -> `LastUseAge` # Additional Context - reported by a customer - needs to be backported to current cloud version (2.66.x) --------- Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com> (cherry picked from commit fa5e590aabda38bd346f1a41484466aebdd8f903)
113 lines
3.9 KiB
Go
113 lines
3.9 KiB
Go
// Package cache provides abstraction of cache implementations that can be used by zitadel.
|
|
package cache
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/zitadel/logging"
|
|
)
|
|
|
|
// Purpose describes which object types are stored by a cache.
|
|
type Purpose int
|
|
|
|
//go:generate enumer -type Purpose -transform snake -trimprefix Purpose
|
|
const (
|
|
PurposeUnspecified Purpose = iota
|
|
PurposeAuthzInstance
|
|
PurposeMilestones
|
|
PurposeOrganization
|
|
PurposeIdPFormCallback
|
|
)
|
|
|
|
// Cache stores objects with a value of type `V`.
|
|
// Objects may be referred to by one or more indices.
|
|
// Implementations may encode the value for storage.
|
|
// This means non-exported fields may be lost and objects
|
|
// with function values may fail to encode.
|
|
// See https://pkg.go.dev/encoding/json#Marshal for example.
|
|
//
|
|
// `I` is the type by which indices are identified,
|
|
// typically an enum for type-safe access.
|
|
// Indices are defined when calling the constructor of an implementation of this interface.
|
|
// It is illegal to refer to an idex not defined during construction.
|
|
//
|
|
// `K` is the type used as key in each index.
|
|
// Due to the limitations in type constraints, all indices use the same key type.
|
|
//
|
|
// Implementations are free to use stricter type constraints or fixed typing.
|
|
type Cache[I, K comparable, V Entry[I, K]] interface {
|
|
// Get an object through specified index.
|
|
// An [IndexUnknownError] may be returned if the index is unknown.
|
|
// [ErrCacheMiss] is returned if the key was not found in the index,
|
|
// or the object is not valid.
|
|
Get(ctx context.Context, index I, key K) (V, bool)
|
|
|
|
// Set an object.
|
|
// Keys are created on each index based in the [Entry.Keys] method.
|
|
// If any key maps to an existing object, the object is invalidated,
|
|
// regardless if the object has other keys defined in the new entry.
|
|
// This to prevent ghost objects when an entry reduces the amount of keys
|
|
// for a given index.
|
|
Set(ctx context.Context, value V)
|
|
|
|
// Invalidate an object through specified index.
|
|
// Implementations may choose to instantly delete the object,
|
|
// defer until prune or a separate cleanup routine.
|
|
// Invalidated object are no longer returned from Get.
|
|
// It is safe to call Invalidate multiple times or on non-existing entries.
|
|
Invalidate(ctx context.Context, index I, key ...K) error
|
|
|
|
// Delete one or more keys from a specific index.
|
|
// An [IndexUnknownError] may be returned if the index is unknown.
|
|
// The referred object is not invalidated and may still be accessible though
|
|
// other indices and keys.
|
|
// It is safe to call Delete multiple times or on non-existing entries
|
|
Delete(ctx context.Context, index I, key ...K) error
|
|
|
|
// Truncate deletes all cached objects.
|
|
Truncate(ctx context.Context) error
|
|
}
|
|
|
|
// Entry contains a value of type `V` to be cached.
|
|
//
|
|
// `I` is the type by which indices are identified,
|
|
// typically an enum for type-safe access.
|
|
//
|
|
// `K` is the type used as key in an index.
|
|
// Due to the limitations in type constraints, all indices use the same key type.
|
|
type Entry[I, K comparable] interface {
|
|
// Keys returns which keys map to the object in a specified index.
|
|
// May return nil if the index in unknown or when there are no keys.
|
|
Keys(index I) (key []K)
|
|
}
|
|
|
|
type Connector int
|
|
|
|
//go:generate enumer -type Connector -transform snake -trimprefix Connector -linecomment -text
|
|
const (
|
|
// Empty line comment ensures empty string for unspecified value
|
|
ConnectorUnspecified Connector = iota //
|
|
ConnectorMemory
|
|
ConnectorPostgres
|
|
ConnectorRedis
|
|
)
|
|
|
|
type Config struct {
|
|
Connector Connector
|
|
|
|
// Age since an object was added to the cache,
|
|
// after which the object is considered invalid.
|
|
// 0 disables max age checks.
|
|
MaxAge time.Duration
|
|
|
|
// Age since last use (Get) of an object,
|
|
// after which the object is considered invalid.
|
|
// 0 disables last use age checks.
|
|
LastUseAge time.Duration
|
|
|
|
// Log allows logging of the specific cache.
|
|
// By default only errors are logged to stdout.
|
|
Log *logging.Config
|
|
}
|