Skip to content

SAML support#3979

Closed
timfrazee wants to merge 63 commits intomasterfrom
tf/saml-entitlements
Closed

SAML support#3979
timfrazee wants to merge 63 commits intomasterfrom
tf/saml-entitlements

Conversation

@timfrazee
Copy link
Contributor

@timfrazee timfrazee commented Dec 11, 2025

Adds support for arbitrary SAML SSO providers for Manifold login.

Also provides the ability for sysadmins to set a default identity provider and optionally hide local login.

Configuration of these features is done in the environment to avoid mistakes that could render users unable to log into Manifold.

SAML

Adds support for SAML SSO providers to serve as identity providers for Manifold login.

SAML providers are defined in the environment. For each defined provider, additional settings / credentials are provided as namespaced ENV-vars.

By default, Manifold requires that it signs its metadata and Authn requests. It also requires that identity providers sign their assertions. To that end, it's necessary to generate a unique SHA256 X509 public/private key pair per-instance, which go in the certificate and private_key settings, respectively. With OpenSSL, this can be done with:

openssl req -new -x509 -days 365 -nodes -sha256 -out saml.crt -keyout saml.pem

The below example defines a SAML provider named "test1". Multiple providers can be defined as a comma-delimited list, then each provider's settings/credentials in appropriately-namespaced variables. The example shows common settings, but Manifold supports most of the options provided by Ruby SAML.

SAML_PROVIDER_NAMES=test1

SAML_TEST1_ENABLED=TRUE
SAML_TEST1_DISPLAY_NAME=Test SAML 1
SAML_TEST1_SP_ENTITY_ID=manifold_test_1
SAML_TEST1_IDP_ENTITY_ID=https://saml.example.com/entityid
SAML_TEST1_IDP_SSO_SERVICE_URL=https://mocksaml.com/api/saml/sso
SAML_TEST1_CERTIFICATE="-----BEGIN CERTIFICATE-----{CERT GOES HERE}-----END CERTIFICATE-----"
SAML_TEST1_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----{PRIVATE KEY GOES HERE}-----END PRIVATE KEY-----"
SAML_TEST1_IDP_CERT="-----BEGIN CERTIFICATE-----{IDP CERT GOES HERE}-----END CERTIFICATE-----"

Additional settings:

SAML_TEST1_HIDDEN=TRUE # Hides the login button, but the provider remains active. Useful for testing.
SAML_TEST1_DEFAULT=TRUE # If any provider is set as default, the user will be automatically redirected to it

SAML_DISABLE_PASSWORD_AUTH=TRUE # Removes email/password authentication, leaving only SSO options

User Groups

User Groups are a new model that serve to connect users to entitleable resources. Members of a user group are granted entitlements to the associated resources.

Entitlements granted through User Group memberships are granted when a user joins, and destroyed if/when a membership is destroyed. Since the membership is the entitler, this does not affect entitlements granted through other means.

This feature also adds admin UI to manage user groups, their members, and their entitleables.

External Identifiers

External identifiers are simple records designed to hold identifier strings that connect an entitleable resource or user group in Manifold to a resource known and managed by an external system. Identifiers are unique, guaranteeing that a maximum of one resource will be returned for a given identifier.

External identifiers are defined in admin under the appropriate resources.

External auth entitlement management

SAML IDPs can define claims named user_groups and entitlements, providing a semicolon-or-comma-delimited list of external identifiers of user groups or entitleable entities, respectively.

When a user logs in, the IDP's list of desired user groups and entitlements is compared against the user's existing identity-managed entitlements, and they are updated to match (adding or removing as needed). The user's identity is referred as the source on user groups and the entitler on entitlements, so this

@timfrazee timfrazee force-pushed the tf/saml-entitlements branch from c4094ac to d91a354 Compare December 16, 2025 17:40
@timfrazee timfrazee marked this pull request as ready for review December 16, 2025 18:00
@timfrazee timfrazee force-pushed the tf/saml-entitlements branch from 221b36a to 8168ddc Compare December 16, 2025 21:11
@timfrazee timfrazee force-pushed the tf/saml-entitlements branch from 1dff445 to 1a142e4 Compare January 14, 2026 22:24
@timfrazee
Copy link
Contributor Author

Closing in favor of #3998

@timfrazee timfrazee closed this Feb 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants