Documentation

SSO

Microsoft

Add Microsoft sign-in to VitNode for work, school and personal Microsoft accounts. Register an Entra app, pick the tenant and enforce who may sign in.

Add a Continue with Microsoft button for Microsoft Entra ID (work and school) and personal Microsoft accounts. The adapter uses OpenID Connect with PKCE, validates the ID token and enforces the tenant you choose on every sign-in.

Before you begin

Register the application

Create an app registration

In the Microsoft Entra admin center, open Entra ID → App registrations and press New registration.

Choose who can sign in

Pick the Supported account types and use the matching tenant value. Microsoft has renamed these options over time; the current labels are:

Who can sign inSupported account typestenant
Work, school and personal Microsoft accountsAny Entra ID Tenant + Personal Microsoft accountscommon
Work and school accounts from any tenantMultiple Entra ID tenantsorganizations
Personal Microsoft accounts onlyPersonal accounts onlyconsumers
Your own organization onlySingle tenant onlyyour tenant ID

A single-tenant app must use its tenant ID, because Microsoft refuses the default common endpoint for single-tenant apps (error AADSTS50194).

Add the redirect URI

Press Register. Then open Authentication, add a redirect URI on the Web platform and save. Add one per environment:

EnvironmentRedirect URI
Development (VITNODE_WEB_URL unset)http://localhost:3000/login/sso/microsoft
Productionhttps://your-domain.com/login/sso/microsoft

Microsoft allows plain http:// only for localhost.

Create a client secret

Copy the Application (client) ID from Overview. Open Certificates & secrets → Client secrets → New client secret, and copy its Value, not the Secret ID. Microsoft shows the value once, and it expires on the date you pick.

.env
MICROSOFT_CLIENT_ID=00000000-1111-2222-3333-444444444444
MICROSOFT_CLIENT_SECRET=xxxxx~xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Add the adapter

Add MicrosoftSSOApiPlugin to authorization.ssoAdapters in the API's vitnode.api.config.ts (where it lives), next to any adapters you already have. Keep the rest of the config as it is:

src/vitnode.api.config.ts (excerpt)
import { MicrosoftSSOApiPlugin } from '@vitnode/core/api/adapters/sso/microsoft'
import { buildApiConfig } from '@vitnode/core/vitnode.config'

export const vitNodeApiConfig = buildApiConfig({
  // ...
  authorization: {
    ssoAdapters: [
      // ...
      MicrosoftSSOApiPlugin({
        clientId: process.env.MICROSOFT_CLIENT_ID,
        clientSecret: process.env.MICROSOFT_CLIENT_SECRET,
        tenant: 'common',
      }),
    ],
  },
})

No authorization block yet? Create one with just ssoAdapters, as in the SSO setup. Then restart the dev server, since .env and the API config are only read at start-up.

Check the result

Open /login, press the Microsoft button under Continue with, sign in and accept. You return to /login/sso/microsoft signed in, or are asked to confirm an email.

Tenant restrictions are enforced

The tenant in the authorize URL is only a hint to Microsoft. VitNode checks the validated ID token instead. Its issuer must be https://login.microsoftonline.com/{tid}/v2.0 for the token's own tid, and that tid must fit tenant:

  • organizations refuses personal accounts (tenant 9188040d-6c67-4c5b-b112-36a304b66dad).
  • consumers accepts only personal accounts.
  • A tenant ID accepts only that tenant.

To allow a few partner organizations on a multi-tenant app, add allowedTenantIds. Any other tenant gets a 403:

src/vitnode.api.config.ts
MicrosoftSSOApiPlugin({
  clientId: process.env.MICROSOFT_CLIENT_ID,
  clientSecret: process.env.MICROSOFT_CLIENT_SECRET,
  tenant: 'organizations',
  allowedTenantIds: ['11111111-2222-3333-4444-555555555555'], 
}),

tenant must be common, organizations, consumers or a tenant ID (GUID); a domain such as contoso.com is refused at startup because it cannot be compared with tid.

Email and account ID

Microsoft's email claim can change and is often not verified, so VitNode trusts it only when Microsoft adds xms_edov: true (the email's domain owner is verified). To receive it, open Token configuration → Add optional claim → ID and add email and xms_edov. Without it, new members confirm an address by email.

The account is stored as {tid}:{oid}. Microsoft names oid with tid as the best key when an ID is shared across services, and the same person in two tenants has a different oid, so they are two accounts.

Scopes and profile fields

SettingValue
Scopesopenid profile email
PKCES256
Account ID{tid}:{oid}
Email trustedonly with xms_edov: true
Profile fieldsfirst name, last name

The profile photo would need Microsoft Graph's User.Read permission, so the adapter does not offer the avatar.

Troubleshooting

  • AADSTS50011, redirect URI mismatch. Add {VITNODE_WEB_URL}/login/sso/microsoft under Authentication on the Web platform.
  • AADSTS7000215, invalid client secret. You copied the Secret ID instead of the secret's Value.
  • AADSTS7000222, expired client secret. Create a new client secret and update the .env.
  • AADSTS50194. A single-tenant app is signing in through common; set tenant to your tenant ID.
  • AADSTS50020 or a 403 after signing in. The account's tenant does not fit tenant or allowedTenantIds.
  • "Need admin approval". The organization blocks user consent; an administrator can grant consent for the tenant.