SealSkin

sso

Web sign-ins: through an identity provider (OpenID Connect, SAML 2.0) or with the root token.

A sign-in is a random token the browser holds in the SESSION_COOKIE cookie, which names a record here: the user, how they signed in, the groups the provider named, and when it ends. security.verify_token asks current for it on every request.

  • A provider flow is bound to the browser that started it by a cookie, so a response the provider sent another browser is refused, and so is its grant: a link carrying someone else's grant signs nobody in. The SAML POST arrives cross-site, where a SameSite=Lax cookie is withheld, so the assertion is checked there and the binding one redirect later (saml_done).
  • A sign-in lasts as long as the provider's: OpenID Connect ends at the ID token's expiry, or, with a refresh token, refreshes at most once every CHECK_SECONDS while in use and ends when the provider refuses, picking up group changes as it does; SAML ends at the assertion's SessionNotOnOrAfter. A logout the provider announces ends the sign-in at once: an OpenID Connect back-channel logout token or front-channel request naming its session, or a signed SAML logout request. Every sign-in ends after sso_max_age_seconds. sso_force_login makes the provider ask for credentials every time.
  • The user name and groups are claims of the ID token, or of the provider's UserInfo endpoint where the ID token leaves them out (_with_userinfo); a SAML attribute is named by its Name or its FriendlyName, in saml_username_attribute and saml_groups_attribute where the two protocols name them differently.
  • The first sign-in as a SealSkin user through each protocol binds it to the provider's subject there (user_manager.ensure_user), and another subject is refused as that user later. A key-file administrator's name is refused, since administrators come from sso_admin_group alone.
  • The built-in administrator admin signs in with one of their application keys (app.application_keys.web_sign_in), which starts a sign-in here like a provider's; it ends after web_session_seconds unused. A user a reverse proxy names has no sign-in here: the proxy's header is read on each request (app.proxy_auth).
  • Each sign-in through a provider is stamped on the user's record (user_manager.note_web_sign_in), and a logout the provider announces ends the stamp, which is what the application keys' dormancy rules read.

Sign-ins are this node's own (sso_keys_path, written 0600): an OpenID Connect one keeps its refresh token so a restarted server can still ask the provider. Only the hash of a sign-in's token is kept.

attributelogger
= logging.getLogger(__name__)
attributeCHECK_SECONDS
= 60
attributeFLOW_SECONDS
= 600
attributeGRANT_SECONDS
= 120
attributeCACHE_SECONDS
= 3600
attributeCLOCK_SKEW_SECONDS
= 120
attributeMAX_PENDING
= 10000
attributeCOOKIE
= 'sealskin_sso'
attributeSESSION_COOKIE
= '__Host-sealskin'
attributeBACKCHANNEL_LOGOUT_EVENT
= 'http://schemas.openid.net/event/backchannel-logout'
attributeASYMMETRIC_ALGORITHMS
= {'RS256', 'RS384', 'RS512', 'PS256', 'PS384', 'PS512', 'ES256', 'ES384', 'ES512', 'EdDSA'}
attributeSAMLP
= 'urn:oasis:names:tc:SAML:2.0:protocol'
attributeSAML
= 'urn:oasis:names:tc:SAML:2.0:assertion'
attributeMD
= 'urn:oasis:names:tc:SAML:2.0:metadata'
attributeDS
= 'http://www.w3.org/2000/09/xmldsig#'
attributeREDIRECT
= 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
attributePOST
= 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
attributeSUCCESS
= 'urn:oasis:names:tc:SAML:2.0:status:Success'
attributeBEARER
= 'urn:oasis:names:tc:SAML:2.0:cm:bearer'
attributeREDIRECT_SIGNATURES
= {'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256': hashes.SHA256, 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384': hashes.SHA384, 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512': hashes.SHA512, 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256': hashes.SHA256, 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384': hashes.SHA384, 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512': hashes.SHA512}