Organization single sign-on

Organization single sign-on (SSO) lets members sign in to an organization through an OpenID Connect (OIDC) identity provider. Okta and Microsoft Entra are the supported providers, each through an application you create in your own tenant. There is no Okta Integration Network listing to install the integration from.

Organization SSO is only available to organizations Hexpm has turned it on for. It's optional, scoped to one Hexpm organization, and never creates a Hexpm account. SSO login on its own adds no members and assigns no roles. Two settings, both off by default, change that: just-in-time membership adds an existing Hexpm account as a member the first time it authenticates with an address on a domain the organization has verified, and provisioning (SCIM) adds, removes, and invites members as your provider assigns and deactivates them. Both give new members a role you choose.

SSO is not a way to sign in to Hexpm. Hexpm keeps two separate sessions, and only the first is a login:

  • The account session is the person's login to Hexpm, established by a password, GitHub, or another credential the account itself owns, together with the account's own two-factor authentication where enrolled. An identity provider never establishes it.
  • The organization access session is what an SSO authentication produces. It is scoped to one organization and records that the provider authenticated the member. An organization decides whether reaching it requires one, and how long one lasts.

A member signs in to Hexpm as themselves first, then authenticates to the organization's provider.

Before you begin

You need:

  • Administrator access to the Hexpm organization.
  • Administrator access to your OIDC provider.
  • A Hexpm account for every person who will use SSO.
  • Organization membership for every person who will link an SSO identity, unless just-in-time membership or provisioning will add them.

Open the Hexpm organization dashboard, select SSO, and keep the Redirect URI shown there available while configuring your provider. The URI ends in the organization name and is unique to this organization, so an organization configured with another organization's URI cannot complete a login.

Create the Okta application

In the Okta Admin Console, follow Okta's OIDC app-integration instructions with these Hexpm settings:

  1. Open Applications, select Applications, and create a new app integration.
  2. Choose OIDC - OpenID Connect as the sign-in method and Web Application as the application type.
  3. Select the Authorization Code grant type.
  4. Add the exact Redirect URI from the Hexpm SSO dashboard as a sign-in redirect URI. Do not use a wildcard.
  5. Leave the sign-out redirect URIs empty. This release does not use OIDC logout.
  6. Under Login initiated by, select App Only if members will always start from the organization login URL. To let them start from Okta instead, select Either Okta or App and set the Initiate login URI described below. The URI appears on the Hexpm SSO dashboard only after SSO login is enabled, so this step needs a second pass through Okta once setup is finished.
  7. Assign only the people or groups who should be able to use the Hexpm integration.
  8. Save the application, then copy its Client ID and Client secret.

The application must allow the openid and email scopes. Hexpm uses the provider subject as the stable identity. The email claim never proves ownership of a Hexpm account and never selects which account a login links to. Hexpm shows it on the link confirmation screen, emails a member when a later login reports an address that isn't verified on their account, lets provisioning match a current member by it, and, when just-in-time membership is on, admits a person only if it's on a verified domain and the provider marks it as verified.

The issuer to enter in Hexpm is the Okta organization URL, https://{yourOktaDomain}. Use the organization issuer rather than a custom authorization server such as /oauth2/default; Hexpm is tested and documented against the organization issuer.

Register the Entra application

In the Microsoft Entra admin center:

  1. Open Identity, Applications, App registrations, and select New registration.
  2. Under Supported account types, choose Accounts in this organizational directory only. Hexpm accepts only the tenant-specific issuer, so a multitenant registration gains nothing.
  3. Under Redirect URI, choose the Web platform and enter the exact Redirect URI from the Hexpm SSO dashboard.
  4. Register the application, then copy the Application (client) ID and Directory (tenant) ID from its Overview page.
  5. Open Certificates & secrets, add a client secret, and copy its Value before leaving the page; it is shown once. Entra client secrets expire, so note the date and rotate before it as described below.
  6. Open Manifest and add the email and xms_edov optional claims to the ID token: the idToken list under optionalClaims has to contain {"name": "email"} and {"name": "xms_edov"}. Keep any entries already there, then save.
  7. Open the application under Enterprise applications, set Assignment required to Yes under Properties, and assign the people or groups who should be able to use the Hexpm integration under Users and groups.

The issuer to enter in Hexpm is the tenant-specific v2 issuer, https://login.microsoftonline.com/{tenant-id}/v2.0. Do not use common, organizations, or another tenant-independent issuer: their discovery documents do not return the issuer you configured, and Hexpm requires that they match. Hexpm uses the exact issuer and stable OIDC subject as the identity key for managed and guest users alike, and never substitutes preferred_username or the user principal name for a missing email claim.

Just-in-time membership needs both optional claims. Entra sends email_verified only when a claims-mapping policy adds it, with whatever value the policy sets, so for an Entra issuer Hexpm ignores email_verified and reads xms_edov in its place. Entra sends xms_edov only together with email, and sets it to true when the owner of the address's domain has verified it, such as for a domain verified in your tenant; Microsoft's optional claims reference lists the cases. Without the claims, SSO login still works, but just-in-time membership refuses everyone with the provider_email_unverified code.

Configure Hexpm

On the organization's SSO dashboard:

  1. Enter the Issuer URL for your provider, exactly as given above. Hexpm requires an HTTPS issuer with no query or fragment and requires the provider discovery document to return that exact issuer.
  2. Enter the application's Client ID and Client secret.
  3. Select Save configuration.
  4. Select Test connection and complete the provider sign-in as the same Hexpm administrator who saved the configuration.
  5. After the test succeeds, select Enable SSO login.

The status changes from Not tested after saving, to Tested, disabled after a successful test, and to Enabled after SSO login is enabled.

Once enabled, Hexpm displays the organization's login URL. Share that URL with assigned organization members.

Configure an Initiate Login URI

The Organization / Initiate Login URI is organization-bound; Hexpm never performs a global issuer lookup. It accepts HTTP GET initiation requests with the standard OIDC parameters:

  • iss is required whenever any recognized third-party initiation parameter is present and must exactly equal the organization's configured issuer.
  • login_hint is optional and is forwarded to the provider for that request only. Hexpm does not persist it.
  • target_link_uri is optional and must use Hexpm's configured origin and an allowlisted location within that organization's dashboard.
  • Unknown parameters are ignored.

Every accepted initiation creates fresh state, nonce, and PKCE values. Hexpm doesn't support custom Okta dashboard tiles, OIN Wizard-generated instances, or a public OIN listing. Tiles and Wizard-generated instances have been tested and work, but Hexpm doesn't document or support them. There is no public OIN listing because none has been submitted for review.

Following the organization login URL requires a Hexpm account session. Without one, Hexpm sends the member to conventional login first and resumes afterwards, so the same URL works signed in or signed out.

The first time a member uses the organization login URL:

  1. The member signs in to Hexpm with their own credential, completing their personal two-factor authentication if they have it enrolled.
  2. The member authenticates through the configured identity provider.
  3. Hexpm asks the member to confirm the link between the returned provider identity and the account they are signed in as. If the member hasn't re-authenticated to Hexpm in the last hour, this takes step-up re-authentication first.

Hexpm relies on the member being signed in, so there's no confirmation code and the provider's email isn't compared with the account's addresses. The Hexpm account has to be a member of the organization already, unless just-in-time membership admits it at this step. Otherwise an organization administrator invites it, and the member accepts the invitation and retries.

A provider email never establishes durable identity, selects an account, creates one, or changes a Hexpm email address. After linking, the connection, exact issuer, and stable provider subject are the identity key. The account's verified primary address is notified when the link is created; an account with no verified primary address is not notified at all.

After linking, later uses of the organization login URL establish an organization access session for that browser session. Signing out of Hexpm, or revoking the browser session, ends the organization access with it.

Verified domains

Just-in-time membership admits people by the domain of the address your provider reports, so the organization first proves it controls that domain. On the organization's SSO dashboard, under Verified domains, add the domain, publish the TXT record shown there on the domain itself, and select Verify. The record value starts with hexpm-domain-verification=. If the record isn't found yet, wait for the DNS change to propagate and verify again.

Only exact matches count. Verifying example.com doesn't cover eng.example.com, so add and verify each domain your provider's addresses use.

Verification isn't permanent. A daily job at 03:15 UTC looks up the record of every verified domain that hasn't been checked in the last 24 hours, and clears the verification when the record is gone. Keep the record published for as long as you use just-in-time membership. A lookup that gets no answer, such as a DNS timeout, leaves the verification as it is.

Adding, verifying, and removing a domain take an organization administrator and step-up re-authentication, and each is recorded in the organization's audit log. A verification the daily job clears is recorded there too.

Just-in-time membership

Just-in-time membership adds an existing Hexpm account to the organization the first time it authenticates through your provider, so you don't have to invite each person before they link. It never creates a Hexpm account and never sends an invitation. Someone without a Hexpm account signs up before their first login, or you use provisioning, which can invite them.

It needs a saved SSO configuration and at least one verified domain. Turn it on under Just-in-time membership on the SSO dashboard by choosing what happens When the seats run out, and pick the Role for new members, Read or Write. Choosing Off, do not add members automatically turns it off again.

A signed-in Hexpm account that isn't a member is admitted when all of these hold:

  • The ID token's email claim is on a verified domain. The part after @ has to equal the verified domain exactly.
  • The provider marks the address as verified. That's the ID token's email_verified claim being true. When the ID token leaves the claim out, as Okta's organization authorization server does, Hexpm asks the provider's userinfo endpoint instead, and counts its email_verified only when it returns the same email. With Microsoft Entra it's the xms_edov claim (see Register the Entra application). Anything else is refused with the provider_email_unverified code, which the person sees and Recent failures records.
  • The account meets the organization's two-factor requirement, if it has one.
  • A seat is free, or the seat policy adds one.

The person sees the same confirmation screen as any other link, and joins with the role you chose when they confirm it. Abandoning that screen adds nothing. The join is recorded in the organization's audit log as a member being added. A login whose address isn't on a verified domain is refused as not a member, the same answer an organization without just-in-time membership gives, so the refusal doesn't reveal whether the organization uses it or which domains it has verified.

While just-in-time membership is on, removing a member in Hexpm doesn't keep them out: their next login through your provider admits them again. Remove their assignment in your provider as well.

Require SSO to reach the organization

Enforcement is set on the organization's SSO dashboard and has three modes:

  • Optional is the default. Members can authenticate through the provider and nothing changes if they do not.
  • Pilot enforces only the members with Require SSO turned on in the members tab, set one at a time, so a team can try it on itself before turning it on for everyone.
  • Required enforces every member except the ones marked exempt, from a date you pick.

Exemptions are managed from the Exempt from SSO list on the members tab, in both modes, and exempt members carry an SSO exempt badge. Moving from pilot to required doesn't change any member's settings. Members enforced in the pilot stay enforced, every other member becomes enforced, and only members on the exemption list are left out.

A required-by date gives members time to link. Until it passes, the organization behaves as it does in pilot. Members who have not linked an identity are emailed in the two weeks before the date, and again if the date moves. When personal keys are blocked, members who have linked but hold a key the date will strip or refuse are emailed too, with each key and what happens to it. A date inside those two weeks is announced when it is saved.

A member who has not linked an identity is also emailed the moment enforcement starts applying to them with no date ahead: required mode saved with no date or a past one, the date moved to now, the connection turned on while required, or an administrator enforcing them or lifting their exemption.

Hexpm refuses to switch an organization to required unless at least one administrator is exempt or has already linked an identity, so a misconfigured provider cannot lock every administrator out of the settings that would fix it. If the organization requires two-factor authentication, including a requirement scheduled for a later date, that administrator also needs two-factor authentication enabled. The check runs again on every save of the enforcement settings while the mode is required, so changing only the session lifetime or the personal key setting is refused too once no administrator qualifies. Once required mode is in effect, the members tab also refuses an enforcement or exemption change that would leave no qualifying administrator.

Which credentials work under enforcement

What applies depends on the credential a request uses:

Credential Under enforcement
Browser session Needs a current organization access session for the organization. Hexpm sends you to the provider and back to the page you asked for.
Hex CLI (mix hex.user auth) The session established when you authorized the CLI carries organization access. Hex v2.6.0 or later asks you to re-authenticate in a browser when it lapses.
hexdocs and other OAuth clients Same, established when you approve the client.
Organization key Never enforced. It authenticates as the organization, not as a person, so SSO doesn't apply to it.
Personal key Allowed unless the organization chose to block them.

Enforcement is per organization and evaluated against the resource. Your Hexpm account, your own packages, the public repository, and every other organization you belong to are unaffected.

The organization access session

An administrator sets how long one lasts: one hour, eight hours, one day (the default), one week, or thirty days. The same lifetime applies to browser sessions, CLI sessions, and OAuth clients.

When one lapses in the browser, Hexpm redirects you to the provider and back. If the provider doesn't prompt you, you won't notice. At the terminal, Hex v2.6.0 or later asks you to authenticate in a browser and then carries on with the same CLI session; you don't have to run mix hex.user auth again.

Authorizing the Hex CLI or approving an OAuth client copies the organization access your browser session holds at that moment to the new session, with the same expiry rather than a fresh lifetime. The copy stays tied to the browser session it came from: signing out of that browser session, revoking it, or letting it expire ends the copied access too, even if the copy hasn't reached its own expiry. Authenticating through the provider for the CLI or client session itself gives that session access of its own, which no longer depends on the browser session.

A shorter lifetime means members authenticate more often. It also limits how long someone your provider has deactivated can keep reaching the organization.

Provisioning (SCIM)

Provisioning lets your provider create and deactivate members here as you assign and deactivate them there. It is separate from SSO login. SSO login authenticates a person, and provisioning changes who is a member.

On the organization's SSO dashboard, under Provisioning (SCIM), choose what happens when the seats run out and the role provisioned members join with, Read, Write, or Admin, then generate the bearer token. The role applies to members added by assignment and to the invitations provisioning sends. Choosing Admin makes every person your provider assigns an administrator of this organization. The token is shown once; regenerate it to replace it, and it is revoked automatically if the connection is pointed at a different provider. Provisioning is configured on a second application in your provider, separate from the one that handles login, using the SCIM base URL from the dashboard and that token.

In Okta, add SCIM 2.0 Test App (OAuth Bearer Token) from the application catalog. Under Provisioning, Integration, enter the SCIM base URL and the bearer token and test the API credentials. Under To App, enable the provisioning features you want: Create Users, Update User Attributes, and Deactivate Users each work on their own, so you can start with deactivation only. Then assign the same people or groups as the login application.

In Microsoft Entra, open Enterprise applications, select New application, then Create your own application, and choose Integrate any other application you don't find in the gallery. The application registered for login cannot be used here; Entra offers provisioning only on an enterprise application created this way. Under Provisioning, choose the Automatic mode, enter the SCIM base URL as the tenant URL and the bearer token as the secret token, and test the connection. Keep the default attribute mappings, turn provisioning on with its scope set to assigned users and groups, and assign people or groups under Users and groups. Entra sends changes on its own cycle, about every forty minutes and sometimes longer; Provision on demand applies one person's assignment, deactivation, or reactivation immediately, while a permanent deletion always waits for the next cycle.

Hexpm matches a provisioned person by userName, so the mapping must produce the email address the person verified on Hexpm. Entra's default maps it from the user principal name; if your users' principal names are not their email addresses, map it from mail instead. Hexpm reads userName, externalId, and active and ignores every other attribute.

What each operation does:

  • Assigning a person whose Hexpm account has a verified email matching the SCIM userName adds them as a member with the role you chose, taking a seat. They're emailed that they were added. If the seats are full, the create is refused or a seat is added to the subscription, per your choice. If the organization requires two-factor authentication and the person has not enabled it, the create is refused until they do; your provider retries on its own schedule.
  • Assigning a current member keeps their membership and role as they are and takes no seat. A current member is matched by a verified email, or by the address their linked SSO identity last reported, which finds a member whose Hexpm account doesn't hold the work address. Someone who isn't a member is never matched through an SSO identity.
  • Assigning an address no Hexpm account has verified sends a pending invitation to that address instead. Nothing creates a Hexpm account, and the seat is spent when the invitation is accepted, not when it is sent. An invitation is refused at acceptance if the organization is full by then, whichever seat policy you chose, because acceptance is what spends the seat.
  • Deactivating or unassigning removes the membership, with the member's organization access sessions and SSO link, and revokes any pending invitation to that address, including one an administrator sent by hand. The seat is freed for reuse; the billed quantity changes only when an administrator changes it.
  • Reactivating matches the userName again the same way assigning does. Deactivation removed the person's SSO link along with their membership, so only a verified email on their Hexpm account matches now: with one, they join again with the provisioned role under the same seat and two-factor checks as assigning them, and without one, the address gets an invitation. A role an administrator granted by hand before the deactivation isn't remembered.
  • Creating a person as inactive ("active": false) stores the provider's record without a membership or an invitation. A connection holds at most 1,000 inactive people, or ten per seat if that's more. Past that, an inactive create is refused until your provider deletes some. Deactivating someone and creating an active person are never refused for this.

You can still manage membership in Hexpm, but a member you remove by hand is added again the next time your provider sends them as active. Unassign them in the provider as well, or the next sync undoes the removal. A member you add by hand is matched by the provider's import through their verified email or the address they sign in with.

Provisioning refuses two removals, the same two the dashboard refuses: the organization's last member, and its last administrator who can still reach the organization (an active account that satisfies the organization's two-factor and SSO requirements). A provider that deactivates the other administrators leaves that one in place. Everything else a provider asks for is applied.

Microsoft Entra reports a displayName update every time it syncs a member, because Hexpm shows the member's username there and never stores the directory's value. The update succeeds and changes nothing; it is not a sign that provisioning is failing.

A full import lists each member's primary email address (or the address your provider already knows them by) to your provider, which is more than the member list on hex.pm shows.

Every provisioning write is recorded in the organization's audit log as SCIM, with the address the request came from. The Provisioning (SCIM) card shows who generated the token, when, and when it was last used.

CI is unaffected: organization keys are not members and never appear on this surface.

The Hex CLI

With Hex v2.6.0 or later, when a CLI session's organization access lapses, the next mix deps.get asks:

acme: SSO authentication required. Authenticate now? [Yn]

It names only the organizations the project actually depends on. Hex knows the whole set before it fetches anything, because a published package's dependencies can only come from the public repository or from that package's own organization, so a member of ten SSO organizations who depends on two is asked about two and asked once.

Saying yes opens a page bound to the CLI session you are already signed in on, and Hex prints its URL and waits for you to press enter. Completing SSO there renews that session: the same session, the same refresh token, and resolution carries on. Saying no continues without the organization's packages.

CI is unaffected. It authenticates with an organization key, which isn't tied to a person or a session, so SSO doesn't apply to it.

Personal keys

A personal key is a static credential. There is no session behind it, nothing expires it unless its owner set an expiry, and your provider never sees it used. Whether one may reach an enforced organization is the organization's choice, and the default is to allow them:

  • Block turns members' personal keys away from this organization. From the moment required mode takes effect, on the required-by date or at the save when there's no date, a request made with a personal key is refused for this organization. The permissions naming the organization are removed from the keys at the next daily run after that, at 03:45 UTC. Their owners are emailed, and the rest of each key keeps working. Creating a key with a permission that names the organization, or every repository, is refused. A key with only API permissions can still be created, and its requests against the organization are refused. Members publishing by hand run mix hex.user auth instead, after mix hex.organization deauth ORGANIZATION on any machine where they ran mix hex.organization auth ORGANIZATION, because mix uses the key that command stored ahead of their sign-in. Automation moves to an organization key.

    Blocking follows the same members enforcement does. A pilot turns personal keys away for the members with Require SSO turned on and for nobody else, and it refuses their requests and new keys without removing permissions from existing keys, so a pilot shows you what required mode will do without taking anything away yet. An exempt member's keys are never touched.

    The removal is permanent. Setting personal keys back to allow, or turning enforcement off, does not restore the permissions that were taken; the members whose keys were changed add them again themselves. Use a pilot first if you want to see the list before anything is removed.

  • Allow leaves them alone, and is the default. Use it if your publishing workflow depends on personal keys. Under required mode, those keys still reach the organization without an organization access session or an expiry, and your provider's conditional-access policy never sees them. A key stops working when its owner is removed from the organization here, because its permissions are checked against current membership. The repository CDN can cache a successful check for up to ten minutes. A provider deactivation counts as removal once provisioning is connected; without provisioning, a provider-only deactivation doesn't affect the key.

    An organization key has the same properties and is never enforced, so allowing personal keys adds more credentials of a kind the organization already accepts. Blocking them means members reach the organization through organization access sessions, which your provider's conditional-access policy applies to. Removing a member doesn't give you that.

Either way the SSO dashboard lists the members holding personal keys that reach the organization, and when each was last used, before you turn enforcement on. For a key whose permissions name the organization the list is exact. For one carrying every repository, or plain API access, it says the key could reach the organization rather than that it did; Hexpm records when a key was used and not what it was used against.

Exemptions

An exempt member reaches the organization with their Hexpm credential alone, so your provider's policy doesn't cover exempt accounts. The members tab lists every exempt member and shows how many there are.

Break-glass

Three things stay reachable for a governed member with no current organization access session: Billing, the SSO settings themselves, and leaving the organization. Everything else on the organization dashboard, and every private package, is refused as usual.

The first two stay open because an organization whose client secret expired, or whose administrator was deactivated in the provider by mistake, has to be able to repair the connection and keep paying. If SSO blocked those screens, a broken connection couldn't be fixed. While the provider is down, a required organization can fix its connection and keep its subscription, and cannot publish or fetch privately until the provider is back. If the subscription has lapsed as well, some repairs wait until it's active again; Seats and billing lists which.

Leaving stays open because it removes the member's own access instead of granting any, and it's the only option a member deactivated in the provider has. Without it, they couldn't authenticate or leave, and would still take up a billed seat.

Reaching any of the three that way is recorded in the organization's audit log, which names the screen. Reaching billing or the SSO settings is also emailed to the administrators, at most once an hour per member. Leaving is not emailed.

Turning enforcement off for the organization is allowed from the break-glass SSO screen. Exempting individual members isn't, because exemptions stay after the outage ends while the organization still shows as enforced. Changing exemptions needs a current organization access session.

The residual bypasses

A required organization can be reached without going through its identity provider in these ways:

  1. Exemptions, one per member, listed on the members tab.
  2. Organization keys, which authenticate as the organization. This is the audited automation exception; enforcement constrains and monitors it but cannot close it.
  3. Personal keys, unless the organization chose to block them.
  4. Break-glass on the billing and SSO settings screens, audited and mailed.
  5. The provisioning token, when provisioning is on. It authenticates as the provider's agent rather than as a person, so nothing about enforcement applies to it, and it keeps working after the administrator who generated it leaves. Every write it makes is audited. Delete it under Provisioning (SCIM) to close it.
  6. Readme URLs. A private package's readme renders on a separate host that never receives your Hexpm session cookie, so the package page signs a URL for it after taking its own authorization decision, and signs one for each image the readme contains. That URL renders that one readme for thirty minutes to anyone holding it. It isn't checked against enforcement, the session it was created from, or the member's membership, and reaching a readme this way isn't audited. It carries no other access: one package, one version, and the images in that readme.

Leaving the organization is also open under break-glass and audited the same way. It isn't listed here because it removes the member's access instead of granting it.

Offboarding

  • Removing a member in Hexpm takes effect within thirty minutes. The CDN verifies CLI and OAuth access tokens without a database lookup, so a token keeps its scopes until it is next refreshed. Access on hex.pm ends immediately, while private documentation is served with those tokens and follows the same thirty minutes.
  • Deactivating someone in your provider removes their membership here when provisioning is connected, which is the same as removing them by hand. Without provisioning, it takes effect when their organization access session expires, which is the lifetime you set; Hexpm does not learn about a provider-side deactivation until then.

Without provisioning, the session lifetime limits how long a provider-side deactivation takes to apply, so choose it instead of keeping the default. Removing the member in Hexpm revokes their access. Removing their provider assignment doesn't.

With just-in-time membership on, removing the member in Hexpm isn't enough on its own: their next login through your provider admits them again. Remove their provider assignment too.

Seats and billing

Configuring SSO takes an active subscription. Being governed by it does not. If a payment fails, enforcement stays as you set it: an organization that requires SSO keeps requiring it, and its members can still authenticate. The SSO settings and billing screens stay reachable through the break-glass path described above.

While the subscription is lapsed, the SSO screen can still rotate the client secret, test the connection, change enforcement, unlink accounts, disable SSO login, remove the configuration, and turn provisioning off, and provisioning keeps working with its existing token. Saving a configuration, turning SSO login on, changing the just-in-time membership or provisioning settings, and generating a provisioning token need an active subscription. An organization that disables SSO login while its subscription is lapsed can't turn it back on until the subscription is active again.

Just-in-time membership and provisioning are the only parts of SSO that can change a seat count, and each asks you to choose its behavior first: when the seats are full, the organization either adds a seat to the subscription or refuses the admission, depending on what you chose under When the seats run out. Enforcement on its own never adds, removes, or bills a seat.

Before you turn on required mode

  1. Link the administrators, or exempt at least one.
  2. Review the members tab and decide who, if anyone, is exempt.
  3. Check the personal-key list and decide whether to leave them allowed or block them.
  4. Pick a session lifetime.
  5. Set a required-by date far enough out for the grace-period email to reach people.

Turning enforcement on revokes nothing that already exists. Organization access sessions run out their lifetime and access tokens keep their scopes until they are next refreshed.

MFA and step-up

Your provider's MFA and Hexpm's two-factor authentication protect different things. The organization's provider enforces the organization's policy on every organization access session. Hexpm's own two-factor authentication enforces the account holder's policy on every account login. A member with both completes both, at different moments, and neither substitutes for the other.

An SSO authentication never suppresses a personal Hexpm two-factor prompt, because it never establishes the account session in the first place. It also never satisfies step-up re-authentication (sudo), which stays on credentials the account itself owns: password, GitHub, an authenticator code, or a recovery code. Configure the required MFA and conditional-access policy for organization access in your provider.

Your provider controls authentication to the SSO application. Organization membership and roles are stored in Hexpm, and your provider changes them only through just-in-time membership and provisioning. Removing a provider assignment removes the member from Hexpm only when provisioning is connected; otherwise, remove the member in Hexpm to revoke organization access.

Rotate the client secret

In Okta, open the application's General settings and use Client Credentials to generate a new secret. Keep the old secret active during the overlap; Okta documents this process in Client secret rotation. In Microsoft Entra, open the application's Certificates & secrets and add a new client secret; the old one stays valid until you delete it.

On the Hexpm SSO dashboard:

  1. Enter the new secret under Client secret rotation and select Save replacement.
  2. Select Test replacement and complete the provider sign-in.
  3. Select Complete rotation only after the replacement test succeeds.
  4. Return to your provider and deactivate or delete the old secret.

The active secret continues serving logins until the tested replacement is promoted.

Select Disable SSO login to stop new SSO logins immediately and revoke every organization access session the connection has granted. This does not remove the saved configuration or linked accounts, and conventional Hexpm login remains available. It does not stop provisioning either: the provisioning token keeps working until you delete it under Provisioning (SCIM).

Organization administrators can unlink an account from the Linked accounts section, which also ends that member's current organization access. Removing a member from the organization does the same and removes the SSO link. If the person is added again later, they must link again.

Remove SSO configuration deletes the connection itself, with the stored client secret, every linked account, and the recorded failures. SSO has to be disabled first. Members keep their Hexpm accounts and their organization membership, and anyone who wants SSO afterwards links again against a newly saved configuration.

Linked accounts shows when each member last authenticated through the connection.

Troubleshooting

The SSO dashboard shows recent failures using stable stage and error codes. Check these common causes:

  • Configuration cannot be saved: confirm that the issuer is an exact HTTPS URL and that its discovery and key endpoints are publicly reachable over HTTPS.
  • The provider rejects the callback: compare the redirect URI registered in the provider with the Redirect URI shown by Hexpm, including the scheme, host, path, and port.
  • Saving an Entra configuration reports an issuer mismatch: the issuer is common, organizations, or another tenant-independent endpoint. Use https://login.microsoftonline.com/{tenant-id}/v2.0.
  • Just-in-time membership refuses Entra users with provider_email_unverified: add the email and xms_edov optional claims to the application's ID token as described in Register the Entra application, and check that the person's email address is on a domain verified in your tenant.
  • The user cannot open the application: confirm that the user or one of their groups is assigned to the application.
  • The connection test fails: restart it from the same browser while signed in as the Hexpm administrator who saved the configuration and initiated the test. If that administrator is unavailable, disable SSO if it is enabled, have a current administrator save the existing configuration again, then test and re-enable it. Leaving the client secret blank while re-saving keeps the current secret.
  • Account linking says the account is not a member: add the existing Hexpm account to the organization, then restart from the organization login URL. With just-in-time membership on, check instead that the address your provider returns is on a verified domain, exactly.
  • A linked identity conflicts: unlink the existing organization link before attempting to connect the same provider identity or Hexpm account again.
  • The login says you are signed in as the wrong account: the provider identity belongs to a different Hexpm account. Sign in as that account, or ask an administrator to unlink it.

Do not send client secrets, authorization codes, tokens, cookies, or raw callback URLs to support. The stage and error code from Recent failures, the organization name, and the approximate time are sufficient for investigation.

Release scope

Enabled organizations can use the organization login URL and third-party-initiated login, with Okta or Microsoft Entra as the provider. Custom Okta dashboard tiles aren't supported, though they have been tested and work. There is no public Okta Integration Network listing because the integration was never submitted for review.

This release supports SCIM provisioning of members (the Users resource). It does not support SAML, account creation, group or role synchronization, or OIDC logout.

Organization 2FA enforcement is configured independently on the Members page. When both policies apply, members must satisfy both.