DEV Community

Cover image for n8n Microsoft OAuth2: Fix 'Need Admin Approval'
Mahdi BEN RHOUMA
Mahdi BEN RHOUMA

Posted on Originally published at iloveblogs.blog

n8n Microsoft OAuth2: Fix 'Need Admin Approval'

The symptom in the original
Stack Overflow question
is familiar to anyone who has wired a Microsoft node into n8n inside a
company tenant. The asker was on n8n Cloud, connecting Teams and OneDrive,
and kept getting "Need admin approval". Their Entra admin went to
Enterprise applications, opened the n8n app, chose Security, Permissions, and
clicked Grant admin consent for [our company]. The grant succeeded. The
error did not move, even after clearing the browser cache.

That is the frustrating part: the admin did the documented thing. The
reason it did not help is that Entra ID consent is scoped to a specific
client ID and a specific list of permissions, and neither of those is
guaranteed to match what n8n sends. This post walks through every place the
mismatch hides, then covers the two self-hosting failures that produce
similar dead ends: the /common endpoint and the redirect URI.

What "Need admin approval" actually means

Microsoft shows that screen when a user signs in to an app that requests at
least one permission the user is not allowed to consent to on their own. Per
Microsoft's
permissions and consent overview,
"application permissions and many high-privilege delegated permissions can
only be consented to by an administrator", and tenants can go further by
disabling user consent entirely.

Here is the detail the accepted Stack Overflow answer gets wrong. It states
that the delegated version of Files.ReadWrite.All "shouldn't require Admin
Consent". The
Microsoft Graph permissions reference
lists Files.ReadWrite.All as admin consent required: Yes for the
delegated work-or-school variant, and n8n's OneDrive credential requests
exactly that scope by default (openid offline_access Files.ReadWrite.All,
per the
n8n Microsoft Entra credential docs).
Teams is similar: ChannelMessage.Read.All is admin-consent-only as a
delegated permission. So the prompt is expected. Admin consent is the fix;
the question is why the grant did not land.

Why the grant did not land: four mismatches

1. Consent was granted to a different client ID

n8n Cloud users click Connect my account and authenticate through n8n's
own pre-registered application. Self-hosted users register their own app.
Both can exist as separate entries under Enterprise applications in the same
tenant, with different Application IDs, and the button only consents the
entry you opened.

Check it from the failing sign-in itself. The request n8n opens is the Entra
authorisation endpoint (visible in the address bar as the pop-up loads, or in
the browser's network log), and it carries the client ID:

https://login.microsoftonline.com/common/oauth2/v2.0/authorize
  ?client_id=<this is the app you must consent>
  &response_type=code
  &redirect_uri=...
  &scope=openid offline_access Files.ReadWrite.All
  &response_mode=query&prompt=select_account
Enter fullscreen mode Exit fullscreen mode

Copy client_id, open Enterprise applications, and search by Application ID
rather than name. If the app your admin consented to has a different ID, the
grant went to the wrong object.

2. The grant covers fewer scopes than n8n requests

Delegated permissions can be consented in two ways, quoting the same
Microsoft overview: "Static: configured list on app registration" and
"Dynamic: request individual permissions at sign-in". n8n is dynamic. The
scope parameter in the URL above is built from the credential, and each
Microsoft node has its own default list (Outlook alone asks for twelve
scopes including Mail.ReadWrite.Shared and MailboxSettings.Read).

The Enterprise applications Permissions page grants what is currently listed
on that service principal. If the list was captured when someone tried a
Teams credential, and you are now connecting OneDrive, Files.ReadWrite.All
is not in the grant and the prompt returns. Compare the "Admin consent" tab
against n8n's
required scopes by integration
table for every node you plan to use. For a self-hosted registration, add
each missing scope under API permissions, Microsoft Graph, Delegated
permissions, then grant again.

3. Application permissions were added instead of delegated

n8n's connect flow is the OAuth2 authorisation code grant with a signed-in
user. Microsoft's comparison table is explicit: delegated permissions "get
access on behalf of a user"; application permissions "get access without a
user" and are "app roles". An app role granted with admin consent is never
consumed by n8n's user flow, so the delegated prompt keeps appearing. In the
App registrations, API permissions view, the Type column must say
Delegated for every Graph scope n8n needs. If you genuinely need app-only
access, n8n documents a separate Microsoft Entra Service Principal
credential for that; it is a different flow, not a switch on the OAuth2 one.

4. Tenant policy blocks the user regardless of the grant

Two settings override everything above:

  • User consent settings under Enterprise applications, Consent and permissions. If the tenant is set to "Do not allow user consent", users cannot self-consent even to low-impact scopes, and the tenant-wide grant must exist first.
  • Assignment required on the enterprise app. Microsoft notes that "applications that require users to be assigned to the application must have their permissions consented by an administrator", and the user must also be assigned.

If the tenant has the
admin consent workflow
enabled, the "Need admin approval" screen gains a request form. Approving
that request is the cleanest path because it consents exactly the client ID
and scopes the failing sign-in asked for.

The quickest reliable fix: consent from inside n8n

The
n8n docs
now recommend an ordering that sidesteps all four mismatches. An Entra admin
opens the credential in n8n, clicks Connect to Microsoft Outlook (or
OneDrive, Teams), and in Microsoft's sign-in pop-up ticks Consent on behalf
of your organization
before accepting. Because the request originates from
n8n, the client ID and the scope list are the real ones. The docs add the
warning that "non-admin accounts will see a message stating that admin
approval is required", which is the very screen the asker hit.

For self-hosted teams, n8n goes further: register one multitenant app with
delegated permissions, consent once, then inject the client ID and secret
via CREDENTIALS_OVERWRITE_DATA_FILE so colleagues never see a consent
dialog. The
pre-configure Microsoft OAuth credentials
guide has the Docker Compose layout; the JSON must be minified:

{"microsoftOutlookOAuth2Api":{"clientId":"YOUR_CLIENT_ID","clientSecret":"YOUR_CLIENT_SECRET"}}
Enter fullscreen mode Exit fullscreen mode

If your credential test instead throws "No testing function found", that is a
different bug, covered in
n8n 'No testing function found for this credential' fix.

Self-hosted failure 1: AADSTS50194 and the /common endpoint

This one is invisible on n8n Cloud and constant on self-hosted single-tenant
setups. The exact text, from the
Entra error code reference:

AADSTS50194: Application '{appId}'({appName}) isn't configured as a multitenant
application. Usage of the /common endpoint isn't supported for such applications
created after '{time}'. Use a tenant-specific endpoint or configure the
application to be multitenant.
Enter fullscreen mode Exit fullscreen mode

n8n's Microsoft OAuth2 credential (MicrosoftOAuth2Api.credentials.ts in
the n8n repository) ships these defaults:

Authorization URL: https://login.microsoftonline.com/common/oauth2/v2.0/authorize
Access Token URL:  https://login.microsoftonline.com/common/oauth2/v2.0/token
Enter fullscreen mode Exit fullscreen mode

Microsoft's
protocol overview
defines the path segment: common for both Microsoft accounts and work or
school accounts, organizations for work or school only, consumers for
personal accounts, or a tenant ID or domain name. A single-tenant
registration rejects common. The fix that closed
n8n issue #3245 is still the
right one: edit both URL fields in the credential and replace common with
your tenant, for example yourcompany.onmicrosoft.com or the directory
GUID:

https://login.microsoftonline.com/yourcompany.onmicrosoft.com/oauth2/v2.0/authorize
https://login.microsoftonline.com/yourcompany.onmicrosoft.com/oauth2/v2.0/token
Enter fullscreen mode Exit fullscreen mode

Alternatively set Supported account types to a multitenant option when
registering, which is what the n8n docs assume. Security teams often refuse
that; the tenant-specific URLs are the compromise. Getting the tenant wrong
produces AADSTS90002 (tenant name not found) or AADSTS700016 (app not
found in that tenant), which point at the same field.

Self-hosted failure 2: AADSTS50011, the redirect URI

Entra only redirects to URIs registered on the app, and the match is strict.
From Microsoft's
redirect URI rules:
redirect URIs "must begin with the scheme https, with exceptions for some
localhost redirect URIs", they "are case-sensitive", a URI without a path
"is returned with a trailing slash", and ports are only ignored for
localhost. A mismatch fails with:

AADSTS50011: The reply URL specified in the request does not match the reply
URLs configured for the application
Enter fullscreen mode Exit fullscreen mode

n8n shows the value it will send as OAuth Callback URL in the credential
panel. Copy that string verbatim into the app's Web platform redirect URIs.
Do not retype it, and do not register http://n8n.internal:5678/... unless
it is literally localhost.

Behind a reverse proxy the panel may show the wrong host because, as the
n8n reverse proxy docs
explain, "n8n creates the webhook URL by combining N8N_PROTOCOL,
N8N_HOST and N8N_PORT", which breaks when the container listens on 5678
and the proxy serves 443. Set the public URL explicitly:

export N8N_WEBHOOK_URL=https://n8n.example.eu/
export N8N_EDITOR_BASE_URL=https://n8n.example.eu/
export N8N_PROXY_HOPS=1
Enter fullscreen mode Exit fullscreen mode

Two notes from the same page. N8N_WEBHOOK_URL "replaces WEBHOOK_URL,
which is deprecated from n8n 2.35.0", though the old name still works with a
warning. And the last proxy must forward X-Forwarded-For,
X-Forwarded-Host and X-Forwarded-Proto. After a restart, reopen the
credential, confirm the callback URL now starts with https://n8n.example.eu,
and re-register it in Entra. The same misconfiguration is behind
the requested webhook is not registered
errors, so fixing it here usually fixes those too. If you run queue mode,
the variables must be identical on main and worker containers; see the
n8n queue mode checklist.

The other two-minute checks

  • Secret Value, not Secret ID. Pasting the ID column yields AADSTS7000215: Invalid client secret is provided. Regenerate and copy the Value immediately; Entra never shows it again.
  • Wrong account in the pop-up. n8n sends prompt=select_account, so pick the work account in the consented tenant, not a personal Microsoft account that lands in consumers.
  • Expired secret. Client secrets have a fixed lifetime; token refresh starts failing silently in workflows long after the initial connect worked. That pattern is dissected in how I fixed my n8n workflow failing silently.
  • Error workflow not firing on the failure. Credential refresh errors are a common blind spot; the n8n error workflow not triggering fix lists why.

A verification order that ends the loop

  1. Trigger the failure and copy client_id and scope from the login.microsoftonline.com URL.
  2. In Enterprise applications, find the app by Application ID. Confirm the Admin consent tab lists every scope from step 1 as Delegated.
  3. If anything is missing, add it under API permissions (self-hosted) or re-run the connect as an admin with "Consent on behalf of your organization" ticked (Cloud or self-hosted).
  4. Self-hosted only: replace common with your tenant in both URL fields if the registration is single-tenant; verify the OAuth Callback URL matches the registered Web redirect URI character for character.
  5. Reconnect in a private window with the correct work account.

If you are new to n8n credentials generally, the
n8n beginner guide covers
where credentials live and how nodes reference them.

Related


Originally published at https://www.iloveblogs.blog

Top comments (0)