Skip to content

OIDC frontend: support Redis and session expiration #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions doc/README.md
Original file line number Diff line number Diff line change
@@ -423,22 +423,22 @@ Connect Relying Parties (RPs). The default configuration file can be found
[here](../example/plugins/frontends/openid_connect_frontend.yaml.example).

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

The configuration parameters available:
* `signing_key_path`: path to a RSA Private Key file (PKCS#1). MUST be configured.
* `db_uri`: connection URI to MongoDB instance where the data will be persisted, if it's not specified all data will only
* `db_uri`: connection URI to MongoDB or Redis instance where the data will be persisted, if it's not specified all data will only
be stored in-memory (not suitable for production use).
* `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`.
* `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`.
* `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).
* `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.
* `provider`: provider configuration information. MUST be configured, the following configuration are supported:
* `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).
* `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)
* `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)
* `client_registration_supported` (default: `No`): boolean whether [dynamic client registration is supported](https://openid.net/specs/openid-connect-registration-1_0.html).
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.
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.
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).
* `authorization_code_lifetime`: how long authorization codes should be valid, see [default](https://github.com/SUNET/pyop#token-lifetimes)
* `access_token_lifetime`: how long access tokens should be valid, see [default](https://github.com/SUNET/pyop#token-lifetimes)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
packages=find_packages('src/'),
package_dir={'': 'src'},
install_requires=[
"pyop >= 3.0.1",
"pyop >= 3.0.1", # TODO
"pysaml2 >= 6.5.1",
"pycryptodomex",
"requests",
35 changes: 28 additions & 7 deletions src/satosa/frontends/openid_connect.py
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
from pyop.exceptions import (InvalidAuthenticationRequest, InvalidClientRegistrationRequest,
InvalidClientAuthentication, OAuthError, BearerTokenError, InvalidAccessToken)
from pyop.provider import Provider
from pyop.storage import MongoWrapper
from pyop.storage import StorageBase
from pyop.subject_identifier import HashBasedSubjectIdentifierFactory
from pyop.userinfo import Userinfo
from pyop.util import should_fragment_encode
@@ -80,13 +80,22 @@ def _create_provider(self, endpoint_baseurl):
client_db_uri = self.config.get("client_db_uri")
cdb_file = self.config.get("client_db_path")
if client_db_uri:
cdb = MongoWrapper(client_db_uri, "satosa", "clients")
cdb = StorageBase.from_uri(
client_db_uri, db_name="satosa", collection="clients"
)
elif cdb_file:
with open(cdb_file) as f:
cdb = json.loads(f.read())
else:
cdb = {}
self.user_db = MongoWrapper(db_uri, "satosa", "authz_codes") if db_uri else {}

self.user_db = (
StorageBase.from_uri(db_uri, db_name="satosa", collection="authz_codes")
if db_uri
else {}
)
#XXX What is the correct ttl for user_db? Is it the same as authz_code_db?

self.provider = Provider(
self.signing_key,
capabilities,
@@ -101,10 +110,22 @@ def _init_authorization_state(self):
sub_hash_salt = self.config.get("sub_hash_salt", rndstr(16))
db_uri = self.config.get("db_uri")
if db_uri:
authz_code_db = MongoWrapper(db_uri, "satosa", "authz_codes")
access_token_db = MongoWrapper(db_uri, "satosa", "access_tokens")
refresh_token_db = MongoWrapper(db_uri, "satosa", "refresh_tokens")
sub_db = MongoWrapper(db_uri, "satosa", "subject_identifiers")
authz_code_db = StorageBase.from_uri(
db_uri, db_name="satosa", collection="authz_codes",
)
authz_code_db.ttl = self.config["provider"].get("authorization_code_lifetime", 600)
access_token_db = StorageBase.from_uri(
db_uri, db_name="satosa", collection="access_tokens"
)
access_token_db.ttl = self.config["provider"].get("access_token_lifetime", 3600)
refresh_token_db = StorageBase.from_uri(
db_uri, db_name="satosa", collection="refresh_tokens"
)
refresh_token_db.ttl = self.config["provider"].get("refresh_token_lifetime", None)
sub_db = StorageBase.from_uri(
db_uri, db_name="satosa", collection="subject_identifiers"
)
#XXX what is the correct TTL for sub_db?
else:
authz_code_db = None
access_token_db = None