Session Management
About session management
The OIDC Session Management draft defines session to be:
Continuous period of time during which an End-User accesses a Relying Party relying on the Authentication of the End-User performed by the OpenID Provider.
Note that we are dealing with a Single Sign On (SSO) context here. If for some reason the OP does not want to support SSO then the session management has to be done a bit differently. In that case each session (user_id,client_id) would have its own authentication event. Not one shared between the sessions.
Design criteria
So a session is defined by a user and a Relying Party. If one adds to that that a user can have several sessions active at the same time each one against a unique Relying Party we have the bases for session management.
Furthermore the user may well decide on different rules for different relying parties for releasing user attributes, where and how issued access tokens could be used and whether refresh tokens should be issued or not.
We also need to keep track on which tokens where used to mint new tokens such that we can easily revoked a suite of tokens all with a common ancestor.
Database layout
The database is organized in 3 levels. The top one being the users. Below that the Relying Parties and at the bottom what is called grants.
Grants organize authorization codes, access tokens and refresh tokens (and possibly other types of tokens) in a comprehensive way. More about that below.
There may be many Relying Parties below a user and many grants below a Relying Party.
The information structure
As stated above there are 3 layers: user session information, client session information and grants. But first the keys to the information.
Session key
A key to the session information is based on a list. The first item being the user identifier, the second the client identifier and the third the grant identifier. If you only want the user session information then the key is a list with one item the user id. If you want the client session information the key is a list with 2 items (user_id, client_id). And lastly if you want a grant then the key is a list with 3 elements (user_id, client_id, grant_id).
- Example::
“diana;;KtEST70jZx1x;;85544c9cace411ebab53559c5425fcc0”
A session identifier is constructed using the session_key function. It takes as input the 3 elements list.:
session_id = session_key(user_id, client_id, grant_id)
Using the function unpack_session_key you can get the elements from a session_id.:
user_id, client_id, grant_id = unpack_session_id(session_id)
User session information
Houses the authentication event information which is the same for all session connected to a user. Here we also have a list of all the clients that this user has a session with. Expressed as a dictionary this can look like this:
{
'authentication_event': {
'uid': 'diana',
'authn_info': "urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocolPassword",
'authn_time': 1605515787,
'valid_until': 1605519387
},
'subordinate': ['client_1']
}
Client session information
The client specific information of the session information. Presently only the authorization request and the subject identifier (sub). The subordinates to this set of information are the grants:
{
'authorization_request':{
'client_id': 'client_1',
'redirect_uri': 'https://example.com/cb',
'scope': ['openid', 'research_and_scholarship'],
'state': 'STATE',
'response_type': ['code']
},
'sub': '117afe8d7bb0ace8e7fb2706034ab2d3fbf17f0fd4c949aa9c23aedd051cc9e3',
'subordinate': ['e996c61227e711eba173acde48001122'],
'revoked': False
}
Grant information
Grants are created by an authorization subsystem in an OP. If the grant is created in connection with an user authentication the authorization system might normally ask the user for usage consent and then base the construction of the grant on that consent.
If an authorization server can act as a Security Token Service (STS) as defined by Token Exchange [RFC-8693] then no user is involved. In the context of session management the STS is equivalent to a user.
Grant information contains information about user consent and issued tokens.:
{
"type": "grant",
"scope": ["openid", "research_and_scholarship"],
"authorization_details": null,
"claims": {
"userinfo": {
"sub": null,
"name": null,
"given_name": null,
"family_name": null,
"email": null,
"email_verified": null,
"eduperson_scoped_affiliation": null
}
},
"resources": ["client_1"],
"issued_at": 1605452123,
"not_before": 0,
"expires_at": 0,
"revoked": false,
"issued_token": [
{
"type": "authorization_code",
"issued_at": 1605452123,
"not_before": 0,
"expires_at": 1605452423,
"revoked": false,
"value": "Z0FBQUFBQmZzVUZieDFWZy1fbjE2ckxvZkFTVC1ZTHJIVlk0Z09tOVk1M0RsOVNDbkdfLTIxTUhILWs4T29kM1lmV015UEN1UGxrWkxLTkVXOEg1WVJLNjh3MGlhMVdSRWhYcUY4cGdBQkJEbzJUWUQ3UGxTUWlJVDNFUHFlb29PWUFKcjNXeHdRM1hDYzRIZnFrYjhVZnIyTFhvZ2Y0NUhjR1VBdzE0STVEWmJ3WkttTk1OYXQtTHNtdHJwYk1nWnl3MUJqSkdWZGFtdVNfY21VNXQxY3VzalpIczBWbGFueVk0TVZ2N2d2d0hVWTF4WG56TDJ6bz0=",
"usage_rules": {
"expires_in": 300,
"supports_minting": [
"access_token",
"refresh_token",
"id_token"
],
"max_usage": 1
},
"used": 0,
"based_on": null,
"id": "96d19bea275211eba43bacde48001122"
},
{
"type": "access_token",
"issued_at": 1605452123,
"not_before": 0,
"expires_at": 1605452723,
"revoked": false,
"value": "Z0FBQUFBQmZzVUZiaWVRbi1IS2k0VW4wVDY1ZmJHeEVCR1hVODBaQXR6MWkzelNBRFpOS2tRM3p4WWY5Y1J6dk5IWWpnelRETGVpSG52b0d4RGhjOWphdWp4eW5xZEJwQzliaS16cXFCcmRFbVJqUldsR1Z3SHdTVVlWbkpHak54TmJaSTV2T3NEQ0Y1WFkxQkFyamZHbmd4V0RHQ3k1MVczYlYwakEyM010SGoyZk9tUVVxbWdYUzBvMmRRNVlZMUhRSnM4WFd2QzRkVmtWNVJ1aVdJSXQyWnpVTlRiZnMtcVhKTklGdzBzdDJ3RkRnc1A1UEw2Yz0=",
"usage_rules": {
"expires_in": 600,
},
"used": 0,
"based_on": "Z0FBQUFBQmZzVUZieDFWZy1fbjE2ckxvZkFTVC1ZTHJIVlk0Z09tOVk1M0RsOVNDbkdfLTIxTUhILWs4T29kM1lmV015UEN1UGxrWkxLTkVXOEg1WVJLNjh3MGlhMVdSRWhYcUY4cGdBQkJEbzJUWUQ3UGxTUWlJVDNFUHFlb29PWUFKcjNXeHdRM1hDYzRIZnFrYjhVZnIyTFhvZ2Y0NUhjR1VBdzE0STVEWmJ3WkttTk1OYXQtTHNtdHJwYk1nWnl3MUJqSkdWZGFtdVNfY21VNXQxY3VzalpIczBWbGFueVk0TVZ2N2d2d0hVWTF4WG56TDJ6bz0=",
"id": "96d1c840275211eba43bacde48001122"
}
],
"id": "96d16d3c275211eba43bacde48001122"
}
The parameters are described below
scope
This is the scope that was chosen for this grant. Either by the user or by some rules that the Authorization Server runs by.
claims
The set of claims that should be returned in different circumstances. The syntax that is defined in https://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter is used. With one addition, beside userinfo and id_token we have added introspection.
resources
This are the resource servers and other entities that should be accepted as users of issued access tokens.
issued_at
When the grant was created. Its value is a JSON number representing the number of seconds from 1970-01-01T0:0:0Z as measured in UTC until the date/time.
not_before
If the usage of the grant should be delay, this is when it can start being used. Its value is a JSON number representing the number of seconds from 1970-01-01T0:0:0Z as measured in UTC until the date/time.
expires_at
When the grant expires. Its value is a JSON number representing the number of seconds from 1970-01-01T0:0:0Z as measured in UTC until the date/time.
revoked
If the grant has been revoked.
issued_token
Tokens that has been issued based on this grant. There is no limitation as to which tokens can be issued. Though presently we only have:
authorization_code,
access_token and
refresh_token
id
The grant identifier.
Token
As mention above there are presently only 3 token types that are defined:
authorization_code,
access_token and
refresh_token
A token is described as follows:
{
"type": "authorization_code",
"issued_at": 1605452123,
"not_before": 0,
"expires_at": 1605452423,
"revoked": false,
"value": "Z0FBQUFBQmZzVUZieDFWZy1fbjE2ckxvZkFTVC1ZTHJIVlk0Z09tOVk1M0RsOVNDbkdfLTIxTUhILWs4T29kM1lmV015UEN1UGxrWkxLTkVXOEg1WVJLNjh3MGlhMVdSRWhYcUY4cGdBQkJEbzJUWUQ3UGxTUWlJVDNFUHFlb29PWUFKcjNXeHdRM1hDYzRIZnFrYjhVZnIyTFhvZ2Y0NUhjR1VBdzE0STVEWmJ3WkttTk1OYXQtTHNtdHJwYk1nWnl3MUJqSkdWZGFtdVNfY21VNXQxY3VzalpIczBWbGFueVk0TVZ2N2d2d0hVWTF4WG56TDJ6bz0=",
"usage_rules": {
"expires_in": 300,
"supports_minting": [
"access_token",
"refresh_token",
"id_token"
],
"max_usage": 1
},
"used": 0,
"based_on": null,
"id": "96d19bea275211eba43bacde48001122"
}
type
The type of token.
issued_at
When the token was created. Its value is a JSON number representing the number of seconds from 1970-01-01T0:0:0Z as measured in UTC until the date/time.
not_before
If the start of the usage of the token is to be delay, this is until when. Its value is a JSON number representing the number of seconds from 1970-01-01T0:0:0Z as measured in UTC until the date/time.
expires_at
When the token expires. Its value is a JSON number representing the number of seconds from 1970-01-01T0:0:0Z as measured in UTC until the date/time.
revoked
If the token has been revoked.
value
This is the value that appears in OIDC protocol exchanges.
usage_rules
Rules as to how this token can be used:
- expires_in
Used to calculate expires_at
- supports_minting
The tokens types that can be minted based on this token. Typically a code can be used to mint ID tokens and access and refresh tokens.
- max_usage
How many times this token can be used (being used is presently defined as used to mint other tokens). An authorization_code token can according to the OIDC standard only be used once but then to, in the same session, mint more then one token.
used
How many times the token has been used
based_on
Reference to the token that was used to mint this token. Might be empty if the token was minted based on the grant it belongs to.
id
Token identifier
Session Info API
add_subordinate
…
remove_subordinate
…
revoke
…
is_revoked
…
to_json
…
from_json
…
Grant API
…
Token API
…
Session Manager API
…
create_session
Creating a new session is done by running the create_session method of the class SessionManager. The create_session methods takes the following arguments.
- authn_event
An AuthnEvent class instance that describes the authentication event.
- auth_req
The Authentication request
- client_id
The client Identifier
- user_id
The user identifier
- sector_identifier
A possible sector identifier to be used when constructing a pairwise subject identifier
- sub_type
The type of subject identifier that should be constructed. It can either be pairwise or public.
So a typical command would look like this:
authn_event = create_authn_event(self.user_id)
session_manager.create_session(authn_event=authn_event, auth_req=auth_req,
user_id=self.user_id, client_id=client_id,
sub_type=sub_type, sector_identifier=sector_identifier)
add_grant
add_grant(self, user_id, client_id, **kwargs)
find_token
find_token(self, session_id, token_value)
get_authentication_event
get_authentication_event(self, session_id)
get_client_session_info
get_client_session_info(self, session_id)
get_grant_by_response_type
get_grant_by_response_type(self, user_id, client_id)
get_session_info
get_session_info(self, session_id)
get_session_info_by_token
get_session_info_by_token(self, token_value)
get_sids_by_user_id
get_sids_by_user_id(self, user_id)
get_user_info
get_user_info(self, uid)
grants
grants(self, session_id)
revoke_client_session
revoke_client_session(self, session_id)
revoke_grant
revoke_grant(self, session_id)
revoke_token
revoke_token(self, session_id, token_value, recursive=False)