Demo environment. Penrose Analytics is fictional, the demo people are shared, and the workspace resets nightly.

Gatehouse

Connect Okta or Entra

Point a workspace at a real identity provider. This guide is written from the providers' own documentation and from the assertions Gatehouse's tests sign and tamper with. It has not been run against a live Okta or Entra tenant, and the screenshots and menu names you meet may differ from the ones below.

What the provider needs

Gatehouse is the service provider. These are the values for this deployment, taken from APP_URL. If you run your own copy they change with it, and so must the provider's configuration.

Entity IDOkta: Audience URI (SP Entity ID). Entra: Identifier (Entity ID).
https://auth.phoenixcodes.org/api/saml/metadata
Assertion consumer service URLOkta: Single sign-on URL, also Recipient and Destination. Entra: Reply URL.
https://auth.phoenixcodes.org/api/saml/acs
Name ID formatOkta: Name ID format. Entra: Unique User Identifier.
EmailAddress, carrying the work email address.
Response binding
HTTP-POST. Gatehouse sends its own request by HTTP-Redirect.
What to sign
The assertion, with SHA-256 or SHA-512 (SHA-1 is refused). Signing the response as well is fine.

The same values are published as SAML metadata at https://auth.phoenixcodes.org/api/saml/metadata, for providers that can import it. Gatehouse signs every request it sends. The certificate in that metadata has the SHA-256 fingerprint B4:DA:20:67:DC:26:C0:4D:55:54:F8:83:12:45:E6:91:5C:80:10:F9:E6:8F:D5:0D:F6:F8:72:6F:57:AF:8C:4B. Okta and Entra accept unsigned requests, so you only need the certificate if you switch on signature checking for requests.

What you take back from the provider: its sign-on URL, its issuer (entity id), and its signing certificate as PEM. Gatehouse only accepts a response signed by that certificate, addressed to the entity id above, and answering a request Gatehouse itself sent.

Okta

  1. In the admin console, create an app integration of type SAML 2.0.
  2. Set Single sign-on URL to the ACS address and tick Use this for Recipient URL and Destination URL. Set Audience URI to the entity id.
  3. Set Name ID format to EmailAddress and Application username to Email.
  4. Add attribute statements: email = user.email, name = user.displayName, and optionally team = user.department.
  5. Add a group attribute statement named groups with a filter that matches the groups you want to map (a regular expression such as gh-.*). Okta sends group names.
  6. Assign people or groups to the app. Open the Sign On tab and choose View SAML setup instructions: the sign-on URL, the issuer and the certificate are there. Download the certificate as PEM.

Microsoft Entra ID

  1. Under Enterprise applications, create your own application and choose the option to integrate one that is not in the gallery. Open Single sign-on and pick SAML.
  2. In Basic SAML Configuration, set Identifier to the entity id and Reply URL to the ACS address.
  3. In Attributes and claims, check that the unique user identifier is user.mail in email address format. The default claims already include the email address and the display name under the URIs in the table below.
  4. Add a group claim for security groups. Entra sends group object ids, not names, so the role map uses ids.
  5. Download Certificate (Base64) from the SAML certificates box. Copy Login URL and Microsoft Entra Identifier from Set up. Under the signing options choose to sign the assertion (the default) or the response and assertion.
  6. Under Users and groups, assign who may sign in.

Register the connection

There is no screen for adding a connection yet: the demo's single sign-on page is read-only. A connection is one row, and an administrator of the database adds it:

insert into sso_connections
  (id, tenant_id, slug, name, is_mock, idp_entity_id, sso_url, idp_cert_pem,
   attribute_map, role_map, default_role, jit, enabled)
values
  ('sso_acme_okta', 'ten_acme', 'acme-okta', 'Acme Okta', false,
   '<issuer from the provider>',
   '<sign-on URL from the provider>',
   '-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----',
   '{"email":"email","name":"name","groups":"groups","team":"team"}',
   '{"gh-admins":"admin","gh-owners":"owner"}',
   'member', true, true);
  • slug is lower case letters, digits and hyphens, at most 60, and unique in the workspace. The person starts at https://auth.phoenixcodes.org/api/saml/login?tenant=<workspace slug>&connection=<slug>.
  • jit decides whether an address Gatehouse has never seen may create a person. enabled false turns the connection off without deleting it.
  • default_role is what a person with no mapped group becomes. Keep it member.

Attributes and groups

attribute_map names the assertion attribute that carries each fact. role_map turns group values into roles; the highest rank among a person's groups wins (owner, then admin, then member). If the email attribute is missing, Gatehouse falls back to the Name ID when it looks like an address.

email
Okta: email
Entra: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
name
Okta: name
Entra: http://schemas.microsoft.com/identity/claims/displayname
groups
Okta: groups, carrying group names
Entra: http://schemas.microsoft.com/ws/2008/06/identity/claims/groups, carrying group object ids
team
Okta: team
Entra: a custom claim you add, for example from the department

The name is trimmed to 120 characters, the team to 60, and at most 100 groups of 200 characters each are read. The role and team are read again on every sign-in, so removing someone from a directory group lowers their role the next time they sign in. To end access at once, deactivate them with SCIM: a deactivated membership is refused whatever the directory says.

Check it

  1. Open the login address in a private window and sign in at the provider.
  2. If Gatehouse refuses, the page names the reason in one sentence. The codes and their wording are in the table on How Gatehouse works. The flow inspector and the audit log hold the same reason with the step it happened at.
  3. The usual causes, in order of frequency: the Audience or Reply URL differs from the values above by a trailing slash or a scheme; the certificate pasted is the wrong one (or was rotated); the provider signs with SHA-1; the group value is a name where an id is expected, or the other way round, so nobody maps to a role.

Provisioning

Sign-in by SAML creates a person on first sight (when jit is on) but never removes one. For hiring and leaving to follow the directory, add SCIM:

  • Create a token under Single sign-on, Provisioning. The base URL is https://auth.phoenixcodes.org/api/scim/v2.
  • Okta: in the app's provisioning settings choose SCIM, enter the base URL, set the unique identifier field to userName, tick Push New Users and Push Profile Updates, and choose HTTP Header as the authentication mode with the token.
  • Entra: in the application's Provisioning, set the mode to Automatic, enter the base URL as Tenant URL and the token as Secret Token, test the connection, then map userPrincipalName or mail to userName.

The full contract, including the exact PATCH shapes these two providers send, is on the SCIM page. As with the sign-in, it is exercised by the test suite and by the documents each provider publishes, not by a live provider.