> ## Documentation Index
> Fetch the complete documentation index at: https://developers.useqx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SSO login with Okta

> How the IT team connects Okta to QX: the SSO login, user provisioning and required SSO.

This guide is for the Okta administrator of your company. It shows how to connect Okta to one QX organization. The work has two parts: the IT team configures Okta, and the owner of the organization configures QX. The [SSO login guide](/en/sso) explains the rules that apply to every provider.

## What QX offers

* A person signs in to QX with the SSO login in Okta, through the OIDC protocol. QX never sees the password.
* Okta creates, updates and deactivates the users of QX through user provisioning, with the SCIM 2.0 protocol. QX receives users only. The groups stay in Okta.
* By default, the role comes from QX: a new person signs in as an operator, and the owner changes the role in **Users**. If the company prefers, the owner group in Okta sets the role at each login.
* The owner can turn on the e-mail binding. With it, the first SSO login links the person to the QX user with the same e-mail.
* The owner turns on required SSO for the whole organization. With the rule on, nobody in the organization signs in with a password, including the owner.
* When the organization requires two-step verification, the SSO connection chooses where the person proves the second factor: in Okta or in the QX authenticator app.
* A session that starts with the SSO login expires at the time that the owner chooses, from 1 to 8 hours after the login. It does not extend.
* The owner removes the SSO connection to change the authorization server or the Okta app, and then configures a new one.

QX tests Okta Identity Engine. In the login test, the identity confirmation and the setup of the authenticator app, QX sends `prompt=login` and `max_age=0`. On Identity Engine, `max_age=0` forces a new login. Okta Classic uses `max_age=1`, and QX does not test Classic.

## The order of the work

Do the steps in this order:

1. The IT team creates the OIDC app in Okta.
2. The IT team assigns the app to the people and configures the groups.
3. The owner configures the SSO connection in QX.
4. The IT team pastes the QX login URL into the app.
5. The owner issues the provisioning key.
6. The IT team activates user provisioning in Okta.
7. The owner does the login test.
8. The owner enables SSO login.
9. The owner turns on required SSO.

Before you start, check two things:

* The Okta user of the owner has the same e-mail as the QX user of the owner.
* When the owner group sets the role, the owner is in that group.

## The QX addresses

The owner sees the addresses in **Settings › SSO**, in the box **Addresses for the identity provider**. Each address has a **Copy** button.

| Address in QX | Field in Okta |
| - | - |
| Login URL | **Initiate login URI**, in the OIDC app |
| Redirect URI | **Sign-in redirect URIs**, in the OIDC app |
| User provisioning base URL | **SCIM connector base URL**, in the SCIM settings |

The name **Initiate login URI** comes from the Okta help. The names of the other two fields follow the Okta Admin Console (not checked against an official source).

The login URL shows only after the owner saves the SSO connection. The other two addresses are these:

```text theme={null}
https://app.useqx.com/sso/callback
https://app.useqx.com/scim/v2
```

## 1. Create the OIDC app in Okta

The names of the menus and the fields in this list follow the Okta Admin Console (not checked against an official source).

1. In the Admin Console, open **Applications › Applications** and click **Create App Integration**.
2. Select **OIDC - OpenID Connect** and **Web Application**, and click **Next**.
3. In **App integration name**, type `QX`.
4. In **Grant type**, keep **Authorization Code**.
5. In **Sign-in redirect URIs**, paste the QX redirect URI.
6. Click **Save**. The **General** tab shows the client ID and the client secret.
7. In **Client authentication**, keep **Client secret**.
8. QX always sends PKCE with `S256`. The option **Require PKCE as additional verification** can stay on.
9. Copy the client ID and the client secret.

Okta offers the methods `client_secret_basic` and `client_secret_post` at the token endpoint. Which method a new app uses by default: not checked against an official source. In QX, start with **Basic (client\_secret\_basic)**. If the login test fails with "The login test failed.", switch to **Post (client\_secret\_post)** and test again.

Give the client ID and the client secret to the owner through a safe channel, such as a password manager.

## 2. Assign the app and configure the groups

1. Assign the app to the people or the groups that use QX. When the owner group sets the role, assign that group too.
2. Only when the owner group sets the role: make Okta send the `groups` claim in the ID token, as the list below explains.

When the owner group sets the role, QX asks for the `groups` scope at each login and reads the `groups` claim. When QX sets the role, QX does not ask for this scope. The values of the claim are the group names. Okta sends up to 100 groups.

* On the org authorization server (`https://<Okta domain>`), use the **Groups claim filter** of the app. Name the claim `groups` and choose a filter that includes the owner group, such as **Equals** with the group name. This filter puts the groups in the ID token only, which is the token that QX reads.
* On a custom authorization server (`https://<Okta domain>/oauth2/<server id>`), create on the server a claim `groups` with the value type **Groups**, in the ID token, with a filter that includes the owner group.

Whether a custom server needs a scope named `groups` to accept the QX request with the owner group: not checked against an official source. If Okta refuses the request because of the `groups` scope, create that scope on the server.

## 3. Configure the SSO connection in QX

The owner does these steps in QX:

1. Open **Settings › SSO** and click **Configure SSO connection**.
2. Select **Okta** and click **Continue**.
3. In **Identity provider address**, paste the issuer of the authorization server: `https://<Okta domain>` for the org server, or `https://<Okta domain>/oauth2/<server id>` for a custom server. Each Okta org has the custom server `default`. QX removes the slash at the end of the address. The address stays fixed after the owner saves the connection.
4. In **Client ID** and **Client secret**, paste the values of step 1.
5. In **Client authentication**, select the same method as the app: **Basic (client\_secret\_basic)** or **Post (client\_secret\_post)**.
6. In **Role of the people**, select **Set in QX** or **Set by the owner group**. With the second option, type in **Owner group** the name of the group exactly as Okta sends it at the login.
7. Only with the owner group: check the line "With the owner group, QX also asks for the groups scope."
8. If QX users will sign in before user provisioning links each one, select **Link QX users by e-mail**. The option works only when QX sets the role. Okta sends `email_verified`, which the binding needs.
9. In **Two-step verification**, select **Through Okta** or **Through the QX authenticator app**. The section **Two-step verification** of this guide explains the options.
10. In **SSO session duration**, select from 1 to 8 hours. The default is 8 hours.
11. Click **Save SSO connection**. If the login of the owner is older than 15 minutes, QX asks for the password.

After the save, the box **Addresses for the identity provider** shows the login URL.

QX compares the identity provider address with the `iss` of each token, character by character. With a custom domain, the issuer mode of the server (`ORG_URL`, `CUSTOM_URL` or `DYNAMIC`) decides the `iss`. In the `DYNAMIC` mode, the `iss` changes with the domain of the request. In QX, use the address that the `iss` of the tokens shows.

A change to the role of the people, the owner group, the e-mail binding or the two-step verification ends the sessions that started with SSO. Make the change outside working hours.

A new client ID or a new **Client authentication** needs the SSO login disabled and asks for a new login test. The owner makes the change in this order:

1. If required SSO is on, click **Turn off required SSO**.
2. Click **Disable SSO login**. All sessions that started with SSO end, including the session of the owner. The owner signs in again with the password, or creates a password with **Forgot your password?**.
3. Click **Edit SSO connection**, change the value and click **Save SSO connection**.
4. Click **Test login**.
5. Click **Enable SSO login**.
6. If required SSO was on, click **Turn on required SSO**.

## 4. Paste the login URL into Okta

1. Open the OIDC app in Okta.
2. In **Initiate login URI**, paste the QX login URL.
3. Select **Redirect to app to initiate login (OIDC Compliant)**.
4. Save the app.

The Okta dashboard opens QX through this address. Okta sends the `iss` parameter with the org address, also when QX uses a custom server. QX ignores this parameter and always starts a new login.

## 5. Issue the provisioning key

The owner does these steps in QX:

1. In **Settings › SSO**, click **Manage provisioning keys**.
2. Click **Issue provisioning key**, then **Issue key**. If the login of the owner is older than 15 minutes, QX asks for the password.
3. Copy the key. QX shows the key only once. The key starts with `qxp_`.
4. Give the key to the IT team through a safe channel. Do not send the key by e-mail or by message.
5. After the IT team pastes the key, check **I pasted the key into the identity provider** and click **Back to the keys**.

## 6. Activate user provisioning in Okta

Okta configures SCIM 2.0 in an App Integration Wizard app. Whether the OIDC app of step 1 offers SCIM provisioning: not checked against an official source. When the OIDC app does not offer it, use an Okta app with SCIM and assign the same people to it.

1. In the SCIM settings of the app, in **SCIM connector base URL**, paste the user provisioning base URL, with no slash at the end.
2. In **Unique identifier field for users**, select the e-mail. Okta looks for the person in QX by `userName` with this value.
3. In the authentication, select **HTTP Header** and paste the provisioning key as the bearer token.
4. Leave **Import Groups** and **Push Groups** off. QX does not receive groups.
5. Save. Okta calls `GET /Users?startIndex=1&count=2`, and QX answers with the list of users.
6. In the **Provisioning** tab, under **To App**, click **Edit**. Turn on **Create User**, **Update User Attributes** and **Deactivate Users**, and click **Save**.

QX recognizes the person by the `sub` of the login, which is the Okta user ID. User provisioning must send the same value in `externalId`. The create example of the Okta documentation sends the Okta user ID in `externalId`. Whether every App Integration Wizard app sends `externalId`: not checked against an official source.

Without `externalId`, QX refuses the create with the message "QX needs externalId to create or link a user when the SSO connection does not link users by e-mail". Then the owner selects **Link QX users by e-mail**. User provisioning then accepts a user with no `externalId`, and the first SSO login completes the binding.

What QX does with the calls of Okta:

* Okta updates the user with a `PUT` of the whole user. A `PUT` with no `externalId` keeps the value that QX stored.
* Okta sends a placeholder password in the create. QX ignores the password.
* To deactivate the person, Okta sends `active=false` in a `PUT`. Okta never sends `DELETE`.

## 7. Do the login test

1. In **Settings › SSO**, the owner clicks **Test login**.
2. QX opens Okta and asks for a new login. The owner signs in with their own user.
3. QX shows "The login test passed. The SSO connection is verified."

The test links the Okta user of the owner to the QX user of the owner. User provisioning does not need to link the owner first. The test needs `auth_time` in the token, and Okta sends this claim at each login.

The test needs two things:

* When the owner group sets the role, the owner is in the owner group.
* When the organization requires two-step verification through Okta, the owner signs in to Okta with the second factor.

## 8. Enable SSO login

1. In **Settings › SSO**, the owner clicks **Enable SSO login**. If the login of the owner is older than 15 minutes, QX asks for the password.
2. A person who is not an owner opens QX from the Okta dashboard and checks the login.

A person signs in to QX from the Okta dashboard. The QX page **Sign in with SSO** asks the person to open QX from the portal of the identity provider.

## 9. Turn on required SSO

1. In **Settings › SSO**, the owner clicks **Turn on required SSO**.
2. The owner reads the warning and clicks **Turn on required SSO** again. If the login of the owner is older than 15 minutes, the warning asks for the password.

Each session that started with a password in the organization ends, including the session of the owner. From then on, each user of the organization signs in with the SSO login.

## Two-step verification

The option of the SSO connection applies when the organization requires two-step verification. A change of the option ends the sessions that started with SSO.

* **Through Okta**: QX sends `acr_values=urn:okta:loa:2fa:any` in each request to Okta. QX accepts the SSO login only when the `acr` of the token is `urn:okta:loa:2fa:any`. With this option, QX does not read the `amr`. A token with no `acr`, or with a single factor value such as `urn:okta:loa:1fa:any`, does not pass.
* **Through the QX authenticator app**: after the login in Okta, the person types the code of the QX authenticator app. At the first login, the person sets up the app. The person has 15 minutes to finish. After that time, the person signs in again through Okta.

After a switch to **Through Okta**, do the login test with the second factor.

A person who signs in with SSO can also set up the authenticator app in **Account security**. Before the setup, QX asks for a new login in Okta. To change the app, the person asks another owner or QX support for a reset of the second factor.

## Session duration

The owner chooses the SSO session duration in **Edit SSO connection**, from 1 to 8 hours. After that time, the person signs in again through Okta. A shorter time also shortens the open sessions, counted from the login. A longer time applies to the next logins only. The identity confirmation does not change the time.

## How QX treats each person

* User provisioning creates the user of a new person. The **Users** screen shows "Waiting for SSO login". The first SSO login activates the user. A new user is an operator.
* When the person already has a QX user, user provisioning links that user by the e-mail, in the same organization. The user keeps the history.
* When QX sets the role, the owner changes the role in **Users**, and the SSO login does not change the role.
* When the owner group sets the role, the role changes at the next SSO login after a group change. A person in the group signs in as an owner, and the other people sign in as operators. The role is read-only in **Users**.
* QX does not create a user at the first login through Okta. A person with no QX user signs in after user provisioning creates the user.
* To deactivate a person, remove the app assignment or deactivate the person in Okta. Okta sends `active=false`, and QX deactivates the user. All sessions of the user end at the same moment.
* Okta sends nothing to QX when it suspends a person. The sessions of that person in QX continue until they expire. To end the access at once, deactivate the person. A short duration limits the time of the open sessions.
* When Okta sends `active=true` for a deactivated user, the user goes back to "Waiting for SSO login" and signs in again at the next SSO login.
* Okta never deletes a QX user. The deactivated user and its history stay in QX.
* The name and the e-mail of the person change only in Okta. The owner sees the user in QX, but does not change them.
* A new e-mail in Okta does not block the SSO login. The user page shows the Okta e-mail when it differs from the e-mail in QX.

## Replace the provisioning key

The SSO connection keeps up to 2 active keys. With two keys, Okta switches to the new key with no gap in user provisioning.

1. The owner issues a new key, as in step 5. In a session that started with SSO, when the login is older than 15 minutes, QX asks for the identity confirmation in Okta.
2. The IT team pastes the new key into the **HTTP Header** authentication of the SCIM settings of the app and saves.
3. The owner checks the **Last use** column of the new key.
4. The owner clicks **Revoke** on the old key, then **Revoke key**.

## Replace the client secret

1. In Okta, the IT team generates a new client secret in the **General** tab of the app (not checked against an official source).
2. The owner opens **Edit SSO connection**, pastes the new secret into **Client secret** and clicks **Save SSO connection**.

A new client secret ends all sessions that started with SSO in the organization. Make the change outside working hours.

## When Okta is down

With required SSO on, nobody signs in to QX while Okta is down. The open sessions continue until they expire.

1. If an owner still has an open session, the owner clicks **Turn off required SSO** in **Settings › SSO**. QX asks for no confirmation, so this works while Okta is down.
2. If no owner has an open session, ask QX support. Support turns off required SSO and writes the reason in the audit log.
3. A person with no password clicks **Forgot your password?** on the login page and sets a password.
4. When Okta is back, the owner clicks **Turn on required SSO**.

A user that user provisioning created, and that never signed in to QX, cannot sign in with a password. That user waits for Okta to come back.

## Remove the SSO connection

To change the authorization server, the domain or the Okta app, the owner removes the SSO connection and configures a new one. The new connection has another login URL.

1. In **Settings › SSO**, the owner clicks **Remove connection**. If the login of the owner is older than 15 minutes, QX asks for the password or for the identity confirmation.
2. The owner reads the warning and clicks **Remove connection** again.

The removal has these effects:

* The sessions that started with SSO end, including the session of the owner.
* SSO login and required SSO stop. People sign in with a password.
* QX deletes the external identities and the provisioning keys. Okta stops creating and deactivating users in QX. Turn off provisioning in the old Okta app.
* The users stay in QX. A person who only signed in with SSO creates a password with **Forgot your password?**, on the login page.

If no owner can sign in, ask QX support. Support removes the connection and writes the reason in the audit log.

## Refusal messages

| Message that the person sees | What the IT team checks |
| - | - |
| Your organization requires a second factor. | The `acr` of Okta, as in the section **Two-step verification**. The person signs in to Okta with the second factor. |
| The time to finish the login ran out. Sign in again through the identity provider. | The person types the code of the QX authenticator app within 15 minutes after the login in Okta. |
| The identity provider did not send the groups of your user. | The `groups` claim of the app or of the authorization server, when the owner group sets the role. |
| Your QX user is an owner. To use the SSO login, run the login test in Settings > SSO. | The owner runs the login test. QX never links an owner by e-mail. |
| Your access to QX is turned off. | The state of the person in Okta and the app assignment. |
| QX did not find your user. | The e-mail of the person in Okta and in QX, user provisioning and the option **Link QX users by e-mail**. |
| The identity provider did not ask for a new login. | Okta Classic. QX tests Okta Identity Engine only. |
| The identity provider did not answer. | The Okta status. Try again in a few minutes. |
| We could not sign you in with SSO. | **Client authentication**, the client secret, the **Identity provider address** and, with the owner group, the `groups` scope on the authorization server. |

## Sources

* Okta, [Authorization servers](https://developer.okta.com/docs/concepts/auth-servers/).
* Okta, [OpenID Connect & OAuth 2.0 API](https://developer.okta.com/docs/api/openapi/okta-oauth/guides/overview/).
* Okta, [Customize tokens returned from Okta with a Groups claim](https://developer.okta.com/docs/guides/customize-tokens-groups-claim/main/).
* Okta, [Step-up authentication](https://developer.okta.com/docs/guides/step-up-authentication/main/).
* Okta, [Custom URL domain](https://developer.okta.com/docs/guides/custom-url-domain/main/).
* Okta, [Create OIDC app integrations](https://help.okta.com/en-us/content/topics/apps/apps_app_integration_wizard_oidc.htm).
* Okta, [Develop a custom OpenID Connect application that can support SSO when launched from the Okta dashboard](https://support.okta.com/help/s/article/develop-a-custom-openid-connect-application-that-can-support-sso-when-launched-from-the-okta-dashboard).
* Okta, [Okta and SCIM Version 2.0](https://developer.okta.com/docs/api/openapi/okta-scim/guides/scim-20/).
* Okta, [SCIM FAQs](https://developer.okta.com/docs/concepts/scim/faqs/).
* Okta, [Create SCIM app integrations](https://help.okta.com/en-us/content/topics/apps/apps_app_integration_wizard_scim.htm).
* Okta, discovery documents of the servers of the org `okta.okta.com`: `https://okta.okta.com/.well-known/openid-configuration` and `https://okta.okta.com/oauth2/default/.well-known/openid-configuration`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.