Role assignment

Stytch's RBAC framework uses Role assignment to delegate access controls. Rather than granting permissions one by one, Members are assigned Roles that grant them sets of permissions.

Stytch's RBAC model supports two different programmatic mechanisms for Role assignment.

  1. Explicit assignment
  2. Implicit assignment

Explicit assignment

Explicit role assignment is when you directly assign (or revoke) a Role to a specific Member object with an API call. Once assigned, the Member has that Role unconditionally until it is explicitly revoked. Explicit assignment is a singular operation between a specific Role and an individual Member.

The following API endpoints support explicit Role assignment.

Below is an example of explicitly assigning the admin Role to a specific Member via the Update Member endpoint.

curl --request PUT \
	--url https://test.stytch.com/v1/b2b/organizations/organization-test-07971b06-ac8b-4cdb-9c15-63b17e653931/members/member-test-32fc5024-9c09-4da3-bd2e-c9ce4da9375f \
	-u 'PROJECT_ID:SECRET' \
	-H 'Content-Type: application/json' \
	-d '{
		"roles": ["admin"]
	}'

Alternatively, you can also explicitly assign or remove Roles in the Dashboard by navigating to a specific Member’s page.

Implicit assignment

Stytch also supports the implicit assignment of Roles. Members can automatically be designated Roles by meeting certain criteria or possessing certain attributes. For example, your Organization's settings can be configured so that all Members with a stytch.com email domain are assigned the Role of developer upon account creation.

Implicit assignment can be thought of as a mechanism to define rules for automatically assigning Roles to multiple Members.

Stytch offers three ways to implement implicit role assignment:

  1. By email domain: everyone with the stytch.com email domain gets the “developer” Role.
  2. By SSO Connection: everyone who authenticates via a specific SSO Connection gets the “employee” Role.
  3. By SSO Connection IdP Group: everyone who authenticates via a specific SSO Connection and is a part of the “engineering” IdP group gets the “developer” Role.

Stytch currently only supports SSO connection implicit role assignments for SAML connections, but not for OIDC connections. Please email us or post in our community if you would like to use this functionality for OIDC connections.

Take a look at this example of how implicitly assigning roles by email domain would be codified in the Organization object.

{
  "organization_id": "my-org-id-123",
  "email_allowed_domains": ["stytch.com", "stytch.io", "customer.com"],
  "rbac_email_implicit_role_assignments": [
    {"domain": "stytch.com", "role_id": "contributor"},
    {"domain": "customer.com", "role_id": "reader"}
  ]
}

In effect, the "reader" Role would automatically be assigned to all Members with a customer.com email, and the "contributor" Role to those with a stytch.com email. Roles are assigned without performing direct operations on any of the affected Member objects.

Implicit role assignments are only valid so long as the granting condition is still true.

Consider this scenario. A Member was granted the “admin” Role via their IdP group membership. But the next time they authenticate, they discover that their IdP group membership has been revoked. The Member would lose the "admin" role.

The following API endpoints support implicit Role assignment by email domain, using the rbac_email_implicit_role_assignments argument:

Below is an example of using the Update Organization endpoint to implicitly assign the "contributor" Role to all Members in the Organization with the "stytch.com" email domain.

curl --request PUT \
	--url https://test.stytch.com/v1/b2b/organizations/organization-test-07971b06-ac8b-4cdb-9c15-63b17e653931 \
	-u 'PROJECT_ID:SECRET' \
	-H 'Content-Type: application/json' \
	-d '{
		"rbac_email_implicit_role_assignments": [
		    {
		        "domain": "stytch.com",
		        "role_id": "contributor"
		    }
		]
	}'

Alternatively, you can also create email implicit role assignments in the Dashboard by navigating to a specific Organization’s page.

The following API endpoints support implicit Role assignment by SSO connection or SSO connection IdP group:

Below is an example of using the Update SAML Connection endpoint to implicitly assign the "employee" Role to all Members in the Organization who authenticate with that SAML connection, and to implicitly assign the "developer" Role to all Members in the Organization who authenticate with that SAML connection and belong to the "engineering" IdP group.

curl --request PUT \
	--url https://test.stytch.com/v1/b2b/sso/saml/organization-test-07971b06-ac8b-4cdb-9c15-63b17e653931/connections/${connectionId} \
	-u 'PROJECT_ID:SECRET' \
	-H 'Content-Type: application/json' \
	-d '{
		"saml_connection_implicit_role_assignments": [
		    {
		        "role_id": "employee"
		    }
		],
		"saml_group_implicit_role_assignments": [
		    {
		        "group": "engineering",
		        "role_id": "contributor"
		    }
		],
	}'

Alternatively, you can also create SSO connection/group implicit role assignments in the Dashboard by navigating to the specific page of the Organization that the SSO connection belongs to.

SAML Member Groups

As mentioned above, Stytch supports implicit role assignments by SAML Connection IdP Group. In order for Stytch to know which groups the Member belongs to, you must add a groups key to the SAML connection's attribute_mapping. The IdP should be configured to correctly send a list of strings under that key.

For example, if your Stytch SAML connection has the following attribute mapping:

{
  "attribute_mapping": {
    "email": "email",
    "full_name": "name",
    "groups": "groups"
  }
}

And Stytch receives the following SAML assertion:

<saml2:Attribute Name="groups" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
    <saml2:AttributeValue>Admins</saml2:AttributeValue>
    <saml2:AttributeValue>Billing</saml2:AttributeValue>
</saml2:Attribute>

The Member will have groups "Admins" and "Billing".

Member Roles

The Member object will contain information about all of a Member's Roles and their sources. For example, consider the following JSON representation of a Member object (showing a subset of the returned fields):

{
  "email_address": "sandbox@stytch.com",
  "member_id": "member-test-32fc5024-9c09-4da3-bd2e-c9ce4da9375f",
  "roles": [
    {
      "role_id": "reader",
      "sources": [
        {
          "type": "email_assignment",
          "details": { "email_domain": "example.com" }
        }
      ]
    },
    {
      "role_id": "contributor",
      "sources": [
        {
          "type": "sso_connection_group",
          "details": {
            "connection_id": "saml-connection-test-51861cbc-d3b9-428b-9761-227f5fb12be9",
            "group": "admins"
          }
        }
      ]
    },
    {
      "role_id": "editor",
      "sources": [
        {
          "type": "direct_assignment",
          "details": {}
        },
        {
          "type": "sso_connection",
          "details": {
            "connection_id": "saml-connection-test-51861cbc-d3b9-428b-9761-227f5fb12be9"
          }
        }
      ]
    },
    {
      "role_id": "stytch_member",
      "sources": [
        {
          "type": "direct_assignment",
          "details": {}
        }
      ]
    }
  ],
  "sso_registrations": [{
    "connection_id": "saml-connection-test-51861cbc-d3b9-428b-9761-227f5fb12be9",
    "external_id": "sandbox@stytch.com",
    "registration_id": "saml-member-registration-test-9a6d293d-d8b3-42e8-abb4-220cc2060e93",
    "sso_attributes": {
      "email": ["sandbox@stytch.com"],
      "first_name": ["Test"],
      "last_name": ["Member"]
    }
  }]
}

This Member has four roles: "reader", "contributor", "editor", and "stytch_member". The "reader" role is implicitly assigned because of the Member's email domain; the "contributor" role is implicitly assigned because the Member has an SSO registration with the specified SSO connection ID, and they belong to the "admins" group within their IdP; the "editor" role is both explicitly assigned, and also implicitly assigned because the Member has an SSO registration with the specified SSO connection ID. The "stytch_member" role, as mentioned in the Stytch Resources and Roles guide, is a special role that all Members have, and cannot be revoked.

Search for Members by Role

Stytch enables you to conveniently search for Members by Role with the Search Members endpoint. This search encompasses both explicit and implicit role assignments.

Member Session Roles

All Stytch RBAC authorization checks are performed based on the roles present in a Member Session, rather than the roles present on a Member object. This is because some implicit role assignments are based on the Member's login method.

For example, consider a SAML connection with the following implicit role assignments:

{
  "connection": {
    "connection_id": "saml-connection-test-51861cbc-d3b9-428b-9761-227f5fb12be9",
    "organization_id": "organization-test-07971b06-ac8b-4cdb-9c15-63b17e653931",
    "saml_connection_implicit_role_assignments": [
      {
        "role_id": "admin"
      }
    ]
  }
}

If a Member's Session contains an SSO authentication factor with the specified SAML connection ID, their Member Session will contain the "admin" role, like so (only a subset of relevant fields are shown):

{
  "member_session": {
    "member_session_id": "session-test-fe6c042b-6286-479f-8a4f-b046a6c46509",
    "member_id": "member-test-32fc5024-9c09-4da3-bd2e-c9ce4da9375f",
    "authentication_factors": [
      {
        "delivery_method": "sso_saml",
        "saml_sso_factor": {
          "id": "saml-member-registration-test-9a6d293d-d8b3-42e8-abb4-220cc2060e93",
          "provider_id": "saml-connection-test-51861cbc-d3b9-428b-9761-227f5fb12be9"
        },
        "type": "sso"
      }
    ],
    "organization_id": "organization-test-07971b06-ac8b-4cdb-9c15-63b17e653931",
    "roles": ["stytch_member", "admin"]
  }
}

However, if the Member Session only contained a password factor, they would only receive the "stytch_member" role and not the "admin" role.

Interactions between Implicit and Explicit Role Assignments

If an explicitly assigned Role is removed from a Member, and the Member is also implicitly assigned that Role from an SSO connection or an SSO group, we will by default revoke any existing Sessions for the Member that contain any SSO authentication factors with the affected connection ID.

For example, consider a Member with the following Roles:

{
  "member_id": "member-test-32fc5024-9c09-4da3-bd2e-c9ce4da9375f",
  "roles": [
    {
      "role_id": "editor",
      "sources": [
        {
          "type": "direct_assignment",
          "details": {}
        },
        {
          "type": "sso_connection",
          "details": {
            "connection_id": "saml-connection-test-51861cbc-d3b9-428b-9761-227f5fb12be9"
          }
        }
      ]
    },
    {
      "role_id": "stytch_member",
      "sources": [
        {
          "type": "direct_assignment",
          "details": {}
        }
      ]
    }
  ]
}

This Member's "editor" comes from two sources: an explicit role assignment and an SSO connection implicit role assignment.

Now consider the following Member Session, which contains a SAML SSO authentication factor:

{
  "member_session": {
    "member_session_id": "session-test-fe6c042b-6286-479f-8a4f-b046a6c46509",
    "member_id": "member-test-32fc5024-9c09-4da3-bd2e-c9ce4da9375f",
    "authentication_factors": [
      {
        "delivery_method": "sso_saml",
        "saml_sso_factor": {
          "id": "saml-member-registration-test-9a6d293d-d8b3-42e8-abb4-220cc2060e93",
          "provider_id": "saml-connection-test-51861cbc-d3b9-428b-9761-227f5fb12be9"
        },
        "type": "sso"
      }
    ],
    "organization_id": "organization-test-07971b06-ac8b-4cdb-9c15-63b17e653931",
    "roles": ["stytch_member", "editor"]
  }
}

If the Member is then updated (for example, from a call to Update Member) to remove the "editor" explicit role assignment, we will revoke the Member Session with the SAML SSO factor.

If you do not want any Sessions to be revoked when updating a Member's explicit role assignments, you can pass in the preserve_existing_sessions field with a value of true. It defaults to false.

This applies to the following endpoints:

What's next

Check out our Quickstart guide to start enforcing authorization with Stytch.