0% found this document useful (0 votes)
6 views

Steps for Azure AD Integration in ASP

The document outlines the steps for integrating Azure AD in both ASP.NET Web API and React applications. It details the process of creating an app registration, configuring permissions, and implementing authentication and authorization in both environments. Key components include setting up application IDs, scopes, and using MSAL for token management in the React application.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

Steps for Azure AD Integration in ASP

The document outlines the steps for integrating Azure AD in both ASP.NET Web API and React applications. It details the process of creating an app registration, configuring permissions, and implementing authentication and authorization in both environments. Key components include setting up application IDs, scopes, and using MSAL for token management in the React application.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 13

Steps for Azure AD Integration in ASP .

net Web API:


1. Create an APP Registration
Under app registration we need to enter details like
a. Adding name
b. Supported Account Types
i. If we want to use only for our internal owner then select (Default
Directory only – Single Tenant)
ii. We will be going to have multiple users from other organization also,
so we need to go with the (Any Microsoft Entra ID tenant - Multitenant)
2. We require Application (client) ID and Directory (tenant) ID
3. Next we need to navigate to expose an API

We need to set to an Application ID URI

After generating the API URI we need to add a scope:

Clicking on scope will open a dialog box as shown below


Where we need to fill the required permissions and make sure that state is
enabled and click on add scope will create the scope.
4. Select the Manifest blade on the left and set accessTokenAcceptedVersion
property to 2

5. Select APP roles from the left section and create app role and add the entries for
each API in the menu shown below:

6. Next we need to navigate to token confifuration and add optional claim as idtyp to
determine if token is an app token or app + user token

Under token type select access and then under the claim search for idtyp as
shown below
7. Under the appsettings.json we will be adding following things as shown
below:
"AzureAd": {
"Instance": "https://login.microsoftonline.com",
"TenantId": "30bf9f37-d550-4878-9494-1041656caf27",
"ClientId": "e1262245-c87d-4f59-ade5-034e808ac807",
"Scopes": {
"Read": [ "ToDoList.Read", "ToDoList.ReadWrite" ],
"Write": [ "ToDoList.ReadWrite" ]
},
"AppPermissions": {
"Read": [ "ToDoList.Read.All", "ToDoList.ReadWrite.All" ],
"Write": [ "ToDoList.ReadWrite.All" ]
}
},

8. Next we need to add dotnet package Microsoft.Identity.Web and using


Microsoft.AspNetCore.Authentication.JwtBearer;
9. In program.cs we need to add authentication code as mentioned below

using Microsoft.Identity.Web;
using Microsoft.AspNetCore.Authentication.JwtBearer;
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationSche
me).AddMicrosoftIdentityWebApi(builder.Configuration, “AzureAd”);

We can skip the second argurment as we are using the AzureAd default.
10.After app.useHttpsRedirection() and before app.UseAuthorization() add
app.UseAuthentication();
11. At controller level we need to add [Authorize] annotations to the class
name.
[ApiController]
[Route("[controller]")]
[Authorize]
public class WeatherForecastController: ControllerBase
{
// Controller logic……}

12. We need to then define the scope to the controller function by using the
data annotation as shown below:
[RequiredScopeOrAppPermission(
RequiredScopesConfigurationKey = "AzureAD:Scopes:Read",
RequiredAppPermissionsConfigurationKey = "AzureAD:AppPermissions:Read"
)]
public IEnumerable<WeatherForecast> Get()
{

If we skip any endpoint with the above annotations then we will get forbidden error.
We can also add the above annotations at the controller level.
Steps for Azure AD Integration in React Application:

1. Create App registration and then select appropriate Supported Account Types.
2. Select Authentication option from the sidebar and appropriate redirect URIs.
3. Under the API Permissions section select the appropriate delegated
permissions by clicking on the Add a permission:
a. Select Microsoft Graph from the Microsoft APIs section.

b. In the delegated permission section, select openid, offline_access in the list.

c. Select the Add Permission


4. Again select the add permission button
a. Select My API tabs
b. In the available list of APIs select the API APP registration
c. In the delegated permission select the necessary scopes from the list
After adding all the permissions, it will look like this as shown below:

5. We need to add following configuration data in the authProvider as shown


below:

export const msalConfig = {


auth: {
// URL where we need to send the request to check the login from Microsoft
authority: "https://login.microsoftonline.com/30bf9f37-d550-4878-9494-
1041656caf27",
//tenantId:"30bf9f37-d550-4878-9494-1041656caf27",
// Client Id of App Registeration in Azure
clientId: "b96245af-83d9-4353-893b-4e6d40cfb29d" ,
// URL to redirect after post authentication
redirectUri: "/",
postLogoutRedirectUri: "/",
validateAuthority: true,
// After being redirected to redirectUri page, should user be redirected back
to the URL where the login originated froom
navigateToLoginRequestUrl: true
},
// Enable logging of MSAL events for easier troubleshooting. Should be disable
in production builds
system: {
loggerOptions: {
loggerCallback: (level, message, containsPii) => {
if (containsPii) {
return;
}
switch (level) {
case LogLevel.Error:
console.error(message);
return;
case LogLevel.Info:
console.info(message);
return;
case LogLevel.Verbose:
console.debug(message);
return;
case LogLevel.Warning:
console.warn(message);
return;
default:
return;
}
}
}
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: false
}
};

along with the protected resources data as shown below:


/**
* Add here the endpoints and scopes when obtaining an access token for
protected web APIs. For more information, see:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/
lib/msal-browser/docs/resources-and-scopes.md
*/
export const protectedResources = {
customerListAPI: {
endpoint: 'https://localhost:7182/api/Customers',
scopes: {
read: ['api://e1262245-c87d-4f59-ade5-034e808ac807/ToDoList.Read'],
write:
['api://e1262245-c87d-4f59-ade5-034e808ac807/ToDoList.ReadWrite'],
},
},
};
And login request as follows:

/**
* Scopes you add here will be prompted for user consent during sign-in.
* By default, MSAL.js will add OIDC scopes (openid, profile, email) to any login
request.
* For more information about OIDC scopes, visit:
* https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-
permissions-and-consent#openid-connect-scopes
*/
export const loginRequest = {
scopes: ["openid", "profile",
"user.read", ...protectedResources.customerListAPI.scopes.read, ...protectedReso
urces.customerListAPI.scopes.write]
};

6. We need to create a custom hook to fetch the data along with getting
accesstoken as mentioned below:
import { useCallback, useState, useEffect } from "react";
import { InteractionRequiredAuthError, InteractionStatus } from "@azure/msal-
browser";
import { useMsal } from "@azure/msal-react";
const useFetchWithMsal = (msalRequest) => {
const { instance, inProgress, accounts } = useMsal();
const [accessToken, setAccessToken] = useState("");

const getAccessToken = useCallback(async () => {


try {
const accessTokenRequest = {
...msalRequest,
account: accounts[0],
};
if (inProgress === InteractionStatus.None) {
const accessTokenResponse = await
instance.acquireTokenSilent(accessTokenRequest);
setAccessToken(accessTokenResponse.accessToken);
return accessTokenResponse.accessToken;
}
} catch (error) {
if (error instanceof InteractionRequiredAuthError) {
const accessTokenResponse = await
instance.acquireTokenPopup(msalRequest);
setAccessToken(accessTokenResponse.accessToken);
return accessTokenResponse.accessToken;
}
throw error;
}
}, [inProgress, msalRequest, accounts, instance]);

useEffect(() => {
if (accounts.length > 0 && inProgress === InteractionStatus.None) {
getAccessToken();
}
}, [instance, msalRequest, accounts, inProgress, getAccessToken]);
const execute = useCallback(async (method, endpoint, requestData = null)
=> {
const token = accessToken || await getAccessToken();
const headers = new Headers();
headers.append("Authorization", `Bearer ${token}`);
if (requestData) headers.append('Content-Type', 'application/json');

const options = {
method: method,
headers: headers,
body: requestData ? JSON.stringify(requestData) : null,
};

const response = await fetch(endpoint, options);


if (response.ok) {
const responseData = await response.json();
return responseData;
} else {
const errorData = await response.text();
throw new Error(`Request failed with status ${response.status}: $
{errorData}`);
}
}, [accessToken, getAccessToken]);

return {
execute,
};
};

export default useFetchWithMsal;

6. We need to use the custom hook for making the api call by including the
access token as shown below:
const {execute} = useFetchWithMsal({
scopes: protectedResources.customerListAPI.scopes.write,
});

execute("POST", protectedResources.customerListAPI.endpoint,
formData).then(data=> {
console.log(data)
}).catch(error=> {
console.error(error);
})

You might also like