-
Notifications
You must be signed in to change notification settings - Fork 340
SPA Authorization Code
This flow enables confidential client applications to request an additional "spa auth code" from the eSTS /token endpoint, and this authorization code can be redeemed silently by the front end running in the browser. This feature is intended for applications that perform server-side (web apps) and browser-side (SPA) authentication, using a confidential SDK such as MSAL.net or MSAL Node server-side, and MSAL.js in the browser (e.g., an ASP.net web application hosting a React single-page application). In these scenarios, the application will likely need authentication both browser-side (e.g., a public client using MSAL.js) and server-side (e.g., a confidential client using MSAL.net), and each application context will need to acquire its own tokens.
Today, applications using this architecture will first interactively authenticate the user via the confidential client application, and then attempt to silently authenticate the user a second time with the public client. Unfortunately, this process is both relatively slow, and the silent network request made client-side (in a hidden iframe) will deterministically fail if third-party cookies are disabled/blocked. By acquiring a second authorization code server-side, MSAL.js can skip hidden iframe step, and immediately redeem the authorization code against the /token endpoint. This mitigates issued caused by third-party cookie blocking, and is also more performant
MSAL 4.40+ supports confidential clients to request an additional "spa auth code" from the eSTS / token endpoint
The redirect_uri used to acquire the spa auth code must be of type web.
In MSAL.Net, using the new WithSpaAuthorizationCode
API get the SpaAuthCode
.
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
{
try
{
// Upon successful sign in, get the access token & cache it using MSAL
IConfidentialClientApplication clientApp = MsalAppBuilder.BuildConfidentialClientApplication();
AuthenticationResult result = await clientApp.AcquireTokenByAuthorizationCode(new[] { "user.read" }, context.Code)
.WithSpaAuthorizationCode(true)
.ExecuteAsync();
HttpContext.Current.Session.Add("Spa_Auth_Code", result.SpaAuthCode);
}
catch
{
}
}
Configure a PublicClientApplication from MSAL.js in your single-page application:
const msalInstance = new msal.PublicClientApplication({
auth: {
clientId: "{{clientId}}",
redirectUri: "http://localhost:3000/auth/client-redirect",
authority: "{{authority}}"
}
})
Next, render the code that was acquired server-side, and provide it to the acquireTokenByCode API on the MSAL.js PublicClientApplication instance. Do not include any additional scopes that were not included in the first login request, otherwise the user may be prompted for consent.
The application should also render any account hints, as they will be needed for any interactive requests to ensure the same user is used for both requests
const code = "{{code}}";
const loginHint = "{{loginHint}}";
const scopes = [ "user.read" ];
return msalInstance.acquireTokenByCode({
code,
scopes
})
.catch(error => {
if (error instanceof msal.InteractionRequiredAuthError) {
// Use loginHint/sid from server to ensure same user
return msalInstance.loginRedirect({
loginHint,
scopes
})
}
});
Once the Access Token is retrieved using the new MSAL.js acquireTokenByCode
api, the token is then used to read the user's profile
function callMSGraph(endpoint, token, callback) {
const headers = new Headers();
const bearer = `Bearer ${token}`;
headers.append("Authorization", bearer);
const options = {
method: "GET",
headers: headers
};
console.log('request made to Graph API at: ' + new Date().toString());
fetch(endpoint, options)
.then(response => response.json())
.then(response => callback(response, endpoint))
.then(result => {
console.log('Successfully Fetched Data from Graph API:', result);
})
.catch(error => console.log(error))
}
ASP.NET MVC project that uses the SPA Authorization Code in the Front End
- Home
- Why use MSAL.NET
- Is MSAL.NET right for me
- Scenarios
- Register your app with AAD
- Client applications
- Acquiring tokens
- MSAL samples
- Known Issues
- AcquireTokenInteractive
- WAM - the Windows broker
- .NET Core
- Xamarin Docs
- UWP
- Custom Browser
- Applying an AAD B2C policy
- Integrated Windows Authentication for domain or AAD joined machines
- Username / Password
- Device Code Flow for devices without a Web browser
- ADFS support
- Acquiring a token for the app
- Acquiring a token on behalf of a user in Web APIs
- Acquiring a token by authorization code in Web Apps
- High Availability
- Token cache serialization
- Logging
- Exceptions in MSAL
- Provide your own Httpclient and proxy
- Extensibility Points
- Clearing the cache
- Client Credentials Multi-Tenant guidance
- Performance perspectives
- Differences between ADAL.NET and MSAL.NET Apps
- PowerShell support
- Testing apps that use MSAL
- Experimental Features
- Proof of Possession (PoP) tokens
- Using in Azure functions
- Extract info from WWW-Authenticate headers
- SPA Authorization Code