Skip to content

Commit 94dec63

Browse files
committed
OIDC frontend: support Redis and session expiration
Support all storage backends from recent pyop. Add automatic expiration TTL for the different collections so that the session databases does not grow without bounds. TODO: add pyop version requirement once there is an official release.
1 parent ba86be2 commit 94dec63

File tree

3 files changed

+33
-12
lines changed

3 files changed

+33
-12
lines changed

doc/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -423,22 +423,22 @@ Connect Relying Parties (RPs). The default configuration file can be found
423423
[here](../example/plugins/frontends/openid_connect_frontend.yaml.example).
424424

425425
As opposed to the other plugins, this plugin is NOT stateless (due to the nature of OpenID Connect using any other
426-
flow than "Implicit Flow"). However, the frontend supports using a MongoDB instance as its backend storage, so as long
426+
flow than "Implicit Flow"). However, the frontend supports using a MongoDB or Redis instance as its backend storage, so as long
427427
that's reachable from all machines it should not be a problem.
428428

429429
The configuration parameters available:
430430
* `signing_key_path`: path to a RSA Private Key file (PKCS#1). MUST be configured.
431-
* `db_uri`: connection URI to MongoDB instance where the data will be persisted, if it's not specified all data will only
431+
* `db_uri`: connection URI to MongoDB or Redis instance where the data will be persisted, if it's not specified all data will only
432432
be stored in-memory (not suitable for production use).
433-
* `client_db_uri`: connection URI to MongoDB instance where the client data will be persistent, if it's not specified the clients list will be received from the `client_db_path`.
433+
* `client_db_uri`: connection URI to MongoDB or Redis instance where the client data will be persistent, if it's not specified the clients list will be received from the `client_db_path`.
434434
* `client_db_path`: path to a file containing the client database in json format. It will only be used if `client_db_uri` is not set. If `client_db_uri` and `client_db_path` are not set, clients will only be stored in-memory (not suitable for production use).
435435
* `sub_hash_salt`: salt which is hashed into the `sub` claim. If it's not specified, SATOSA will generate a random salt on each startup, which means that users will get new `sub` value after every restart.
436436
* `provider`: provider configuration information. MUST be configured, the following configuration are supported:
437437
* `response_types_supported` (default: `[id_token]`): list of all supported response types, see [Section 3 of OIDC Core](http://openid.net/specs/openid-connect-core-1_0.html#Authentication).
438438
* `subject_types_supported` (default: `[pairwise]`): list of all supported subject identifier types, see [Section 8 of OIDC Core](http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes)
439439
* `scopes_supported` (default: `[openid]`): list of all supported scopes, see [Section 5.4 of OIDC Core](http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims)
440440
* `client_registration_supported` (default: `No`): boolean whether [dynamic client registration is supported](https://openid.net/specs/openid-connect-registration-1_0.html).
441-
If dynamic client registration is not supported all clients must exist in the MongoDB instance configured by the `db_uri` in the `"clients"` collection of the `"satosa"` database.
441+
If dynamic client registration is not supported all clients must exist in the MongoDB or Redis instance configured by the `db_uri` in the `"clients"` collection of the `"satosa"` database.
442442
The registration info must be stored using the client id as a key, and use the parameter names of a [OIDC Registration Response](https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationResponse).
443443
* `authorization_code_lifetime`: how long authorization codes should be valid, see [default](https://github.com/SUNET/pyop#token-lifetimes)
444444
* `access_token_lifetime`: how long access tokens should be valid, see [default](https://github.com/SUNET/pyop#token-lifetimes)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
packages=find_packages('src/'),
1616
package_dir={'': 'src'},
1717
install_requires=[
18-
"pyop >= 3.0.1",
18+
"pyop >= 3.0.1", # TODO
1919
"pysaml2 >= 6.5.1",
2020
"pycryptodomex",
2121
"requests",

src/satosa/frontends/openid_connect.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from pyop.exceptions import (InvalidAuthenticationRequest, InvalidClientRegistrationRequest,
1717
InvalidClientAuthentication, OAuthError, BearerTokenError, InvalidAccessToken)
1818
from pyop.provider import Provider
19-
from pyop.storage import MongoWrapper
19+
from pyop.storage import StorageBase
2020
from pyop.subject_identifier import HashBasedSubjectIdentifierFactory
2121
from pyop.userinfo import Userinfo
2222
from pyop.util import should_fragment_encode
@@ -80,13 +80,22 @@ def _create_provider(self, endpoint_baseurl):
8080
client_db_uri = self.config.get("client_db_uri")
8181
cdb_file = self.config.get("client_db_path")
8282
if client_db_uri:
83-
cdb = MongoWrapper(client_db_uri, "satosa", "clients")
83+
cdb = StorageBase.from_uri(
84+
client_db_uri, db_name="satosa", collection="clients"
85+
)
8486
elif cdb_file:
8587
with open(cdb_file) as f:
8688
cdb = json.loads(f.read())
8789
else:
8890
cdb = {}
89-
self.user_db = MongoWrapper(db_uri, "satosa", "authz_codes") if db_uri else {}
91+
92+
self.user_db = (
93+
StorageBase.from_uri(db_uri, db_name="satosa", collection="authz_codes")
94+
if db_uri
95+
else {}
96+
)
97+
#XXX What is the correct ttl for user_db? Is it the same as authz_code_db?
98+
9099
self.provider = Provider(
91100
self.signing_key,
92101
capabilities,
@@ -101,10 +110,22 @@ def _init_authorization_state(self):
101110
sub_hash_salt = self.config.get("sub_hash_salt", rndstr(16))
102111
db_uri = self.config.get("db_uri")
103112
if db_uri:
104-
authz_code_db = MongoWrapper(db_uri, "satosa", "authz_codes")
105-
access_token_db = MongoWrapper(db_uri, "satosa", "access_tokens")
106-
refresh_token_db = MongoWrapper(db_uri, "satosa", "refresh_tokens")
107-
sub_db = MongoWrapper(db_uri, "satosa", "subject_identifiers")
113+
authz_code_db = StorageBase.from_uri(
114+
db_uri, db_name="satosa", collection="authz_codes",
115+
)
116+
authz_code_db.ttl = self.config["provider"].get("authorization_code_lifetime", 600)
117+
access_token_db = StorageBase.from_uri(
118+
db_uri, db_name="satosa", collection="access_tokens"
119+
)
120+
access_token_db.ttl = self.config["provider"].get("access_token_lifetime", 3600)
121+
refresh_token_db = StorageBase.from_uri(
122+
db_uri, db_name="satosa", collection="refresh_tokens"
123+
)
124+
refresh_token_db.ttl = self.config["provider"].get("refresh_token_lifetime", None)
125+
sub_db = StorageBase.from_uri(
126+
db_uri, db_name="satosa", collection="subject_identifiers"
127+
)
128+
#XXX what is the correct TTL for sub_db?
108129
else:
109130
authz_code_db = None
110131
access_token_db = None

0 commit comments

Comments
 (0)