xMatix
Sign in Request demo
xMatix
PRODUCTS
SalesField SalesCRMRewardsClaimsInventoryProcurementWarehouse ManagementField ServiceServiceSupportTelephony & MessagingFinance & AccountingPayrollExpense ManagementCommercePortalsAnalytics & ReportingData StudioMobile AppSee all products →
PLATFORM
Platform overviewApp BuilderAutomationIntegrationsSecurity & GovernanceChange ManagementDevelopers
SENSE AI
Sense AI overviewSense AssistSense ControlSense VisionAI StudioTrust & governanceIn Claude & ChatGPTUse cases
SOLUTIONS
FMCG & DistributionManufacturing & Dealer NetworksAutomotive & DealershipsPharma & HealthcareConsumer DurablesAgri-InputsBuilding MaterialsService NetworksWarehousing & 3PLFinancial AccountingERP SoftwareIndia GST ComplianceUAE VAT & e-InvoicingSaudi ZATCA & VATAll solutions →
RESOURCES
Knowledge CenterDeveloper & CLIBlogGuidesWhat is xMatix?Company facts
COMPANY
AboutCareersPartnersEventsContactAuthorsLegal
Sign in Request demo
BLOG · ENGINEERING

One sign-in for every assistant

Letting an AI assistant act as a user is an identity problem before it is an AI problem. Why we built a standards-compliant authorization server instead of handing out API keys — and what the security review should look for.

· Delivery, Infrastructure & Security · · 8 min read

The moment a business platform lets an external assistant act on a user's behalf, it has taken on an identity problem, and the quality of the whole integration is decided by how honestly it solves that one. This post is about the piece of xMatix nobody will see in a demo: the authorization server that sits between Claude, ChatGPT or Claude Code and your data.

The shortcut we did not take

The fastest way to connect an assistant to a system is a long-lived API key: generate it, paste it into the assistant's settings, done. It is also the way to fail a security review, for three reasons that do not go away with better prompting.

A key has no user. Whatever it can do, it can do for anyone who holds it, so it is either scoped to a service account — and now the assistant sees more than the person asking — or one key is minted per user and the platform has become a secrets distributor. A key does not expire until someone remembers to rotate it. And a key knows nothing about the organisation: in a multi-tenant platform where one person may belong to several, the question "which organisation is this call for?" has to be answered somewhere, and a key cannot answer it.

What an assistant actually asks for

The assistants solved this problem for us by agreeing on how they want to authenticate. Under the Model Context Protocol, a well-behaved client that receives a 401 from an endpoint reads the protected-resource metadata it points to, discovers the authorization server, registers itself dynamically, and starts an ordinary OAuth authorization-code flow with PKCE. The user sees a browser window, signs in, consents, and is sent back. The assistant holds a short-lived token and a refresh token. Nothing in that sequence is exotic; it is the protocol your own login already uses, applied to a machine client.

So the platform had to become an authorization server. Not a login page — xMatix already has one — but an issuer that brokers that login for any registered client and mints tokens the platform's own APIs will accept.

What we built

The server is a general OAuth 2.1 and OpenID Connect issuer, mounted inside the AI service rather than as a new deployment. The checklist a reviewer would want, stated plainly:

  • Authorization code with PKCE, mandatory. No implicit flow, no password grant. Dynamic client registration is supported because the assistants require it, and so are client metadata documents, where the client identifies itself by a URL we fetch over HTTPS.
  • The upstream login is the platform's own. The server is itself a confidential client of the identity provider your users already sign in with. Only the validated identity token is used, and its subject, tenant and name claims are mirrored into ours, so every downstream service resolves exactly the user account it would for a direct login. There is no second user directory.
  • One organisation per token. After sign-in, the consent screen lists the organisations the user belongs to — filtered to those whose policy allows this client — and the choice is written into the token. A multi-tenant user picks; a single-tenant user with a remembered consent never sees the screen.
  • Short-lived access, rotating refresh. Access tokens live an hour. Refresh tokens rotate on every use, and a replayed refresh token revokes its entire family, because replay is the signature of a stolen token.
  • Scopes that mean something. Read, write, chat and setup are separate scopes. A write scope is only issued when the organisation has allowed writes; if it has not, the scope is dropped at issuance, whatever the client requested. The consent screen shows what was actually granted.
  • Policy re-evaluated, not cached. The organisation's policy — enabled, writes allowed, approved clients — is checked on every refresh and on every gateway call. Turning the feature off revokes the organisation's refresh tokens, so sessions end now.
  • Signing keys you can hold. Tokens are RS256-signed. The private key can come from your key vault; otherwise one is generated once and stored encrypted. Retired keys stay published for verification until nothing depends on them.
  • The boring RFCs. Discovery, revocation, introspection, the resource indicator, the issuer identifier on the redirect. Each is a small thing a compliant client expects, and each missing one is a support ticket.

The consent screen is part of the security model

It is tempting to treat the consent page as decoration. We render it ourselves, server-side, with no scripts and a strict content-security policy, and it states three things a user should read: which client is asking, identified by a name and — only over HTTPS — its own logo and site; which organisation the token will be bound to; and which scopes will actually be granted, after the organisation's ceiling has been applied. If writes are off, the screen does not promise writes. A consent page that shows what was requested rather than what will be granted is a lie of omission, and it is the most common one in this category.

The resource side

An issuer is useless unless the APIs trust it. Every xMatix service that already accepts the platform's login now also accepts tokens from our issuer on the same bearer scheme, selected by the token's issuer claim, with the accepted audiences pinned. The tenant validator, which normally checks that a token's identity provider matches the organisation's configured one, knows that for our issuer the login already happened against that provider and skips the redundant match. Nothing else changed. The permission model downstream — security profiles, record security, restriction rules — never learned there was a new way to arrive, which is exactly what you want from a permission model.

Why general, and not just for the assistants

We could have built a narrower thing that only handled MCP clients. We deliberately did not. The server has a notion of client kinds: connectors, which need the organisation's opt-in and can only be registered dynamically as public or secret-based clients with HTTPS redirects; integration apps, which are registered by an administrator, carry an explicit organisation allow-list and may use the client-credentials grant for machine-to-machine work; and first-party clients. The next integration your IT team builds — a reporting job, a partner system, an internal tool — signs in the same way the assistants do, against the same policy, with the same audit. One authorization server, many clients, is how identity is supposed to work, and it is cheaper to build it once properly than to build the shortcut three times.

What to ask any vendor

If you are evaluating an AI connector to any business system, the questions are the same ones this post answers. Whose permissions does the assistant carry? How long does a token live, and what happens when a refresh token is replayed? Which organisation is a call bound to, and who chose it? What does the consent screen show — what was requested, or what was granted? Does switching the feature off end sessions now or eventually? If a vendor cannot answer those in a sentence each, the connector is an API key with a nicer name.

Related: Sense in Claude and ChatGPT · The platform security review checklist · Security & governance

← All posts
See it on your business.
Request a demo