Azure Active Directory Authentication
To get started, run the setup command:
yarn rw setup auth azure-active-directory
This installs all the packages, writes all the files, and makes all the code modifications you need. For a detailed explanation of all the api- and web-side changes that aren't exclusive to Azure, see the top-level Authentication doc. For now, let's focus on Azure's side of things.
Follow the steps in Single-page application: App registration.
After registering your app, you'll be redirected to its "Overview" section.
We're interested in two credentials here, "Application (client) ID" and "Directory (tenant) ID".
Go ahead and copy "Application (client) ID" to your .env
file as AZURE_ACTIVE_DIRECTORY_CLIENT_ID
.
But "Directory (tenant) ID" needs a bit more explanation.
Azure has an option called "Authority". It's a URL that specifies a directory that MSAL (Microsoft Authentication Library) can request tokens from.
You can read more about it here,
but to cut to the chase, you probably want https://login.microsoftonline.com/${tenantId}
as your Authority, where tenantId
is "Directory (tenant) ID".
After substituting your app's "Directory (tenant) ID" in the URL, add it to your .env
file as AZURE_ACTIVE_DIRECTORY_AUTHORITY
.
All together now:
AZURE_ACTIVE_DIRECTORY_CLIENT_ID="..."
# Where `tenantId` is your app's "Directory (tenant) ID"
AZURE_ACTIVE_DIRECTORY_AUTHORITY="https://login.microsoftonline.com/${tenantId}"
Ok, back to Single-page application: App registration. At the end, it says...
Next, configure the app registration with a Redirect URI to specify where the Microsoft identity platform should redirect the client along with any security tokens. Use the steps appropriate for the version of MSAL.js you're using in your application:
- MSAL.js 2.0 with auth code flow (recommended)
- MSAL.js 1.0 with implicit flow
Redwood uses MSAL.js 2.0 with auth code flow, so follow the steps there next.
When it asks you for a Redirect URI, enter http://localhost:8910
and http://localhost:8910/login
, and copy these into your .env
file as AZURE_ACTIVE_DIRECTORY_REDIRECT_URI
and AZURE_ACTIVE_DIRECTORY_LOGOUT_REDIRECT_URI
:
Configure one, then you'll be able to configure another.
AZURE_ACTIVE_DIRECTORY_CLIENT_ID="..."
# Where `tenantId` is your app's "Directory (tenant) ID"
AZURE_ACTIVE_DIRECTORY_AUTHORITY="https://login.microsoftonline.com/${tenantId}"
AZURE_ACTIVE_DIRECTORY_REDIRECT_URI="http://localhost:8910"
AZURE_ACTIVE_DIRECTORY_LOGOUT_REDIRECT_URI="http://localhost:8910/login"
That's it for .env vars. Don't forget to include them in the includeEnvironmentVariables
array in redwood.toml
:
[web]
# ...
includeEnvironmentVariables = [
"AZURE_ACTIVE_DIRECTORY_CLIENT_ID",
"AZURE_ACTIVE_DIRECTORY_AUTHORITY",
"AZURE_ACTIVE_DIRECTORY_REDIRECT_URI",
"AZURE_ACTIVE_DIRECTORY_LOGOUT_REDIRECT_URI",
]
Now let's make sure everything works: if this is a brand new project, generate
a home page. There we'll try to sign up by destructuring signUp
from the
useAuth
hook (import that from 'src/auth'
). We'll also destructure and
display isAuthenticated
to see if it worked:
yarn rw g page home /
import { useAuth } from 'src/auth'
const HomePage = () => {
const { isAuthenticated, signUp } = useAuth()
return (
<>
{/* MetaTags, h1, paragraphs, etc. */}
<p>{JSON.stringify({ isAuthenticated })}</p>
<button onClick={signUp}>Sign Up</button>
</>
)
}
Roles
To add roles exposed via the roles
claim, follow Add app roles to your application and receive them in the token.
logIn
Options
options
in logIn(options?)
is of type RedirectRequest and is a good place to pass in optional scopes to be authorized.
By default, MSAL sets scopes
to /.default which is built in for every application that refers to the static list of permissions configured on the application registration. Furthermore, MSAL will add openid
and profile
to all requests. In the example below we explicit include User.Read.All
in the login scope.
await logIn({
scopes: ['User.Read.All'], // becomes ['openid', 'profile', 'User.Read.All']
})
See loginRedirect, PublicClientApplication class and Scopes Behavior for more documentation.
getToken
Options
options
in getToken(options?)
is of type RedirectRequest.
By default, getToken
will be called with scope ['openid', 'profile']
.
Since Azure Active Directory applies incremental consent, we can extend the permissions from the login example by including another scope, for example Mail.Read
:
await getToken({
scopes: ['Mail.Read'], // becomes ['openid', 'profile', 'User.Read.All', 'Mail.Read']
})
See acquireTokenSilent, Resources and Scopes or full class documentation for more.
Azure Active Directory B2C-specific configuration
You can design your own auth flow with Azure Active Directory B2C using hosted user flows. Using it requires two extra settings.
Update the .env file:
AZURE_ACTIVE_DIRECTORY_AUTHORITY=https://{your-microsoft-tenant-name}.b2clogin.com/{{your-microsoft-tenant-name}}.onmicrosoft.com/{{your-microsoft-user-flow-id}}
AZURE_ACTIVE_DIRECTORY_JWT_ISSUER=https://{{your-microsoft-tenant-name}}.b2clogin.com/{{your-microsoft-tenant-id}}/v2.0/
AZURE_ACTIVE_DIRECTORY_KNOWN_AUTHORITY=https://{{your-microsoft-tenant-name}}.b2clogin.com
Here's an example:
AZURE_ACTIVE_DIRECTORY_AUTHORITY=https://rwauthtestb2c.b2clogin.com/rwauthtestb2c.onmicrosoft.com/B2C_1_signupsignin1
AZURE_ACTIVE_DIRECTORY_JWT_ISSUER=https://rwauthtestb2c.b2clogin.com/775527ef-8a37-4307-8b3d-cc311f58d922/v2.0/
AZURE_ACTIVE_DIRECTORY_KNOWN_AUTHORITY=https://rwauthtestb2c.b2clogin.com
And don't forget to add AZURE_ACTIVE_DIRECTORY_KNOWN_AUTHORITY
to the includeEnvironmentVariables
array in redwood.toml
.
(AZURE_ACTIVE_DIRECTORY_JWT_ISSUER
is only used on the API side. But more importantly, it's sensitive—do not include it in the web side.)
Update activeDirectoryClient
instance
This lets the MSAL web-side client know about our new B2C authority:
const azureActiveDirectoryClient = new PublicClientApplication({
auth: {
clientId: process.env.AZURE_ACTIVE_DIRECTORY_CLIENT_ID,
authority: process.env.AZURE_ACTIVE_DIRECTORY_AUTHORITY,
redirectUri: process.env.AZURE_ACTIVE_DIRECTORY_REDIRECT_URI,
postLogoutRedirectUri:
process.env.AZURE_ACTIVE_DIRECTORY_LOGOUT_REDIRECT_URI,
knownAuthorities: [process.env.AZURE_ACTIVE_DIRECTORY_KNOWN_AUTHORITY],
},
})
Now you can call the logIn
and logOut
functions from useAuth()
, and everything should just work.
Here's a few more links to relevant documentation for reference: