How to authenticate and store tokens in a multitenant web client (multiple B2C identities in the same browser) - azure-ad-b2c

I'm designing a single-page app (SPA) and API that will support multiple tenants, including in the same client browser. Imagine an experience similar to the Azure Portal, where users can switch between identities that they have signed into Azure AD with, except that in this case I'm using Azure AD B2C. All sign-ins happen via a single Azure AD B2C instance. Importantly, the tenants do not necessarily have to be aware of each other since they are white-labeled -- the user might be redirected to https://multitenant.app/tenantA and sign in via B2C, and have a totally different experience when directed to https://multitenant.app/tenantB and signing in via B2C there. The two tenants do not need to share data between themselves on the client.
How might I go about:
1) designing the client so that requests to https://multitenant.app/tenantX are directed to Azure AD B2C in a way that enables sign-in using the rules for tenantX, and
2) designing the client so that the MSAL.js library correctly provides a token store containing tokens specific to tenantX when the user has navigated to https://multitenant.app/tenantX in the browser?
Currently I'm expecting to need to intercept requests to the backend API on the client, determine if a redirect to B2C is necessary first in order to sign in to the tenant that the request is for, and attach the appropriate access token for that tenant to the API request. (All this is assuming that I use the Implicit Flow so that I have the access & refresh tokens available on the client.)
Does this make sense? Is there a better way? I've debated using session cookies issued by the server so that the browser handles the "intercept-requests-and-attach-credentials" aspect of this, so maybe that's an option that would avoid the need to maintain all these tokens on the client?
And how does this work when the client signs into B2C? Can I tweak/disable the B2C SSO capabilities sufficiently so that a single user agent (browser) can still obtain multiple different tokens (for different identities)?

The approach needs to be a bit different. This is how Microsoft do it with their "tenant picker" in the Azure Portal.
We hold a mapping of in which tenants your account lives in
We then list the tenants in a tenant picker UI in the app
When you switch tenants, we do an SSO authentication to the new resource (ie the selected tenant) to get a token to it
We use the new token to evaluate your rights in this tenants subscription
To translate this in AAD B2C you can:
Hold a mapping of identifier to 'tenant'
On authentication, call your API to get a list of tenants. Use this sample to list the tenants in the authentication flow
The user selects the tenant, or maybe you do it like Microsoft and have a default preference, in which case the step above is skipped using a B2C precondition. This way the user only goes through selecting a tenant in the auth flow once. Afterwards they use an in-app tenant picker (read on...)
The token issued to the user has the tenant inside it as a claim, this will then be used to do authorization when this token arrives are your API.
In the SPA, now render a tenant picker, use the same API as used in step 2 essentially
The user can select a new tenant in the SPA, use id_token_hint (example) to seed a new B2C user journey with the selected tenant. The user will get SSO through this journey and get a new token with the new tenant inside it as a claim.

Related

What is the flow of Azure AD based authentication in a project having SPA and web api?

I have a front end SPA (single page application) and back end api.
Each event in the SPA (like button click) invokes the respective api endpoint, and displays the result in the SPA.
I want to implement Azure AD based authentication so that only my Azure Tenant users are able to use the SPA/api.
Is the following flow correct approach to implementing such a feature:
User opens the SPA
User clicks on login button which opens Microsoft login popup
User enters Microsoft credentials in the popup, and if credentials are correct then user gets the JWT token
For every subsequent api request, the JWT token is placed in the bearer header
The endpoint validates the JWT token using Azure public key and rejects the request if token is missing or validation fails.
Is this flow correct and what is such a flow called?
There are several implementation steps that needs to be performed before you will have the flow that you have described:
User flow needs to be configured (Azure AD) - e.g. selfsignup allowed?
Backend and frontend applications needs to be registered (Azure AD)
Permissions and scopes needs to be added (Azure AD)
Backend API needs to be configured (e.g. API management) in order to validate the JWT token
I highly recommend to configure one of the Azure sample implementations end2end to get and idea of all the needed tasks: https://learn.microsoft.com/en-us/azure/active-directory-b2c/configure-authentication-sample-spa-app
The steps you outlined are correct.
An OAuth 2.0 "flow" outlines the steps to acquire a token from an Identity Provider (IdP). Since you are using a SPA, there are some restrictions on which flows you can use. A SPA can't act as a "Confidential Client" which is required for some flows. (Basically - the Client Secret required for the other flows would be visible in the browser network trace, so it's not "confidential".) The "Implicit Flow" used to be recommended for SPAs but it's less secure, so now the "Authorization code flow (with PKCE)" is recommended. Steps 2 & 3 in the question above are when you are executing the flow to acquire a token.
The authentication flow doesn't really address how you save and send the token to the API (#4 in the question), but the Microsoft Authentication Library (MSAL) helps with that - More information here - https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-spa-overview
In Azure AD, you'll want 2 App Registrations - one for your SPA and one for your API. The API App Registration will need to "Expose an API" which really means to define a scope. Your SPA App Registration will need to Add an "API Permission" to the scope you defined from your API App Registration. (It will show up in My APIs.) This relationship is how #5 in the question is enforced.
Many of the steps for setting up authentication in Azure AD and Azure B2C are similar but Azure AD is designed for authenticating users that are part of your organization. Azure B2C allows you to build a set of users that aren't members of a particular Azure AD organization.

AAD B2C Multiapps Authenication and Authorisation concerns

We're looking into Azure AAD B2C since we offer bespoke applications to a number of users. We've chosen B2C since we're after 1 user repository but these users can span across a number of domain applications
It's my understanding that AAD B2C is just a IdP and isn't concerned about user claims.
I am confused though, since we're supporting N number of applications with this single B2C instance, where does Authorisation sit?
With the app? If so, I assume my users will authenticate with AAD, get a token, and then use the said token to call an API / APP? Won't each request require a round trip to the database to see if said UID (User Id) can do said action?
Some of these domain apps could be SPA's, others could be API;s others could be simple MVC applications
You can make a rest api request during authentication to fetch an attribute containing the users roles. Then the app/api can just examine that.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/add-api-connector-token-enrichment?pivots=b2c-custom-policy

Restricting User Access Azure B2C

According to this documentation, I can restrict access to applications on an Azure tenant using enterprise applications.
I tried to set this up on my B2C Tenant but when I test my user flows, I can still log in to those applications and receive an ID token.
Should the restrictions also work on the B2C Tenant or is there a different process required for B2C?
Using b2c User flows we can't restrict the user access. You need to handle this from the application side and also using Custom policy you can call the REST API in the user journey and can validate user restrictions.

Multiple Sign ins in Azure AD

I've implemented SSO using SAML authentication on Asure AD in my banking application. I have a scenario where I've to let a manager/supervisor log in to approve a transaction. A regular rep would not have authority to approve, the manager would come in and physically login in (keeping the rep's session intact) and approve a transaction and then logout. Is it possible to have multiple sign ins in the same browser instance through Azure AD?
UPDATE - Per what I researched and mentioned by Carl as well, Azure AD does not support multiple users to login in an application in the same browser instance.
Yes, in the same tenant, users with different roles can perform multiple logins in the same browser. Log in to the Azure portal and you can see that accounts with different roles in the upper right corner can be switched back and forth.
These identities have already validated their credentials for this session, and have an auth token. Switching between these accounts now will not prompt you for their passwords again.
Update:
Even if two accounts are in the same domain, they cannot be logged in at the same time. Currently, only two browsers can be used for two accounts in the same domain.
SAML SSO is a form of delegated authentication. The user is authenticated at the identity provider site (eg Azure AD) which sends a SAML assertion containing user identity information to the service provider site. The service provider trusts this information and establishes a local authentication session for the user using the information contained in the SAML assertion. SAML assertions often contain the user's email address but any user identity information may be included.
You can achieve multiple sign-ins on the same browser , Kindly check this link.

Azure AD B2C - Sign out a user from all sessions

I have 3 websites using a single B2C tenant. I have been asked to set it up so that when a user signs out of one website, sign out of them all.
Likewise if their account is deleted.
I thought that I would have to introduce a call to Azure on every request to determine if the user is still logged in, but as far as I can see, there isn't a Graph API endpoint that would allow me to determine the user status.
Am I thinking about this the wrong way? Is there a way to do this easily using B2C, Graph API, the Active Directory client etc.?
Maybe there is an option when setting up the OpenIdConnectAuthenticationOptions for example.
According the description on Azure Document:
While directing the user to the end_session_endpoint will clear some of the user's single sign-on state with Azure AD B2C, it will not sign the user out of the user's social identity provider (IDP) session. If the user selects the same IDP during a subsequent sign-in, they will be reauthenticated, without entering their credentials. If a user wants to sign out of your B2C application, it does not necessarily mean they want to sign out of their Facebook account entirely. However, in the case of local accounts, the user's session will be ended properly.
So you can directly use the end_session_endpoint. You can find it in the metadata document for the b2c_1_sign_in policy endpoint, e.g.:
https://login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=b2c_1_sign_in
You can refer to Azure Active Directory B2C: Web sign-in with OpenID Connect for more info.
Any further concern, please feel free to let me know.
I might be late. But if that helps. A.c to docs
When you redirect the user to the Azure AD B2C sign-out endpoint (for both OAuth2 and SAML protocols), Azure AD B2C clears the user's session from the browser. However, the user might still be signed in to other applications that use Azure AD B2C for authentication. To enable those applications to sign the user out simultaneously, Azure AD B2C sends an HTTP GET request to the registered LogoutUrl of all the applications that the user is currently signed in to.
Applications must respond to this request by clearing any session that identifies the user and returning a 200 response. If you want to support single sign-out in your application, you must implement a LogoutUrl in your application's code.
This is called single sign out .
Please refer to https://learn.microsoft.com/en-us/azure/active-directory-b2c/session-overview#single-sign-out
Microsoft has an API for this by now. I link to the following blog, as the documentation is currently wrong.
microsoft developer blog: revokeSignInSessions & invalidateAllRefreshTokens
Request
POST https://graph.microsoft.com/beta/users/{id}/revokeSignInSessions
Response
HTTP/1.1 204 No Content

Resources