What is SAML?
The Security Assertion Markup Language (SAML) is an XML-based standard for communicating authentication information between multiple parties. Its most common use case is in providing federated identity and single sign-on (SSO) functionality, which allow for employees at Deere to login once with a single set of credentials and use that same identity across multiple external services.
The Standard
There are three participants in the SAML flow:
- the Identity Provider (IdP), e.g. Okta,
- the Subject, i.e. the user’s browser, and
- the Service Provider (SP), e.g. Zuora, Rally, etc.
The standard defines an XML schema for assertions from one party to another. An assertion is made up of some metadata (e.g. who is the subject) and a series of statements, which take on one of three forms:
- Authentication (how and when did the subject authenticate)
- Attribute (key-value pairs representing properties of the subject, such as email address, group membership, etc.)
- Authorization Decision ($X$ is authorized to do $Y$ on $Z$)
Additionally, the standard defines a format for metadata that describe configuration information for a service’s metadata often includes information about the role of the service, the public key for verifying the assertion, and more.
The SSO Flow
These notes will focus on the redirect based flow, where the browser brokers the authentication. Of such flows, there are two types, depending on whether the SP or the IdP initiates the flow.
SP-Initiated
- Subject requests a resource from the SP.
- SP checks if browser has as security context:
If yes, skip to 7.
Else, redirect with a
GET
to IdP with two query parameters:SamlRequest
: Base64 encoded XMLRelayState
: any state that needs to be kept track of, e.g. deep links
- IdP checks if browser has a security context. If not, prompt user for credentials.
- IdP generates a SAML assertion and puts it in an xhtml document as a hidden form.
Sign the assertion with private key and redirect with a
POST
to SP. Echo theRelayState
back to the SP. - SP verifies the authenticity of the assertion with IdP’s public key. If valid, SP generates a security context and forwards it to the subject.
- Subject requests the resource again.
- SP checks security context to see if user is authorized to access resource. If yes, responds with the resource.
It is important to note that this process is stateless, hence the RelayState
query parameter must be used to keep track of information we want to persist.
IdP-Initiated
- IdP prompts users for credentials.
- User selects service from IdP portal.
- IdP generates a SAML assertion and puts it in an xhtml document as a hidden form.
Sign the assertion with private key and redirect with a
POST
to SP. - SP verifies the authenticity of the assertion with IdP’s public key. If valid, SP generates a security context and forwards it to the subject.
- SP checks security context to see if user is authorized to access resource. If yes, responds with the resource.
What is SCIM?
The System for Cross-domain Identity Management (SCIM) is an open standard for provisioning users and groups across applications.
For example, suppose that we want to provide access to an application for all members of a particular AD group and automatically assign each user to different permission groups based on their position in the company. Now, say that someone has left the team, and we want to revoke access to their account.
All these identity management tasks are effortless in services that support the SCIM standard.
The Standard
The SCIM standard defines two things:
- a JSON schema for representing users and groups, and
- a RESTful API to perform CRUD (Create, Read, Update, and Delete) operations on users and groups.
Example User Lifecycle
Suppose that John joins your company as a software engineer in the sales department. Your company uses Microsoft Active Directory (AD) as a centralized user store integrated with Okta, which you use for identity management.
An example flow for how Okta may provision John’s user in your favorite SaaS might be (disclaimer: I don’t actually know exactly what Okta does, but this is my best guess from reading the docs):
- John’s account is created in AD and assigned to the
Sales
andDeveloper
AD groups. - John’s account information is synced to Okta, which uses the
Sales
group to assign him toSaaS.com
and pushes theDeveloper
group to the application. - Okta notices that John’s account does not exist on
SaaS.com
, so it issues the followingPOST
request tohttps://SaaS.com/scim/v2/Users
:to which{ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], "userName": "DoeJohn@company.com", "name": { "givenName": "John", "familyName": "Doe" }, "emails": [{ "primary": true, "value": "DoeJohn@company.com", "type": "work" }], "displayName": "John Doe", "locale": "en-US", "externalId": "randomid123", "groups": ["Developer"], "password": "password123", "active": true }
SaaS.com
responds with a201 Created
and the newly created user. - John gets promoted to a manager and gets added to the
Manager
AD group. - Okta updates his user by sending a
PATCH
request tohttps://SaaS.com/scim/v2/Users/$theusersuuid
:to which{ "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations": [{ "op": "replace", "value": { "groups": ["Manager"] } }] }
SaaS.com
responds with a200 OK
and the updated user. - John now leaves the company.
- Okta deactivates his account and sends a
PATCH
request tohttps://SaaS.com/scim/v2/Users/$theusersuuid
(note that Okta doesn’t use theDELETE
verb):{ "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations": [{ "op": "replace", "value": { "active": false } }] }
Sources
SAML
- https://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0-cd-02.html
- https://developer.okta.com/docs/concepts/saml/
- https://www.samltool.com/generic_sso_res.php