Skip to main content

Gate: Plugin - HttpOnly cookies

This plugin adds support for HTTP-only cookie-based authentication.

With this plugin, your multi-page application can delegate authentication to Gate and protect against client-side token exfiltration attacks.

caution

Cookies are limited to 4 kB in size. When over the limit, browsers ignore Set-Cookie instructions. This may result in failed sign in attempts by your users.

At the moment, Gate does not monitor the size of the cookie.

Example usage

Please see API authentication at the edge.

Customer InfrastructureUserGateWeb ApplicationSlashID(1)Serves the sign-in page.(2)Submit credentials (using our JS SDK).(3)SlashID JWT.(4)PUT /httpOnlysHeaders:Authorization: Bearer <SlashID JWT>Gate requires authentication for this endpoint.This is afetchrequest, so that the JWT comes in theAuthorizationheader.(5)Forward the request as theJWT is valid.Headers:SlashID-HTTPOnly-New: {"id":"...", "payload":"..."}(6)HTTP 307Headers:Location: /dashboardSlashID-HTTPOnly-Control: create(7)Remove headerSlashID-HTTPOnly-ControlAdd headerSet-Cookie: _slashid-httpOnlys="..."; Secure; SameSite=Lax; HttpOnly; ...Forward the response.Cookie_slashid-httpOnlyskeeps an array of httpOnlys.Gate created a httpOnly. The user is now signed in.(8)GET /dashboardHeaders:Cookie: ...; _sid-gate-httpOnly=<value>The cookie is encrypted with AES256-GCM, guaranteeingits confidentiality and integrity.(9)Forward the request as the httpOnly cookie is valid.Headers:SlashID-HTTPOnlys: [<ID, JWT>](10)...(11)...(12)DELETE /sign-outHeaders:Cookie: ...; _slashid-httpOnlys=...(13)Forward the request as the httpOnly cookie is valid.Headers:SlashID-HTTPOnlys: [<ID, JWT>](14)HTTP 307Headers:Location: /sign-inSlashID-HTTPOnly-Control: destroy <httpOnly ID>All httpOnlys are destroyed when an ID isn't specified.(15)Remove headerSlashID-HTTPOnly-ControlAdd headerSet-Cookie: _slashid-httpOnlys=; Max-Age=0(delete the cookie)Forward the response.Gate destroyed the httpOnly. The user is now signed out.

Configuring Gate

GATE_PLUGINS_<PLUGIN NUMBER>_TYPE=httpOnly-proxy
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_SLASHID_ORG_ID=<SlashID Org ID>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_SLASHID_API_KEY=<SlashID API key>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_SLASHID_BASE_URL=<SlashID base URL>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_CAN_CREATE_HTTP_ONLY=<Can create a new HTTP-only entry?>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_ALLOW_UNAUTHENTICATED_REQUESTS=<Allow unauthenticated requests?>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_FAILED_AUTHENTICATION_ENDPOINT="<Redirect client to this endpoint when authentication failed>"
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_SECRET_KEY_BASE="<Secret key base>"
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_COOKIE_NAME="<HTTP-Only cookie name>"
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_REQUIRED_GROUPS=<Required SlashID groups list>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_MAX_GROUPS_INFO_AGE=<Max groups info age>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_ONLINE_TOKENS_VALIDATION=<Validate tokens with SlashID servers>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_ONLINE_TOKENS_VALIDATION_TIMEOUT=<Validate tokens with SlashID servers timeout>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_JWKS_URL=<Custom JSON Web Key Sets URL>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_JWKS_REFRESH_INTERVAL=<JSON Web Key Sets refresh interval>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_JWT_EXPECTED_ISSUER=<JWT expected issuer>

In the Environment variables configuration, <PLUGIN NUMBER> defined plugin execution order.

where:

  • <SlashID Org ID> your SlashID organization ID
  • <SlashID base URL> base URL of SlashID servers. By default, https://api.slashid.com.
  • <Required SlashID groups list> list of groups required to access the endpoint. By default, empty (no groups required). If multiple groups are provided, all of them are required. In environment variables multiple roles should be separated by a comma. For example: user,admin. In HCL, JSON, TOML and YAML multiple roles should be provided as a list. For example: ["user", "admin"].
  • <Can create a new HTTP-only entry?> if enabled, the URL is allowed to create new HTTP-only entries.
  • <Allow unauthenticated requests?> if enabled, the URL is allowed to receive unauthenticated requests. It will still receive existing HTTP-only entries. This is useful for pages like your sign-in page: it must not prompt the user for authentication when they're authenticated.
  • <Redirect client to this endpoint when authentication failed> if the URL requires authentication but there no HTTP-only entries in the ruquest.
  • <Secret base key> a 64-char long hex encoded string that must be generated using a cryptographically-strong number generator. This key is used to derive per-message keys that are used to encrypt the HTTP-only entries contained in the cookie.
  • <HTTP-only cookie name> the name of the cookie containing HTTP-only entries.
  • <Max groups info age> maximum age of groups information. If groups are present in JWT or in cache, but their information is older than this value, Gate will fetch the latest information from SlashID servers. Age should have format 1h, 1m, 1s or 1ms. You can combine multiple units, for example: 1h30m. If not provided, groups information will be fetched from SlashID servers on every request.
  • <Validate tokens with SlashID servers> if enabled, JWT tokens will be validated with SlashID servers for each request. It will introduce a slight latency overhead for each request, but it guarantees data freshness and accounts for activity on the identity object (disabled account, groups and roles changes and similar). To help to measure the impact of this option on your request, we recommend checking the Gate Monitoring guide. If disabled, Gate verifies the JWT signature and expiration without making any external call. true by default.
  • <Validate tokens with SlashID servers timeout> timeout for validating tokens with SlashID servers. By default, 5s. If the timeout is reached, the request will be rejected with 502 Bad Gateway status code.
  • <Custom JSON Web Key Sets URL> URL of key sets used for offline token validation. By default, SlashID key sets are used.
  • <JSON Web Key Sets refresh interval> interval for refreshing key sets used for offline token validation. By default, 15m.
  • <JWT expected issuer> expected issuer of the JWT token. By default, https://api.slashid.com.

To learn more about configuring Gate, please visit configuration page and plugins section.

info

The order of plugins in configuration determines their execution order.

Disabling plugin for specific URLs

You can enable or disable this plugin for specific URLs by using the enabled option in the URLs configuration.

GATE_URLS_0_PATTERN=svc-example.com/*
GATE_URLS_0_TARGET=http://example:8080

GATE_URLS_1_PATTERN=svc-another-example.com/
GATE_URLS_1_TARGET=https://another-example:8080

Here's an example:

gate = {
log = {
format = "text"
level = "trace"
}

default = {
target = "https://example.com"
}

plugins = [
{
enabled = false
type = "httpOnly-proxy"
id = "HTTPONLY_PROXY"
parameters = {
slashid_org_id = "00000000-0000-0000-0000-000000000000"
slashid_base_url = "https://api.slashid.com"
failed_authentication_endpoint = "/failed-auth"
secret_key_base = "0000000000000000000000000000000000000000000000000000000000000000"
jwks_url = "https://api.slashid.com/.well-known/jwks.json"
jwks_refresh_interval = "3600s"
jwt_expected_issuer = "123"
online_tokens_validation_timeout = "3600s"
}
}
]

urls = [
{
pattern = "service.internal/create-httponly"
target = "https://example.com"
plugins = {
"HTTPONLY_PROXY" = {
enabled = true
parameters = {
can_create_httpOnly = true
}
}
}
},
{
pattern = "service.internal/sign-in"
target = "https://example.com"
plugins = {
"HTTPONLY_PROXY" = {
enabled = true
parameters = {
allow_unauthenticated_requests = true
}
}
}
},
{
pattern = "service.internal/private-page"
target = "https://example.com"
plugins = {
"HTTPONLY_PROXY" = {
enabled = true
parameters = {
allow_unauthenticated_requests = false
}
}
}
},
{
pattern = "service.internal/sign-out"
target = "https://example.com"
plugins = {
"HTTPONLY_PROXY" = {
enabled = true
parameters = {
allow_unauthenticated_requests = false
}
}
}
}
]
}