Back to Blog

Copilot Extensibility Authentication with TypeSpec - What You Actually Need to Know

May 30, 20269 min readMichael Ridland

If you are building agents or plugins on top of Microsoft 365 Copilot and your APIs need to talk to systems that actually require authentication (which is most of them), you are going to spend more time on auth than you expect. This is true of nearly every integration project but it bites particularly hard in the Copilot context because you have multiple identity layers stacked on each other - the user signed into Copilot, the agent or app calling the API, the API's own authentication needs, and any downstream systems that the API talks to. Get one wrong and either nothing works or you accidentally let people see data they should not.

Microsoft has been pushing TypeSpec as the recommended way to define APIs for Copilot extensibility. TypeSpec is a language for describing APIs that generates OpenAPI specs (and other artifacts) from a higher level definition. The authentication story in TypeSpec for Copilot is reasonably well thought out but it has some sharp edges that catch people out.

Here is what we have learned deploying Copilot extensibility with authenticated APIs for Australian enterprise clients.

The authentication options at a glance

When you define an API for Copilot extensibility in TypeSpec, you can declare one of several authentication schemes. The main ones that actually matter in practice are:

  • No authentication (for public APIs only - rare in enterprise)
  • API key authentication (a static secret sent in a header)
  • OAuth 2.0 with various flows
  • Entra ID (Azure AD) authentication, which is really a flavour of OAuth

For most enterprise scenarios in Australia, you will end up with Entra ID authentication or OAuth 2.0 against another identity provider. API key auth shows up sometimes for internal experimental work but it is not a serious choice for anything customer facing or that touches sensitive data.

The TypeSpec definition itself is straightforward. You declare the security scheme as part of the service definition and TypeSpec generates the appropriate OpenAPI security definitions. The Copilot platform reads those definitions and handles the user side of the authentication flow - prompting the user to sign in, collecting the consent, and managing the tokens.

That last sentence sounds simple. In practice it has the most failure modes of anything in the whole setup.

The user consent reality

When a Copilot agent or plugin calls an authenticated API for the first time, the user gets prompted to authenticate to that API. They sign in, they consent to the requested scopes, the platform stores a token, and subsequent calls work without re-prompting.

The first thing that catches people is that this consent flow looks different depending on the user's organisation policies. Some organisations have admin consent required for all API access. In those organisations, the user does not see a consent screen - they see a "your administrator needs to approve this" message and nothing happens until IT processes the request. We have seen Copilot agent rollouts get stuck for weeks because the consent process was not pre-arranged with IT.

For any enterprise deployment, you need to work with the IT team to either pre-approve the agent's required scopes through admin consent, or to ensure users have the permissions to grant consent themselves. This is not a Copilot specific issue - it is true of any OAuth integration in an enterprise tenant - but it is more visible in Copilot because the agents get rolled out to broad user populations and any consent friction becomes a support burden immediately.

The second thing that catches people is the token lifecycle. Tokens expire. Refresh tokens expire. Users revoke consent. When any of these happen, the next call to the API fails and the user sees an error. The Copilot platform handles re-prompting in some cases but not all. We have built error handling into our APIs to detect the common token failure modes and return a clear message that the agent can present to the user, rather than letting a generic 401 propagate.

Entra ID specifics

For APIs that authenticate against Entra ID (which is the default and recommended approach for Microsoft 365 Copilot extensibility), there are a few things specific to that integration worth knowing.

You register the API as an Entra ID application. The application has its own application ID, its own scopes that you define, and its own client secrets or certificates. When the user signs into the Copilot agent and the agent calls your API, the token presented to the API is issued for your API's application ID with the scopes the user consented to.

The "scopes" part is where most design effort goes. You want scopes that are granular enough to be meaningful (admins do not want to grant a blanket "read everything" scope) but not so granular that the consent screen has 40 items on it. We typically recommend three to five scopes that map to functional areas of the API - "read user data", "modify user data", "read team data", and so on. Avoid scopes that nobody can interpret like "FullAccess" or "Standard". Names that make sense to a non-technical admin reading the consent screen are worth the effort.

The TypeSpec definition lets you declare scopes per operation. So a read operation might only require the "read" scope, while a write operation requires the "write" scope. This is good practice and the platform handles it correctly - Copilot will request the right scopes based on which operations the agent uses.

The on behalf of pattern

The most common pattern for serious Copilot extensibility is "on behalf of" authentication. The user authenticates to Copilot. Copilot calls your API with a token for your API. Your API then needs to call downstream systems (a CRM, an internal SQL database, a third party SaaS tool) and it needs to do that as the user, not as a service account.

This pattern is well supported through OAuth 2.0 on behalf of (OBO) flow. The TypeSpec definition does not directly express the OBO flow - that is server side implementation - but you need to plan for it from the start.

The reason is data security. If your API calls downstream systems with a service account, then every user gets the same access regardless of their own permissions. A user who is supposed to only see their own region's data ends up seeing everything. We have audited Copilot deployments where this had happened and the data exposure was significant. The fix is invasive because the architecture has to be reworked.

If you are building authenticated APIs for Copilot and any downstream call needs to respect user level permissions, design for OBO from the start. Get the API team and the identity team in the same room early. This is exactly the kind of architectural decision where our AI solutions architects get involved on engagements because it has compounding consequences if you get it wrong.

Multi tenant and ISV considerations

If you are building Copilot extensibility for sale (an ISV scenario) rather than for internal use, the authentication design gets harder. You need to support multiple customer tenants. Each customer has their own Entra ID. Your API needs to authenticate users from any of those tenants but still know which customer they belong to and which data they can access.

The TypeSpec authentication definitions support this through multi-tenant Entra ID configurations. The implementation though is mostly on you. You register your API as a multi-tenant Entra ID application. Each customer admin consents to the app for their tenant. Your API validates tokens from any of those tenants but uses the tenant ID claim to scope data access. This is standard SaaS plumbing but the discipline of getting it right in a Copilot context is the same as anywhere else.

A specific gotcha we have hit - some customer tenants have policies that block multi-tenant app registrations entirely. You can find that customers who want to use your Copilot extension cannot because their IT department has a default block. The workaround is to support a single-tenant deployment mode as an alternative, but that doubles the complexity of your setup process.

If you are building in this space, the early conversations with customer IT teams matter a lot. We have helped ISV clients design the authentication side of their Copilot offerings as part of Copilot extensibility engagements and the patterns vary depending on the customer profile.

What to actually do

A few practical recommendations from real deployments.

Use Entra ID rather than custom OAuth or API key auth wherever you can. It integrates cleanly with the Copilot platform, it gives you free single sign on for users already signed into Microsoft 365, and it gives admins one place to manage access. Roll your own auth only when there is no choice.

Plan the scope design before you write the TypeSpec. Get the scopes named in plain language that an IT admin will understand on a consent screen. Three to five scopes is the right zone for most APIs.

Build OBO into the architecture from the start if any downstream system needs user level permissions. Retrofitting this is painful.

Test the consent flow with users from outside your IT team early. The flow you see as a developer with full admin rights is not the flow that a normal user experiences. We have caught major usability issues by walking through the consent flow with a real end user before launch.

Handle the token failure cases explicitly. Returning a generic 401 from your API makes Copilot show a generic error. Detecting the specific failure mode and returning a clear message gives the user something they can act on.

Pre-arrange admin consent with IT for any production rollout. Do not assume that users will be able to consent themselves. They often cannot.

The honest take

Authentication for Copilot extensibility is not particularly novel. The patterns are the same OAuth and Entra ID patterns that every enterprise integration has used for years. What is new is the user population. Copilot agents get rolled out to thousands of users at once, and any friction in the auth flow becomes a support call. The bar for "this just works" is higher than for traditional enterprise APIs that have a smaller user population who are willing to tolerate quirks.

Get the auth design right early and the rollout is smooth. Get it wrong and you spend the first three months of post launch fixing consent issues, token errors and permission edge cases.

If you are planning a Copilot extensibility build and want a second opinion on the authentication architecture before you commit, get in touch. The hour spent reviewing the design upfront is worth a lot more than the same hour spent fixing it later.

Reference - Microsoft 365 Copilot Extensibility - TypeSpec Authentication