ConnXL Docs

Administer

Identity provider setup

Step-by-step wiring for each identity provider — where to find the client ID and secret, what the issuer URL looks like, and the one redirect URI you have to register. Covers Microsoft, Google, and any standards-compliant OIDC provider.

9 min read

Access control explains what a provider does. This page is the wiring: the exact values each provider wants, and where to find them.

The redirect URI comes first

Every provider, without exception, needs one value registered on its side: the URL it sends the user back to after sign-in.

https://your-agent-host/auth/callback

The dashboard shows the exact value on every provider you open, under Access → Sign-in, with a copy button. Use that — don't retype it.

Note

Register it after you've set your own agent domain on the Install in Excel page. Until then the dashboard shows the default host, and the redirect URI changes the moment you set a real one — leaving the value you registered no longer matching. Providers compare this string character for character: a missing https://, a trailing slash, or the wrong port all produce the same unhelpful "redirect_uri mismatch" error.

Microsoft — work and school accounts

Use the Entra ID provider. This covers accounts that live in a Microsoft directory (you@your-company.com), not personal Outlook or Hotmail addresses.

  1. In the Azure portal, go to Microsoft Entra ID → App registrations → New registration.
  2. Under Redirect URI, choose Web and paste the callback URL from the dashboard.
  3. Copy the Application (client) ID and the Directory (tenant) ID from the overview page.
  4. Under Certificates & secrets → New client secret, create a secret and copy its value immediately — Azure never shows it again.
  5. In ConnXL, add the Entra provider, paste the client ID and tenant ID, and point the client secret at your own secret store.

Who can sign in is a separate choice on that provider:

  • Only my Microsoft organization — the issuer is pinned to your tenant. Anyone outside it is refused before any other rule runs.
  • Any Microsoft organization — accepts other companies' directories, subject to your audience rules. This needs two things in your app registration that ConnXL cannot set or detect: the registration must accept accounts in any organizational directory (multi-tenant), and it must request the xms_edov optional claim on the access token (Token configuration → Add optional claim). Without the first, Microsoft refuses outside sign-ins itself; without the second, every sign-in is refused at our end, because that claim is the only signal that an email address really belongs to the person presenting it.

Microsoft — personal accounts

Use the Microsoft personal account provider for outlook.com, hotmail.com and live.com addresses. These are not in any Entra directory, so the Entra provider will never accept them.

The setup is the same as above with one difference: at New registration, set supported account types to Personal Microsoft accounts only (or "any organizational directory and personal Microsoft accounts" if you want both populations). There is no issuer to enter — every personal Microsoft account lives in one Microsoft-owned directory, so ConnXL pins that issuer for you.

Note

This lets in anyone with a free Microsoft account. Pair it with the allowed-domains list, or with an audience of named users, unless your add-in is genuinely meant to be public.

Microsoft — any account

Use the Microsoft (any account) provider when your users are a mix of work/school directories and personal accounts, and you want one sign-in button for all of them. There is no tenant and no issuer to enter — sign-in goes through Microsoft's common endpoint, and ConnXL verifies each token's issuer against the tenant the token itself was minted in.

The setup is the same app registration as above, with two settings that are both mandatory (ConnXL cannot set or detect either, and getting one wrong fails as an opaque Microsoft error):

  1. At New registration (or later under Authentication → Supported account types), choose Accounts in any organizational directory and personal Microsoft accounts. Any narrower choice makes Microsoft itself refuse one of the two account classes.
  2. Under Token configuration → Add optional claim → ID, add xms_edov. Work-account emails are only trusted when Microsoft attests the domain owner — without the claim, every work-account sign-in is refused at our end (personal accounts are unaffected; their address is the verified account identity).

Note

Like the personal-accounts provider, this lets in anyone with any Microsoft account. Use the allowed-domains list or a named audience to narrow it — and prefer the plain Entra ID provider when your users all live in known directories.

Google

Use the Google provider. There is no issuer to enter — Google has exactly one, shared by every Google account.

  1. In the Google Cloud console, go to APIs & Services → Credentials → Create credentials → OAuth client ID.
  2. Application type Web application; add the callback URL under Authorized redirect URIs.
  3. Copy the Client ID and Client secret.

The equivalent of Microsoft's "who can sign in" choice lives on Google's side, under OAuth consent screen → User type:

  • Internal — only accounts in your Google Workspace organization.
  • External — any Google account on the internet. While the app is in Testing you are capped at 100 named test users; publishing lifts that.

Note

An External, published Google app accepts every Google account there is. ConnXL has no per-organization switch for Google because Google's issuer carries no organization — restrict with the allowed-domains list instead.

Any other provider (generic OIDC)

Use the OpenID Connect provider for everything else. It is unbounded — connect Okta and Auth0 and your own Keycloak side by side, each with its own sign-in button.

It needs three things: the issuer URL, a client ID, and a client secret. ConnXL reads the issuer's /.well-known/openid-configuration document to discover the authorize, token and JWKS endpoints, so you never enter those.

The issuer must be an https:// URL with a host — a bare domain is rejected. The Set up for picker next to the field switches the example to your vendor's shape:

FieldTypeDescription
OktaOptional
issuerTypically https://your-org.okta.com, or https://your-org.okta.com/oauth2/default when you use a custom authorization server. Applications → Create App Integration → OIDC → Web Application.
Auth0Optional
issuerYour tenant domain, e.g. https://your-tenant.us.auth0.com. Applications → Create Application → Regular Web Application.
KeycloakOptional
issuerRealm-scoped: https://id.your-company.com/realms/your-realm. Clients → Create client → OpenID Connect, with client authentication ON.
AWS CognitoOptional
issuerhttps://cognito-idp.<region>.amazonaws.com/<user-pool-id>. Note that self-registration, if enabled on the pool, means anyone can create an account.
Ping IdentityOptional
issuerhttps://auth.pingone.com/<environment-id> for PingOne.

Any other standards-compliant provider works the same way — if it publishes a discovery document, ConnXL can use it.

Scopes

Leave the scopes list empty unless your provider needs more than the defaults. ConnXL always requests what it needs to identify the user; extra scopes are only useful when your IdP requires an explicit one to release the email claim.

Row-Level Security (token exchange)

Everything above gets a person signed in. This section is about what happens next: carrying that identity all the way down to your own database, so a query returns their rows and nobody else's.

The Sign-in token exchange authentication mode on an HTTP connection makes that possible. Instead of forwarding the Microsoft token as-is, the agent mints a short-lived JWT from the identity it just validated, signs it with a secret you supply, and sends that as the bearer token on every request the function makes.

The minted token carries sub, email and name from the signed-in Excel user, plus role, aud, iss, iat and exp. PostgREST — the REST API Supabase generates over your database — and Hasura accept exactly this shape, so your Row-Level Security policies apply per user: every cell request arrives as the person who typed the formula, not as one shared service account.

Which of the two user modes to pick

  • user_token — plain forwarding. Choose it when your API validates Microsoft tokens itself: it already has the issuer, audience and signing keys configured, and reads the caller's identity straight out of the token the agent forwards.
  • user_token_exchange — token exchange. Choose it when your API validates its own JWTs and knows nothing about Microsoft — PostgREST, Supabase, Hasura, or any service that verifies a shared HS256 secret. The agent is the bridge between the two worlds.
  • Both modes send the credential as Authorization: Bearer <token>. If your API reads it from a different header instead, set the connection's userTokenHeader field to that name — the token is then sent raw in that header, with no Bearer prefix. Leave it empty for the default.

Recipe: per-user rows from Supabase

  1. Find the signing secret. In your Supabase dashboard, go to Project Settings → API → JWT Secret. That is the secret PostgREST verifies every incoming token against.
  2. Store it as a reference. Put the value in your own secret store and point the connection's exchangeSecret field at it — secret://env/SUPABASE_JWT_SECRET, or any of the other backends listed under Connections. The value itself never reaches ConnXL.
  3. Create the connection. Type HTTP API, base URL https://<project-ref>.supabase.co/rest/v1, authentication Sign-in token exchange, audience authenticated.
  4. Add the apikey header. PostgREST wants your project's anon key on every request in addition to the bearer token. Add it as an extra header on the connection — name apikey, value the anon key, again as a secret:// reference. Without it Supabase rejects the call before it ever inspects the JWT.
  5. Write the policy. Turn RLS on for the table and key it on a claim from the minted token:
Supabase RLS policysql
create policy "own rows" on documents for select using (auth.jwt()->>'sub' = user_id);

Match on auth.jwt()->>'email' instead when your rows are keyed by address rather than by the provider's subject id.

The token-exchange fields

FieldTypeDescription
exchangeSecretRequired
secret://…A reference to the HS256 secret the token is signed with — for Supabase, Project Settings → API → JWT Secret. Write-only: once saved, the dashboard only ever shows that a secret is set, never its value.
exchangeAudienceRequired
stringThe aud claim stamped on the minted token. Supabase and PostgREST expect authenticated.
exchangeIssuerOptional
stringThe iss claim. Leave it empty unless the receiving service pins a specific issuer.
exchangeTtlSecondsOptional
numberHow long a minted token stays valid, between 60 and 600 seconds. Defaults to 300.
exchangeRoleOptional
stringA static role claim on every minted token. Defaults to authenticated, which is what Supabase expects for a signed-in caller.

Your agent becomes a token issuer for your own project

That is the whole point of the mode, and it is worth being deliberate about — anyone who can call a function on this connection gets a token minted in their own name. Three things bound it:

  • The secret stays on your infrastructure. The agent resolves the secret:// reference at execution time, on your host. ConnXL stores the reference, never the value, and no minted token is ever logged.
  • Tokens are short-lived. Ten minutes is the ceiling, five the default — long enough for a recalculation, too short to be worth hoarding.
  • The user must be signed in to Excel. There is no anonymous fallback: a cell that calls one of these functions with nobody signed in fails with a sign-in error rather than quietly minting a token with empty claims.

When sign-in doesn't work

  • "redirect_uri mismatch" — the registered URL doesn't match the one the dashboard shows, character for character. Re-copy it.
  • "redirect_uri mismatch" complaining about http:// vs https:// (Entra shows it as AADSTS500112) — TLS terminates on a load balancer or reverse proxy in front of the agent, and the agent doesn't trust forwarded headers by default. Set CONNXL_TRUSTED_PROXY=1 on the agent host so the callback is built as https://.
  • Sign-in succeeds but the add-in still refuses you — authentication worked, authorization didn't. Check the allowed/denied domains and the audience under Access control.
  • Every Entra sign-in fails in "any organization" mode — the xms_edov optional claim is missing from the app registration.
  • Nothing happens when you click the sign-in button — the agent must serve trusted HTTPS; Excel refuses to load an add-in, or its sign-in dialog, from an untrusted host.

On this page