The Kong Session Plugin can be used to manage browser sessions for APIs proxied through the Kong API Gateway. It provides configuration and management for session data storage, encryption, renewal, expiry, and sending browser cookies. It is built using lua-resty-session.
For information about configuring and using the Sessions plugin with the Dev Portal, see Sessions in the Dev Portal.
Configuration Reference
This plugin is partially compatible with DB-less mode.
In DB-less mode, you configure Kong Gateway declaratively. Therefore, the Admin API is mostly read-only. The only tasks it can perform are all related to handling the declarative config, including:
- Setting a target's health status in the load balancer
- Validating configurations against schemas
- Uploading the declarative configuration using the
/config
endpoint
config.storage
must be set to cookie
. The kong
strategy uses
a database, and is not supported. The plugin currently lacks checks
for this invalid configuration in DB-less mode.
Example plugin configuration
Parameters
Here's a list of all the parameters which can be used in this plugin's configuration:
Form Parameter | Description |
---|---|
name
required Type: string |
The name of the plugin, in this case session . |
service.name or service.id
Type: string |
The name or ID of the service the plugin targets.
Set one of these parameters if adding the plugin to a service through the top-level /plugins endpoint.
Not required if using /services/SERVICE_NAME|SERVICE_ID/plugins . |
route.name or route.id
Type: string |
The name or ID of the route the plugin targets.
Set one of these parameters if adding the plugin to a route through the top-level /plugins endpoint.
Not required if using /routes/ROUTE_NAME|ROUTE_ID/plugins . |
enabled
Type: boolean Default value: true |
Whether this plugin will be applied. |
config.secret
optional Type: string Default value: random number generated from kong.utils.random_string
|
The secret that is used in keyed HMAC generation. If keyring database encryption is enabled, this value will be encrypted. This field is referenceable, which means it can be securely stored as a secret in a vault. References must follow a specific format. |
config.cookie_name
optional Type: string Default value: session
|
The name of the cookie. |
config.cookie_lifetime
optional Type: number Default value: 3600
|
The duration in seconds that the session will remain open. |
config.cookie_idletime
optional Type: number |
The cookie idle time (in seconds); if a cookie is not used for this time period, the session becomes invalid. This value is not set by default, meaning idle time checks are disabled. |
config.cookie_renew
optional Type: number Default value: 600
|
The remaining duration in seconds of a session at which point the Plugin renews the session. |
config.cookie_path
optional Type: string Default value: /
|
The resource in the host where the cookie is available. |
config.cookie_domain
optional Type: string Default value: Set using Nginx variable host, but may be overridden
|
The domain with which the cookie is intended to be exchanged. |
config.cookie_samesite
optional Type: string Default value: Strict
|
Determines whether and how a cookie may be sent with cross-site requests. |
config.cookie_httponly
optional Type: boolean Default value: true
|
Applies the |
config.cookie_secure
optional Type: boolean Default value: true
|
Applies the Secure directive so that the cookie may be sent to the server only with an encrypted request over the HTTPS protocol. See the Restrict access to cookies docs on MDN. |
config.cookie_discard
optional Type: number Default value: 10
|
The duration in seconds after which an old session’s TTL is updated that an old cookie is discarded. |
config.cookie_persistent
optional Type: boolean Default value: false
|
Allows the browser to persist cookies even if the browser is closed. By default, cookies are not persisted across browser restarts. |
config.storage
optional Type: string Default value: cookie
|
Determines where the session data is stored. |
config.logout_methods
optional Type: array of string elements Default value: ["POST", "DELETE"]
|
The methods that may be used to end sessions: POST, DELETE, GET. |
config.logout_query_arg
optional Type: string Default value: session_logout
|
The query argument passed to logout requests. |
config.logout_post_arg
optional Type: string Default value: session_logout
|
The POST argument passed to logout requests. Do not change this property. |
Usage
The Kong Session plugin can be configured globally or with an entity (e.g., Service, Route) and is always used in conjunction with another Kong Authentication Plugin. This plugin is intended to work similarly to the multiple authentication setup.
After the Kong Session plugin is enabled in conjunction with an Authentication plugin, it runs prior to the credential verification. If no session is found, then the authentication plugin runs again and credentials are checked normally. If the credential verification is successful, then the Session plugin creates a new session for usage with subsequent requests.
When a new request comes in and a session is already present, then the Kong Session
plugin attaches the ngx.ctx
variables to let the authentication
plugin know that authentication has already occurred via session validation.
As this configuration is a logical OR scenario, and it’s desired that anonymous
access be forbidden, you should configure the Request Termination plugin on an anonymous consumer. Failure to do so allows unauthorized
requests. For more information, see multiple authentication.
Set up With a Database
For usage with Key Auth plugin
-
Create an example Service and a Route
Issue the following cURL request to create
example-service
pointing to mockbin.org, which echoes the request:curl -i -X POST \ --url http://localhost:8001/services/ \ --data 'name=example-service' \ --data 'url=http://mockbin.org/request'
Add a route to the Service:
curl -i -X POST \ --url http://localhost:8001/services/example-service/routes \ --data 'paths[]=/sessions-test'
The URL
http://localhost:8000/sessions-test
now echoes whatever is being requested. -
Configure the key-auth plugin for the Service
Issue the following cURL request to add the key-auth plugin to the Service:
curl -i -X POST \ --url http://localhost:8001/services/example-service/plugins/ \ --data 'name=key-auth'
Be sure to note the created plugin
id
, which is needed later. -
Verify that the key-auth plugin is properly configured
Issue the following cURL request to verify that the [key-auth][key-auth] plugin is properly configured on the Service:
curl -i -X GET \ --url http://localhost:8000/sessions-test
Since the required header or parameter
apikey
is not specified, and anonymous access is not yet enabled, the response should be401 Unauthorized
. -
Create a Consumer and an anonymous Consumer
Every request proxied and authenticated by Kong must be associated with a Consumer. You can now create a Consumer named
anonymous_users
by issuing the following request:curl -i -X POST \ --url http://localhost:8001/consumers/ \ --data "username=anonymous_users"
Be sure to note the Consumer
id
, which is needed later.Now create a consumer that authenticates via sessions:
curl -i -X POST \ --url http://localhost:8001/consumers/ \ --data "username=fiona"
-
Provision
key-auth
credentials for your Consumercurl -i -X POST \ --url http://localhost:8001/consumers/fiona/key-auth/ \ --data 'key=open_sesame'
-
Enable anonymous access
You can now re-configure the key-auth plugin to permit anonymous access by issuing the following request (replace the UUIDs below with the
id
value from previous steps):curl -i -X PATCH \ --url http://localhost:8001/plugins/<your-key-auth-plugin-id> \ --data "config.anonymous=<anonymous_consumer_id>"
-
Add the Kong Session plugin to the service
curl -X POST http://localhost:8001/services/example-service/plugins \ --data "name=session" \ --data "config.storage=kong" \ --data "config.cookie_secure=false"
Note: cookie_secure is true by default, and should always be true, but is set to false for the sake of this demo to avoid using HTTPS.
-
Add the Request Termination plugin
To disable anonymous access to only allow users access via sessions or via authentication credentials, enable the Request Termination plugin.
curl -X POST http://localhost:8001/services/example-service/plugins \ --data "name=request-termination" \ --data "config.status_code=403" \ --data "config.message=So long and thanks for all the fish!" \ --data "consumer.id=<anonymous_consumer_id>"
Set up Without a Database
Add all these to the declarative config file:
services:
- name: example-service
url: http://mockbin.org/request
routes:
- service: example-service
paths: ['/sessions-test']
consumers:
- username: anonymous_users
# manually set to fixed uuid in order to use it in key-auth plugin
id: 81823632-10c0-4098-a4f7-31062520c1e6
- username: fiona
keyauth_credentials:
- consumer: fiona
key: open_sesame
plugins:
- name: key-auth
service: example-service
config:
# using the anonymous consumer fixed uuid (can't use the username)
anonymous: 81823632-10c0-4098-a4f7-31062520c1e6
# cookie_secure is true by default, and should always be true,
# but is set to false for the sake of this demo in order to avoid using HTTPS.
cookie_secure: false
- name: session
config:
storage: kong
cookie_secure: false
- name: request-termination
service: example-service
consumer: anonymous_users
config:
status_code: 403
message: 'So long and thanks for all the fish!'
Verification
-
Check that Anonymous requests are disabled:
curl -i -X GET \ --url http://localhost:8000/sessions-test
Should return
403
. -
Verify that a user can authenticate via sessions
curl -i -X GET \ --url http://localhost:8000/sessions-test?apikey=open_sesame
The response should now have the
Set-Cookie
header. Make sure that this cookie works.If cookie looks like this:
Set-Cookie: session=emjbJ3MdyDsoDUkqmemFqw..|1544654411|4QMKAE3I-jFSgmvjWApDRmZHMB8.; Path=/; SameSite=Strict; HttpOnly
Use it like this:
curl -i -X GET \ --url http://localhost:8000/sessions-test \ -H "cookie:session=emjbJ3MdyDsoDUkqmemFqw..|1544654411|4QMKAE3I-jFSgmvjWApDRmZHMB8."
This request should succeed and the
Set-Cookie
response header does not appear until the renewal period. -
Navigate to
http://localhost:8000/sessions-test
If the cookie is attached to the browser session, it should return the code
403
and the message “So long and thanks for all the fish!”. -
Navigate to
http://localhost:8000/sessions-test?apikey=open_sesame
It should return
200
and authenticated viakey-auth
key query parameter. -
Navigate to
http://localhost:8000/sessions-test
It can now use the session cookie that is granted by the Session plugin.
Defaults
By default, the Kong Session plugin favors security using a Secure
, HTTPOnly
,
Samesite=Strict
cookie. cookie_domain
is automatically set using Nginx
variable host, but can be overridden.
Session Data Storage
The session data can be stored in the cookie itself (encrypted) storage=cookie
,
or inside Kong. The session data stores these context
variables:
ngx.ctx.authenticated_consumer.id
ngx.ctx.authenticated_credential.id
ngx.ctx.authenticated_groups
The plugin also sets a ngx.ctx.authenticated_session
for communication between
the access
and header_filter
phases in the plugin.
Groups
Authenticated groups are stored on ngx.ctx.authenticated_groups
from other
authentication plugins and the session plugin will store them in the data of
the current session. Since the session plugin runs before authentication
plugins, it also sets authenticated_groups
associated headers.
Kong Storage Adapter
The Session plugin extends the functionality of lua-resty-session with its own
session data storage adapter when storage=kong
. This stores encrypted
session data into the current database strategy and the cookie does not contain
any session data. Data stored in the database is encrypted and the cookie contains only
the session id, expiration time, and HMAC signature. Sessions use the built-in Kong
DAO ttl
mechanism that destroys sessions after specified cookie_lifetime
unless renewal
occurs during normal browser activity. Log out the application via XHR request
(or something similar) to manually handle the redirects.
Logging Out
It is typical to provide users the ability to log out (i.e., to manually destroy) their
current session. Logging out is possible with either query parameters or POST
parameters in
the request URL. The config’s logout_methods
allows the plugin to limit logging
out based on the HTTP verb. When logout_query_arg
is set, it checks the
presence of the URL query parameter specified, and likewise when logout_post_arg
is set, it checks the presence of the specified variable in the request body.
Allowed HTTP verbs are GET
, DELETE
, and POST
. When there is a session
present and the incoming request is a logout request, the Kong Session plugin
returns a 200 before continuing in the plugin run loop, and the request does not
continue to the upstream.
Known Limitations
Due to limitations of OpenResty, the header_filter
phase cannot connect to the
database, which poses a problem for initial retrieval of a cookie (fresh session).
There is a small window of time where the cookie is sent to client, but the database
insert has not been committed yet because the database call is in a ngx.timer
thread.
The current workaround is to wait for some interval of time (~100-500ms) after
Set-Cookie
header is sent to the client before making subsequent requests. This is
not a problem during session renewal period as renew happens in access
phase.
Changelog
Kong Gateway 3.1.x
- Added the new configuration parameter
cookie_persistent
, which allows the browser to persist cookies even if the browser is closed. This defaults tofalse
, which means cookies are not persisted across browser restarts.
Kong Gateway 2.7.x
- Starting with Kong Gateway 2.7.0.0, if keyring encryption is enabled,
the
config.secret
parameter value will be encrypted.