# Authentication

Once an app is deployed, its URL is publicly available. Protect it so only the right people can open it, and choose the method that fits your audience. You set it in the app's configuration under **Authentication → Authentication Type**, which offers six options.

![The Authentication Type dropdown in an app's configuration, listing None, Basic, OIDC, GitLab, GitHub, and JumpCloud](/data-apps/auth-options.png)

## Authentication methods

- **None (Public Access)** — the app is public to anyone with the URL. You can still add your own authorization inside the app; for Streamlit, use the [Streamlit authenticator](https://github.com/mkhorasani/Streamlit-Authenticator) ([example](https://github.com/keboola/mkt-bi-ocr/blob/master/Select_Invoices.py)).
- **Basic (Password)** — the **default** for new apps. Keboola generates a shared password; users enter it before the app opens. Once the app is deployed, click **Open App** on its configuration page: the dialog has the app's address and the password, each with a copy button. When Kai builds an app, it shows the password as the last step.
- **OIDC (Custom)** — users sign in with your identity provider (Google, Microsoft Entra ID, Okta, Auth0, or any other OIDC provider). Recommended for anything beyond a quick share.
- **GitHub** — restrict access with GitHub OAuth by organization, team, repository, or allowed users.
- **GitLab** — restrict access with GitLab OAuth by groups, projects, or roles.
- **JumpCloud** — restrict access with JumpCloud OIDC, with optional role-based filtering.

## OIDC (single sign-on)

:::note[Do you actually need OIDC?]
Only set this up if people must sign in with their **company accounts** — so that access follows your directory, and someone who leaves the company loses it. **Basic (Password)** is the only method that needs nothing outside Keboola: it shares one password and you're done. **GitHub**, **GitLab** and **JumpCloud** also restrict access by organization or team, and they still need an OAuth app in that provider's console, but no consent screen and no audience decision — noticeably less work than OIDC.
:::

OIDC lets users log into your app through your single sign-on (SSO) provider. Keboola has ready-made provider options for Google (**Google SSO**), Microsoft Entra ID (**Azure OIDC**), **Okta**, and **Auth0**, plus **Generic OIDC** for any other OpenID Connect provider. Users sign in with the provider you configured; if an app has more than one provider, they first pick an **Authentication Provider**.

![The app's sign-in page asking the user to select an authentication provider, one button per configured provider](/data-apps/auth-select-oidc-provider.png)

The flow is the same everywhere: open the app in Keboola, register it with your provider using the app's callback URL, paste the provider's credentials into the app's **Authentication** settings, and deploy. Expect about 15 minutes of clicking in two browser tabs, and longer the first time in a Google Cloud project that has no consent screen yet. It needs admin rights in the provider's console: for Google, the **Owner** or **OAuth Config Editor** role on a Google Cloud project; for the others, the right to register applications in your tenant. Kai and kbagent can't do this part for you.

### Step 1 — Open the app and copy its callback URL

Your provider needs the app's callback URL, so start in Keboola.

1. In your Keboola project, open **Apps** and click the app. It doesn't matter whether Kai built it or you created it yourself. No app yet? [Create one manually](/data-apps/getting-started/#create-an-app-manually) first; it opens on its configuration page.
2. Under **Authentication**, find the read-only **Callback URL** field and click its copy button. That is the exact value your provider needs. It appears for OIDC, GitHub, GitLab and JumpCloud, and not for None or Basic, which need no callback.

   No such field? Build the URL yourself from the **App URL** block on the **Overview** tab. That block shows the app's host as a URL prefix plus a generated part, for example `toy-store-sales` and `-74016144.hub.europe-west3.gcp.keboola.com`, and its copy button gives you the app's URL rather than the callback URL. Add `/_proxy/callback` to the end:

   ```
   https://<url-prefix>-<app-id>.hub.<stack-host>/_proxy/callback
   ```

   For example: `https://toy-store-sales-74016144.hub.europe-west3.gcp.keboola.com/_proxy/callback`

   An app created without a URL prefix has no hyphenated part, so its callback URL is `https://<app-id>.hub.<stack-host>/_proxy/callback`.

   Either way, the value exists from the moment the app does; you don't have to deploy first.

The block sits below **Authentication**:

![The app's Overview tab: Description, Authentication, and Git Repository cards, then the App URL block, with the App Info panel on the right](/data-apps/build-in-ui-config.png)

Keep this tab open. You now have the callback URL; each app has its own, so register every app with your provider separately.

### Step 2 — Set up your identity provider

Pick your provider:

**Google Cloud**

Let people sign in with their Google account.

**Before you start**

You need:

- **A Google Cloud project** where you can manage the consent screen and OAuth clients: the **Owner** role, or the **OAuth Config Editor** role. The OAuth client lives in the Google Cloud project, not in the Google Workspace admin console.
- **A decision on who should get in.** With the sign-in scopes Keboola requests (`openid`, `email`, `profile`), an **Internal** audience limits sign-in to your Google Workspace organization (the project must belong to that organization), and an **External** audience lets in anyone with a Google account.

**Set up the consent screen.** Google keeps it under **Google Auth Platform**; open it directly at [console.cloud.google.com/auth/overview](https://console.cloud.google.com/auth/overview) and pick your project.

1. If the page says **Google Auth Platform not configured yet** and offers **Get started**, the project has no consent screen yet. Click it and fill in the wizard: **App name** and **User support email**, the **Audience** (**Internal** or **External**, see above), a contact email, then tick the User Data Policy box and click **Create**. If the page shows your app's details instead, the consent screen already exists; carry on. (**Branding**, **Audience** and **Clients** sit in the left menu either way, so they don't tell you which case you're in.)
2. Optional: open [**Branding**](https://console.cloud.google.com/auth/branding) and add `keboola.com` under **Authorized domains**. Google adds it for you when you save the redirect URI in the next step ("The domains of the URIs you add below will be automatically added to your OAuth consent screen as authorized domains"), so this is only worth doing if you want it in place beforehand.
3. Check [**Audience**](https://console.cloud.google.com/auth/audience). An **Internal** app shows only its user type; an **External** one also shows **Publishing status**, an **OAuth user cap** and a **Test users** list. Ignore all three. Google's own text there says that while the status is Testing "only test users are able to access the app", and that is not true for a Keboola app: the proxy asks for the `openid`, `email` and `profile` scopes only, and Google exempts exactly that set from the test-user rule, so an External app lets any Google account in whether or not you publish it. Publishing only matters if you want your app name and logo shown on the consent screen, and then Google asks for branding details and a verification review.

4. Know what the audience buys you: it is the only access control Google SSO offers here. Anyone in the audience you chose can open the app — there is no group or user filter, and Keboola takes only a Client ID and secret for this provider. To narrow it further, use Microsoft Entra ID or Okta, which do have assignment, or check the signed-in user inside the app itself.

You now have: a consent screen with `keboola.com` authorized and the audience you want.

**Create the OAuth client:**

1. Open [**Clients**](https://console.cloud.google.com/auth/clients) and click **Create client**.
2. Set **Application type** to **Web application** and give the client a name, for example `Keboola app - Toy store sales`.
3. Under **Authorized redirect URIs**, click **Add URI** and paste the callback URL from step 1, for example `https://toy-store-sales-74016144.hub.europe-west3.gcp.keboola.com/_proxy/callback`. It has to match exactly: `https`, the full host, `/_proxy/callback`, no trailing slash, no stray spaces.
4. Click **Create**. Copy the **Client ID** and the **Client secret** now; Google shows the secret only at creation. If you lose it, open the client and click **Add Secret**.

You now have: a Client ID and a Client secret.

**Back in Keboola.** On the app's configuration page, under **Authentication**, set **Authentication Type** to **OIDC (Custom)**, select **Google SSO** in the **Provider** dropdown, paste the **Client ID** and **Client secret** (this option has no issuer field), and click **Save**. After saving, the secret field is masked. Reveal it with the eye icon and you'll see an encrypted value starting with `KBC::ProjectSecure` rather than what you pasted. That is your secret stored [encrypted](/extend/encryption/), not a replacement; the rest of the prefix depends on which cloud your stack runs on. To change it later, paste a new value over it.

**If sign-in fails:**

- **Access blocked: This app's request is invalid**, with `Error 400: redirect_uri_mismatch` — the URI in the OAuth client differs from the app's callback URL. Open **Request details** on that page: it shows the `redirect_uri` Google received. Compare it with the **App URL** block character by character (a stray space or a missing character is the usual cause) and fix the client.
- Someone outside your organization can't sign in — expected with the Internal audience. Switch to External on the **Audience** page if that's not what you want.
- Someone outside your organization *can* sign in — the audience is External. For the scopes Keboola uses, Google doesn't limit an External app to its test users, even in Testing. Switch to Internal.
- `invalid_client`, or a token error right after signing in — the Client ID or Client secret in Keboola doesn't match the OAuth client. Paste them again, or add a new secret in Google Cloud and update the app.

Changed the redirect URI or the audience on Google's side later? No redeploy needed; Google says such changes take from a few minutes to a few hours to apply.
*Console steps walked through on 2026-09-22.*

**Microsoft Entra ID**

Let people sign in with their Microsoft work account.

**Before you start**

You need:

- **Permission to register applications** in your tenant. The **Application Developer** role is enough for the registration itself.
- **The Cloud Application Administrator or Application Administrator role**, or ownership of the app's service principal, if you want to restrict who can sign in.

**Register the app:**

1. Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/) and go to **Entra ID → App registrations → New registration**.
2. Enter a **Name** your users will recognize.
3. Under **Supported account types**, keep the single-tenant option, which names your tenant: **Single tenant only**, or **Accounts in this organizational directory only** in older portal builds. Only users and guests of your tenant can sign in.
4. Under **Redirect URI (optional)**, choose **Web** and paste the callback URL from step 1.
5. Click **Register**. The app's **Overview** page opens. Copy the **Application (client) ID** and the **Directory (tenant) ID**; Keboola needs both.

**Create a client secret:**

1. Under **Manage**, open **Certificates & secrets** and click **New client secret**.
2. Enter a description, pick an expiry, and click **Add**. Microsoft caps the lifetime at 24 months and recommends under 12.
3. Copy the secret's **Value** right away; Entra hides it once you leave the page. Note the expiry, too: before it passes, create a new secret and update the app's authentication settings, or sign-in stops working.

You now have: an Application (client) ID, a Directory (tenant) ID, and a client secret Value.

**Optional — restrict who can sign in.** Out of the box, anyone in your tenant can open the app. To let in only specific people or groups, go to **Entra ID → Enterprise apps**, open your app, and under **Manage → Properties** set **Assignment required?** to **Yes**. Then, under **Manage → Users and groups**, click **Add user/group**, pick who may sign in, leave **Select a role** on its default, and click **Assign**. Nothing is saved until you do. Assigning groups, rather than single users, needs a Microsoft Entra ID P1 or P2 license. Everyone else now gets `AADSTS50105` at sign-in, with one exception that will mislead you: the requirement doesn't apply to Global Administrators, so test with an ordinary account rather than your own.

**Back in Keboola** — on the app's configuration page, under **Authentication**, set **Authentication Type** to **OIDC (Custom)**, select **Azure OIDC** in the **Provider** dropdown, and paste the **Client ID**, **Client secret**, and **Tenant ID**. Keboola builds the issuer from the tenant ID (`https://login.microsoftonline.com/<tenant ID>/v2.0`). Click **Save**.

**If sign-in fails:**

- `AADSTS50011: The redirect URI … does not match` — the redirect URI in the registration differs from the app's callback URL. Fix it under **Manage → Authentication**.
- `AADSTS7000215: Invalid client secret is provided` — the secret expired, or you pasted the secret's **Secret ID** instead of its **Value**. Create a new one and update the app.
- `AADSTS50105: … is not assigned to a role for the application` — you required assignment and this user isn't assigned. Add them under **Enterprise apps → your app → Users and groups**.
*Checked against Microsoft's documentation on 2026-09-23. Not yet walked through a live tenant, and the Entra admin center changes often, so check the menu names as you go.*

**Okta**

Let people sign in with their Okta account.

**Before you start**

You need:

- **Admin access to your Okta org** (the **Application Administrator** or **Super Administrator** role), to create app integrations.

**Create the app integration:**

1. In the Okta Admin Console, go to **Applications and Resources → Applications** (**Applications → Applications** in Classic Engine orgs) and click **Create App Integration**. If Okta asks which experience to use, choose **Classic experience**.
2. Choose **OIDC - OpenID Connect** as the **Sign-in method** and **Web Application** as the **Application type**, then click **Next**.
3. Enter an **App integration name**, for example `Keboola app - Toy store sales`.
4. Under **Sign-in redirect URIs**, enter the callback URL from step 1. Leave an entry under **Sign-out redirect URIs** if you plan to set a **Logout URL** in Keboola later; Okta only returns people to a URI registered there.
5. Under **Assignments**, decide who can sign in: **Allow everyone in your organization to access** or **Limit access to selected groups** (or skip the assignment for now and add people later).
6. Click **Save**. On the **General** tab, under **Client Credentials**, copy the **Client ID** and the **Client secret**.

You now have: a Client ID and a Client secret, and Okta knows your callback URL.

**Back in Keboola** — on the app's configuration page, under **Authentication**, set **Authentication Type** to **OIDC (Custom)**, select **Okta** in the **Provider** dropdown, and paste the **Client ID** and **Client secret**. Set **Domain/Org URL** to the issuer of the authorization server you want to use; your Okta domain is shown in the Admin Console when you click your name at the top right. For plain single sign-on, Okta points you at the **org authorization server**, whose issuer is the bare domain with no path, for example `https://acme.okta.com`. Custom authorization servers need API Access Management, a paid add-on in production orgs. If your org has one, its issuer is `https://acme.okta.com/oauth2/default`, which is also what the field's example shows, and you can check under **Security → API → Authorization Servers**. One trap on an Integrator Free Plan org: the `default` server there ships **without an access policy**, and every token request fails until you add one. Open **Security → API → default → Access Policies** and add a policy that applies to your app. **Logout URL** is optional: use the `end_session_endpoint` from the discovery document of whichever server you chose, at `https://<yourOktaDomain>/oauth2/default/.well-known/openid-configuration` or `https://<yourOktaDomain>/.well-known/openid-configuration` for the org server. Okta returns people to a URI registered under **Sign-out redirect URIs**, so keep one there that matches. Click **Save**.

**If sign-in fails:**

- "The 'redirect_uri' parameter must be a Login redirect URI in the client app settings" — the URI in the integration differs from the app's callback URL. Fix **Sign-in redirect URIs** on the integration's **General** tab.
- "User is not assigned to the client application" — the user, or their group, isn't assigned to the integration. Add them on the **Assignments** tab.
- Issuer or discovery error when the app starts the sign-in — check **Domain/Org URL** against the `issuer` in that server's discovery document, character for character, with no trailing slash. If sign-in reaches Okta and then fails on a free-plan org, check that the `default` authorization server has an access policy.

*Checked against Okta's documentation on 2026-09-23. Not yet walked through a live org, so check the menu names as you go.*

**Auth0**

Let people sign in through Auth0, with whatever connections your tenant offers: username and password, social logins, or enterprise identity providers.

**Before you start**

You need:

- **The Admin role** on your Auth0 tenant; the Editor roles can't create applications.

**Register the application:**

1. In the [Auth0 Dashboard](https://manage.auth0.com/), go to **Applications → Applications** and click **Create Application**.
2. Name it, choose **Regular Web Applications**, and click **Create**.
3. Open the **Settings** tab. Under **Basic Information**, copy the **Domain**, **Client ID**, and **Client Secret**.
4. Scroll down to **Application URIs** and paste the callback URL from step 1 into **Allowed Callback URLs**. If you plan to set a **Logout URL** in Keboola, add the app's URL to **Allowed Logout URLs** in the same block; Auth0 refuses any post-logout redirect that isn't registered there.
5. Click **Save Changes** at the bottom of the page.

You now have: your tenant Domain, a Client ID, and a Client Secret.

**Back in Keboola** — on the app's configuration page, under **Authentication**, set **Authentication Type** to **OIDC (Custom)**, select **Auth0** in the **Provider** dropdown, and paste the **Client ID** and **Client secret**. Set **Issuer URL** to the `issuer` value from your tenant's discovery document, at `https://<the domain your users sign in through>/.well-known/openid-configuration`. That's your custom domain if you have one, otherwise the **Domain** from step 3, and the two produce different issuers. Copy it character for character. Auth0 issuers normally end in a slash, for example `https://acme.us.auth0.com/` or `https://login.acme.com/`, while the field's own example omits it. **Logout URL** is optional: `https://<yourAuth0Domain>/oidc/logout` also ends the Auth0 session when someone signs out of the app. Click **Save**.

**If sign-in fails:**

- "Callback URL Mismatch" on an Auth0 error page, with a line reading "`{URL}` is not in the list of allowed callback URLs" — the URL in **Allowed Callback URLs** differs from the app's callback URL. Fix it under **Settings → Application URIs**.
- Issuer mismatch or discovery error when the app starts the sign-in — the **Issuer URL** must match the `issuer` in Auth0's discovery document character for character: `https://`, your Auth0 domain, trailing slash.
- Users of one connection can't sign in — that connection isn't enabled for this application. Turn it on under the application's **Connections** tab.
*Checked against Auth0's documentation on 2026-09-23. Not yet walked through a live tenant, so check the menu names as you go.*

**Another provider**

Any OpenID Connect provider works through the **Generic OIDC** option.

1. In the provider's console, register an OIDC / OAuth 2.0 **web application** and set the callback URL from step 1 as its redirect URI.
2. Copy the **Client ID** and **Client secret**.
3. Find the provider's **issuer URL**. It's the `issuer` value in the provider's discovery document, usually at `https://<provider-host>/.well-known/openid-configuration`. Copy it exactly, trailing slash included or omitted as the document has it — Keboola verifies it character for character.
4. Back in Keboola, set **Authentication Type** to **OIDC (Custom)**, select **Generic OIDC** in the **Provider** dropdown, and paste the **Client ID**, **Client secret**, and **Issuer URL**. **Logout URL** is optional; it ends the provider's session when someone signs out of the app. Click **Save**.

The Okta and Auth0 tabs walk through the same flow with a real console, so they make a useful template.

### Step 3 — Deploy and test

1. A new app: set its code source and click **Deploy App**; the short wizard asks for the backend version, the backend size and an inactivity timeout (details: [Create an app manually](/data-apps/getting-started/#create-an-app-manually)). Just testing sign-in? A **Streamlit** app with a one-line inline script is the quickest thing to deploy. An app that's already running needs **Redeploy App** for the new authentication to take effect; a stopped one, **Start App**.
2. When the status turns **Active**, click **Open App**. Your provider asks you to sign in and, the first time, to allow the app to see your name and email address; then it sends you into the app. If the page still says the app is stopped right after a deploy, reload it — the status catches up a moment later.
3. Test with the accounts that matter: one that should get in, one that shouldn't. Once you're in, the app's own session cookie keeps you signed in, so a second try in the same window proves nothing — use a fresh private window, or open `https://<your-app-url>/_proxy/sign_out` to end the app session and start over.

   Know what a correct rejection looks like before you read it as a fault. With Google and an **Internal** audience, an account from outside your organization is stopped by Google with a message that the app is restricted to its organization — that is the app working. Do **not** switch the audience to **External** to make that message go away; it opens the app to every Google account there is. The reverse is the quiet failure: if an outside account lands in the app, your audience is External and the app is public to anyone signed in to Google.

### Provider settings at a glance

| Provider | Keboola provider option | What you enter besides Client ID and Client secret |
|---|---|---|
| **Google Cloud** | Google SSO | Nothing; the issuer `https://accounts.google.com` is preset |
| **Microsoft Entra ID** | Azure OIDC | **Tenant ID**; Keboola derives the issuer `https://login.microsoftonline.com/<tenant ID>/v2.0` |
| **Okta** | Okta | **Domain/Org URL**: `https://<yourOktaDomain>/oauth2/default` |
| **Auth0** | Auth0 | **Issuer URL**: `https://<yourAuth0Domain>/` |
| Any other | Generic OIDC | **Issuer URL** from the provider; **Logout URL** optional |

`<yourOktaDomain>` and `<yourAuth0Domain>` are your tenant hosts, for example `acme.okta.com` or `acme.us.auth0.com`.

## GitHub authentication

Restrict access to your app using GitHub OAuth. Users authenticate via their GitHub account, and you can optionally restrict access to specific organizations, teams, repositories, or individual users.

### Required fields

| Field | Description | Example |
|---|---|---|
| **Client ID** | Client ID from GitHub Developer Settings > OAuth Apps. | `Ov23liABCDEF123456` |
| **Client Secret** | Client Secret from the same GitHub OAuth App. | *(paste your GitHub secret)* |

### Optional fields

| Field | Description | Example |
|---|---|---|
| **GitHub URL** | Your GitHub Enterprise Server URL. Leave empty for public GitHub. | `https://github.com` |
| **Organization** | URL slug of your GitHub organization. Restricts access to organization members. | `my-company` |
| **Team** | URL slug of the team within the organization. Requires Organization to be set. | `data-engineers` |
| **Repository** | Restrict to repository collaborators. Format: `owner/repo-name`. | `my-company/analytics` |
| **Access Token** | Required for private org/team/repo restrictions. Needs `read:org` scope. Generate at GitHub > Settings > Developer Settings > Personal Access Tokens. | `ghp_...` |
| **Allowed Users** | Comma-separated GitHub usernames. If set, only these users can log in. | `jane-smith, john-doe` |

### Setup instructions

1. Go to your GitHub account **Settings > Developer Settings > OAuth Apps** and create a new OAuth App.
2. Set the **Authorization callback URL** to the app's callback URL. Copy it from the **Callback URL** field under **Authentication**, or build it as `https://<url-prefix>-<app-id>.hub.<stack-host>/_proxy/callback` (e.g., `https://my-app-12345678.hub.north-europe.azure.keboola.com/_proxy/callback`).
3. Copy the **Client ID** and **Client Secret** from the created OAuth App.
4. In your Keboola app configuration, select **GitHub** as the authentication method.
5. Paste the **Client ID** and **Client Secret**.
6. Optionally configure organization, team, repository, or allowed users restrictions.
7. If you use organization, team, or repository restrictions with a private organization, provide an **Access Token** with `read:org` scope.
8. Save and redeploy your app.

## GitLab authentication

Restrict access to your app using GitLab OAuth. Users authenticate via their GitLab account, and you can optionally restrict access by groups, projects, or roles.

### Required fields

| Field | Description | Example |
|---|---|---|
| **Client ID** | Application ID from GitLab > Settings > Applications. | `a1b2c3d4e5f6...` |
| **Client Secret** | Application secret from the same GitLab application. | `gloas-xxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
| **GitLab Instance URL** | Use `https://gitlab.com` for public GitLab, or your self-hosted URL. | `https://gitlab.com` |

### Optional fields

| Field | Description | Example |
|---|---|---|
| **Groups** | Only members of these groups can access the app. Use the URL path, not the display name. Separate multiple groups with commas. | `my-org/data-team` |
| **Projects** | Restrict access to members of these projects. Format: `namespace/project-slug`. | `my-org/analytics-app` |
| **Allowed Roles** | Leave empty to allow any role. Valid values: `guest`, `reporter`, `developer`, `maintainer`, `owner`. | `developer, maintainer` |

### Setup instructions

1. Go to your GitLab instance **Settings > Applications** and create a new application.
2. Set the **Redirect URI** to the app's callback URL. Copy it from the **Callback URL** field under **Authentication**, or build it as `https://<url-prefix>-<app-id>.hub.<stack-host>/_proxy/callback` (e.g., `https://my-app-12345678.hub.north-europe.azure.keboola.com/_proxy/callback`).
3. Ensure the `openid`, `profile`, and `email` scopes are selected. If you use group or project restrictions, also select `read_api`.
4. Copy the **Application ID** and **Secret**.
5. In your Keboola app configuration, select **GitLab** as the authentication method.
6. Paste the **Client ID**, **Client Secret**, and **GitLab Instance URL**.
7. Optionally configure groups, projects, or allowed roles restrictions.
8. Save and redeploy your app.

## JumpCloud authentication

Restrict access to your app using JumpCloud OIDC. Users authenticate via their JumpCloud account, and you can optionally restrict access by roles.

### Required fields

| Field | Description | Example |
|---|---|---|
| **Client ID** | Client ID from JumpCloud Admin Console > SSO > your app. | `6507c80f5f2b490a...` |
| **Client Secret** | Client Secret from JumpCloud Admin Console > SSO > your app > SSO tab. Treat like a password. | *(paste your JumpCloud secret)* |
| **Issuer URL** | Pre-filled. For custom tenants, ask your JumpCloud admin for the correct issuer URL. | `https://oauth.id.jumpcloud.com/` |
| **Logout URL** | Pre-filled. Change only if your JumpCloud admin provides a different logout endpoint. | `https://oauth.id.jumpcloud.com/oauth2/sessions/logout` |

### Optional fields

| Field | Description | Example |
|---|---|---|
| **Allowed Roles** | Role values must match exactly what is set in JumpCloud's attribute mapping. Leave empty to allow any authenticated user. | `data-analyst, admin` |

### Setup instructions

1. In the **JumpCloud Admin Console**, go to **SSO** and create a new application (or use an existing one).
2. Configure the application as an **OIDC** application.
3. Set the **Redirect URI** to the app's callback URL. Copy it from the **Callback URL** field under **Authentication**, or build it as `https://<url-prefix>-<app-id>.hub.<stack-host>/_proxy/callback` (e.g., `https://my-app-12345678.hub.north-europe.azure.keboola.com/_proxy/callback`).
4. Copy the **Client ID** and **Client Secret** from the SSO tab.
5. In your Keboola app configuration, select **JumpCloud** as the authentication method.
6. Paste the **Client ID**, **Client Secret**, **Issuer URL**, and **Logout URL**.
7. Optionally configure allowed roles to restrict access.
8. Save and redeploy your app.

## Callback URL format

Every method that uses OAuth or OIDC needs a callback URL, and the app's configuration gives you the finished value: the **Callback URL** field under **Authentication**, with a copy button. Copy it rather than typing it. A single wrong character is the most common reason sign-in fails, and the provider reports it as a redirect mismatch rather than as a typo.

The rest of this section is for reading a URL you already have, or for a stack where the field hasn't appeared yet.

```
https://<url-prefix>-<app-id>.hub.<stack-host>/_proxy/callback
```

For example: `https://my-app-12345678.hub.north-europe.azure.keboola.com/_proxy/callback`

`<url-prefix>-<app-id>.hub.<stack-host>` is the whole host shown in the **App URL** block on the app's configuration page: the URL prefix, a hyphen, and the App ID, for example `toy-store-sales-74016144`. An app created without a URL prefix has no hyphenated part, so its callback URL is `https://<app-id>.hub.<stack-host>/_proxy/callback`.

---

**Next:** [Publish and share →](/data-apps/publish-and-share/)
