Azure B2C - renew session - reactjs

I have a React app that uses Azure B2C to authenticate users (PKCE flow).
There is a requirement to keep the session active as long as the user has some activity.
I cannot use "Rolling" for session timeout, because some of the requests are made by an independent job, which is not triggered by the user.
Here is my question - how can I control renewing the session? I would like to renew the session every time I am getting the access token.

Access tokens and ID tokens are short-lived. Since you are using the Authorization-Code Grant flow of OAuth, after they expire, you must refresh them to continue to access resources .
Hence in order to get the refresh-token, you would have to send a POST request to the /token endpoint of B2C with the scope .(i.e; Provide the refresh_token instead of the code in the rquest).see reference 1.
Make sure to add scopes along with AppId 'openid profile offline_access AppId’
Ex: scope: 'openid profile offline_access XXXXXX-f9a4-4b8e-XXXX-dXXXXXXX01f'
References:
Authorization code flow - Azure Active Directory B2C | Microsoft
Docs
microsoft-authentication-library-for-js/FAQ (github.com)

Related

How do I check if the user from a non-Graph Azure AD token is a member of an email distribution list in an APIM policy

Have an API in Azure API Management (APIM).
The API operation validates a JWT generated by Azure Active Directory (AAD) using a scope from a backend app registration (the scope is NOT User.Read). Note: client id is another app registration which is an authorized app of that backend scope.
After the JWT is validated, am I able take that token, extract user info out of it and verify if the user is part of a email distribution list (DL)? If so, how to do it within an APIM policy?
I am aware of MS Graph APIs. Using Postman I can confirm the DL is listed in the tenant's groups and can get its group ID. I can also confirm the user is a member of the group. The bit I'm stuck with for Graph API is that it needs a different token to the one supplied by the client application (due to he scopes being from different domains custom app registration vs graph) and I'm stuck at this point. Should I make the client app also get a graph token and pass it in a separate header, or is there way to orchestrate things from within APIM or something else?
The non-APIM part of this solution is provided by a Microsoft article. I've summarised those and combined with the APIM parts in the following steps:
In Azure, create a new Azure App Registration (note the client id for later)
Under "Certificates and secrets", add a client secret (note the secret for later)
Under "API Permissions", add a new MS Graph Application Permission (can be User.Read.All, Group.Read.All, GroupMember.Read.All depending on your situation). MS Graph's "groups" includes both AD groups and Distribution Lists (DL). Note: don't use Delegated permission.
Application permissions allow the authorized app to enquire about any user/group. You will need an Azure Admin to Grant Admin Consent for the App Registration to have the chosen Application Permission.
Now in Azure APIM, go to your API and edit the inbound policy.
Validate the JWT from the user making the call (See validate-jwt or newer validate-azure-ad-token) to ensure the User is authorized to call this API.
Extract the oid claim from the JWT (this is the user ID I'll use for the graph call) and save it in a variable using set-variable policy
Add a send-request policy request an auth token for MS Graph using client-credentials flow (this is when you'll need the client id and secret from earlier App registration). Note: secrets should be stored in a secure store like KeyVault but that is outside the scope of this answer.
Extract the access_token field from the JSON response body and put it in a variable using set-variable policy.
Create another send-request policy, but this time to the MS Graph endpoint. For User.Read.All permission you'd use /users/<userIdFromJwtOidClaim>/memberof/<groupId>. MS Graph v1.0 API Reference, and pass the access_token in the Authorization header using <set-header> element.
A status code of 200 indicates the user is a member of the group. IIRC A status code of 403 indicates the user isn't a member of the group.
Use a choose policy to perform logic depending on the user's group membership.
Use return-response policy to send a response back to the user.

InteractionRequiredAuthError: AADSTS65001: The user or administrator has not consented to use the application with ID

Trying to create a simple SPA and call a Rest API in Azure, and I am getting InteractionRequiredAuthError: AADSTS65001: The user or administrator has not consented to use the application with ID 'xxx' named 'MySpaApp'. Send an interactive authorization request for this user and resource.
Did the following:
Registered the REST Api application
Added permission for MyRestApi.Tasks.Get, its status is Granted for my users
Added a scope for Tasks.Get
Added a client application using the SPA application's Client Id
Registered the SPA application
URI is http://localhost
Implicit grant and hybrid flows:
Access tokens checked
ID tokens checked
Supported account types: any organizational directory
API Permissions, added MyRestApi.Tasks.Get
In Enterprise Applications, MySpaApp, clicked Grant Admin Consent for my users
Went back to MySpaApp, and verified that Tasks.Get has been granted
From MySpaApp, if I call msal.acquireTokenSilent with "Tasks.Get" for scope, I get:
The user or administrator has not consented to use the application with ID 'xxx' named 'MySpApp'. Send an interactive authorization request for this user and resource.
If I call call msal.acquireTokenSilent with "User.Read" for scope, I get back a token.
Any further ideas on troubleshooting?
Try my method:
Register an SPA in Azure and check id token and access token.
Then register a REST Api application and expose the api, and then add the client id of the spa application to the REST Api application.
Next, go to the spa application.
Under 'API permissions' click on 'Add permission', then click on the
'My APIs' tab.
Find your api application and select scope.
Click 'Add permissions'.
Grant admin consent.
Then use the implicit flow in the browser to get the token.
https://login.microsoftonline.com/{tenant id}/oauth2/v2.0/authorize?
client_id={client_id}
&response_type=id_token token
&redirect_uri={redirect_uri}
&scope=openid api://{api app client id}/{scope name}
&response_mode=fragment
&state=12345
&nonce=678910
Parse the token:

How to Revoke Token generated on Azure AD On Behalf user flow?

I am getting access token and then calling MS graph API , however i am not getting any API for revoking the access token /refresh token generated for specific account(used on behalf of user authorization flow).
Used the azure AD logout API which redirects to the logout URL but not exactly logging out of Office 365 account and can still able to generate the new access token using refresh token after logout. This should not happen.
Please suggest some solution.
It seems like your only option is here cmdlet Revoke-AzureADUserAllRefreshToken.
https://learn.microsoft.com/en-us/powershell/module/azuread/revoke-azureaduserallrefreshtoken?view=azureadps-2.0
Your case is also described in the Office 365 scope over here: https://www.michev.info/Blog/Post/1137/immediately-revoke-access-to-office-365-applications

Does what you send in Scope Governs whether you can login with Microsoft Account using Azure AD V2 Endpoints

I have registered a application using the App Registration (Preview) Blade and added the Azure Service Management API as API Permissions I downloaded the MSAL based Sample from
https://github.com/azure-samples/active-directory-dotnet-webapp-openidconnect-v2
Now in startup.auth.cs if i change the Scope i.e keep openid and add https://management.azure.com and then run and try and Login with a Microsoft Account i get the following error
This Doesn't Look like a Work or School Email you cant Sign-in here with Personal Account use your work or School Account Instead.
if i remove the Scope for https://managment.azure.com and just keep Openid profile offline_access i get the Consent Screen and Login
new OpenIdConnectAuthenticationOptions
{
// The Authority represents the v2.0 endpoint - https://login.microsoftonline.com/common/v2.0
// The Scope describes the initial permissions that your app will need. See https://azure.microsoft.com/documentation/articles/active-directory-v2-scopes/
ClientId = clientId,
Authority = String.Format(CultureInfo.InvariantCulture, aadInstance, "common", "/v2.0"),
RedirectUri = redirectUri,
Scope = "openid https://management.azure.com/.default",
PostLogoutRedirectUri = redirectUri,
I am Expecting to have the user Login and Obtain a Token for management API , i am Looking for Reasons for getting the above Error is this Expected ? The Account that i am using exists in my directory as a Member . this works if i use a Managed user(user#tenant.onmicrosoft.com) to Login
Since personal MS accounts cannot be used to manage Azure subscriptions unless they are added to an Azure AD, you should use the organizations endpoint instead of common.
In v1 "common" meant any AAD tenant.
In v2 "common" means any AAD tenant + any personal MS account.
If you wanted only personal accounts, you can use "consumers".
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-protocols-oidc#fetch-the-openid-connect-metadata-document
You can use "organizations" to allow any AAD tenant but disallow MS accounts.
Of course a user can just edit the URL and login with a personal MS account anyway, so you'll want to check the tenant id of the logged in user.
The tenant id for MS accounts is always 9188040d-6c67-4c5b-b112-36a304b66dad, per the docs: https://learn.microsoft.com/en-us/azure/active-directory/develop/id-tokens#payload-claims.
So check the idp claim.

Microsoft Graph Admin Consent Flow Doesn't Contain Refresh Token

Is it possible to get refresh token also in the admin consent flow?
I've received access_token but not refresh_token even though I've included the offline_access permission in the delegated permissions.
to be more clear: I need to get to the users drive files (i.e get/update files) of the entire tenant (organization). therefore i'm requesting Application Permissions and Using the admin consent endpoint.
therefore I use the client_credentials grant in order to get the entire tenant access_token but unfortunately with no refresh_token in order to extend time of privileges of the tenant for more then 1 hour.
if i misuse the protocols above clarification will be highly appreciated
While Marc's answer is correct, I think the whole thing can be explained in a little more detail:
To get full access to a tenant (i.e. not just resources associated with the current consenting user), then you need to use the Admin Consent flow. However, unlike other flows in Graph's OAuth, you do not require a refresh_token to maintain access. Instead, you can simply request an access_token at any time once an admin has consented. Each access_token lasts 60 minutes.
Having first used other flows such as the Management API and Graph's Code Grant flow, this one confused me, but it's actually even simpler than those.
To get consent, simply direct the admin to the following URL:
https://login.microsoftonline.com/[Their Tenant ID]/adminconsent?client_id=[Your Client ID]&redirect_uri=[Your Redirect URI]
Your redirect URI will get a response with params:
?admin_consent=True&tenant=[Their Tenant ID]
Once you've received this confirmation, you can request an access_token at any time by sending a POST request with the following form fields:
client_id: [Your Client ID],
client_secret: [Your Client Secret],
scope: 'https://graph.microsoft.com/.default',
grant_type: 'client_credentials'
To the following URI:
https://login.microsoftonline.com/[Their Tenant ID]/oauth2/v2.0/token
The response will contain a new 60 minute access_token and you can simply call it again whenever required.
Refresh Tokens are only returned when both offline_access is requested and you are using the Authorization Code Grant.
More importantly, if you are receiving an access_token then you are not executing the Admin Consent workflow. Administrative Consent is only used for consenting to your application's scopes. The Admin Consent response does not contain an access_token, it only contains the Tenant ID (for the tenant that was consented) and a boolean that tells you if consent was granted as query parameters:
http://{return_uri}/?tenant=[tenant id]&admin_consent=[True/False]
If you are receiving an access_token then you are using either the Authorization Code, Client Credentials, or Implicit grants.
UPDATE:
There is no refresh token issued for Client Credentials, you simply request a new token from the /token endpoint as needed.

Resources