v0.8.0
Sign in with Microsoft
@nauth-toolkit/social-microsoft adds Entra ID (formerly Azure AD). A Microsoft 365 subscription is Entra ID, so "sign in with Microsoft" and "SSO against our M365 tenant" are the same OIDC flow — there is no separate SSO product to integrate with. One config value decides which population can sign in.
microsoft: {
enabled: true,
clientId: process.env.MS_CLIENT_ID,
clientSecret: process.env.MS_CLIENT_SECRET,
callbackUrl: `${process.env.API_BASE_URL}/auth/social/microsoft/callback`,
tenant: 'common', // or a directory GUID to pin one organisation
}
tenant | Who can sign in |
|---|---|
common | Work/school accounts from any directory, plus personal accounts |
organizations | Work/school accounts from any directory |
consumers | Personal Microsoft accounts only |
| A directory GUID | That one organisation only |
Access can be gated on Entra app roles or security groups, checked on every sign-in rather than only at signup — so revoking a role locks the user out at their next attempt. Entra's own Assignment required toggle remains the simplest option and needs no code.
Two details differ from the other providers and are deliberate. Accounts are joined on the oid claim, never email and never sub (which is pairwise per application). And email is only trusted for auto-linking when the directory is one you pinned, or Entra's xms_edov claim confirms the tenant owns the domain, or the account is personal — because a tenant administrator controls the email claim for users in their own directory, which is the nOAuth account-takeover pattern.
See the Microsoft Entra ID guide.
Dates in the reader's own time
Users gain optional timezone and locale. The frontend SDK reads them from the browser and sends them with signup — including across the social redirect, so a Google, Apple, Facebook or Microsoft signup captures them too. Either the user or an admin can change them later.
Notification emails use them. Templates get a new {{timestampFormatted}} variable rendering the event time in the recipient's zone and locale, falling back to email.defaultTimezone / email.defaultLocale, then the server's settings, then UTC:
email: {
defaultTimezone: 'Europe/Dublin',
defaultLocale: 'en-GB',
},
Twelve default templates switched from a raw UTC ISO string to the formatted form — including the MFA-device-removed alert, which previously showed no date at all. {{timestamp}} is unchanged, so custom templates keep working exactly as before.
Two nullable columns are added by a migration that runs automatically at startup on both Postgres and MySQL. Existing rows are untouched and fall back to the server default until a user sets a preference.
This controls date formatting only — email body text is not translated. See Configuration and Notifications.
Also fixed
Two long-standing bugs on the Express and Fastify paths, both invisible from NestJS:
- Google, Apple and Facebook received
tokenVerifierwhere they expectedhookRegistry, and vice versa — so lifecycle hooks and native token verification were each wired to the wrong object. - A missing optional provider package returned out of initialisation entirely, so an absent
social-googlesilently prevented Apple and Facebook from registering. A real construction failure — a bad secret, an invalid tenant — is now reported as an error rather than "install the package".