Authenticating users in .NET apps with MSAL.NET
Overview
About us
Co-Presenter Name
☁️ Co-Presenter Title
Co-Presenter Name
☁️ Co-Presenter Title
For questions or help with this series: MSUSDev@Microsoft.com
All demos and source code available online:
Setting the scene
Series roadmap
- Session 1:
- ↪️ Authenticating users in JavaScript apps with MSAL.NET
- Session 2:
- Discover Microsoft Graph Toolkit Components
- Session 3:
- Authenticating to Azure with MSAL.NET
- Session 4:
- The Microsoft Graph SDK for .NET
Today’s agenda
- What is the Microsoft Identity Platform?
- How do we authenticate manually?
- How can the MSAL help us authenticate?
- Where can we use the MSAL token?
Identity Development with the Microsoft Identity Platform
Goal
Identity as a control plane
Azure Active Directory
Active Directory Authentication Library
Microsoft Identity Platform
https://docs.microsoft.com/azure/active-directory/develop/
Unified full-stack development tools to work with all Microsoft identities.
Microsoft Identity Platform Breakdown
Demo: Microsoft Identity Platform documentation
::: notes
-
Open a browser and navigate to https://docs.microsoft.com/en-us/azure/active-directory/develop/
-
Review the various sections of the landing page
-
In the About Microsoft identity platform section, within the Overview sub-sectoin, selet Microsoft identity plateform (v2.0)
-
Review the documentation on this page
:::
Authenticating to Microsoft
AAD Applications
- Register applications with AAD to get access to authentication and tokens
- Usually include a redirect URI for the application
- Registration will yield client credentials required to authenticate
- Can register different types of applications
Application Types
- Single-page applications
- Web applications
- Web APIs
- Desktop/Mobile applications
- Server-side applications
Demo: Registering an application in Azure AD
::: notes
-
Open a browser and navigate to https://portal.azure.com
-
Navigate to Azure Active Directory
-
Navigate to App registrations
-
Create a new registration using the following settings:
-
Name: Example
-
Supported account types: Accounts in any organization dirctory (Any Azure AD directory - Multitenant)
-
Redirect URI: Public client/native (mobile & desktop) - http://localhost
-
-
In the new registration, navigate to the API permissions section
-
Observe the built-in Microsoft Graph permission for User.Read
:::
Authentication flows
| Flow | Description | |
|---|---|---|
| Authorization code | Native and web apps securely obtain tokens in the name of the user | |
| Client credentials | Service applications run without user interaction | |
| On-behalf-of | The application calls a service/web API, which in turns calls Microsoft Graph | |
| Implicit | Used in browser-based applications | |
| Device code | Enables sign-in to a device by using another device that has a browser | |
| Integrated Windows | Windows computers silently acquire an access token when they are domain joined | |
| Interactive | Mobile and desktops applications call Microsoft Graph in the name of a user | |
| Username/password | The application signs in a user by using their username and password |
Interactive authentication flow
::: notes
-
The application redirects the user to the Azure AD sign-in portal, and the user acquires a token interactively from Azure AD
-
The application uses the token to access Microsoft Graph
:::
Device code flow
::: notes
-
The application requests a unique device code from Azure AD
-
The user uses another workstation along with the device code to sign in to the Azure AD sign-in portal
-
The original application acquires a token from Azure AD based on the user sign-in
-
The application uses the token to access Microsoft Graph
:::
Login URL
- One base URL for all login and token queries:
- Relative URLs for specific actions:
- login: \/authorize
- acquire token: \/token
Tenants
- https://login.microsoftonline.com/tenant_id/oauth2/v2.0
- Unique Tenant Id for just your organization
organizations: Any organizational (work/school) accountconsumers: Any Microsoft accountcommon: Any account
::: notes
The different values influence the in-browser user experience when logging in. For example; if you specify the tenant id, then the user will immediately see your organization’s branding.
:::
Authorize with Azure AD using OAuth 2.0
- Navigate to the \/authorize endpoint for login.microsoftonline.com
- Provide appropriate query string parameters
client_id: Unique Client Id for application registrationresponse_type: Set tocoderedirect_uri: One of the Redirect Uris specified in application registration processscope: List of permissions that you are requesting consent toresponse_mode: Eitherform_postorquery- (Optional)
state: Sanity-check value
- Provide appropriate query string parameters
- Login using your browser
- Observe the response
- If
response_mode=query, will include a unique code on the query string- Use this code to acquire a token
- (Optional) Echoes the state parameter
- If
Authorize Query String and URI Parameters
| Parameter | Description |
|---|---|
client_id |
AAD application unique identifier |
response_type |
Usually code |
redirect_uri |
Where to go after authentication |
response_mode |
Usually query but can be form_post |
scope |
What permissions are required |
state (optional) |
Value that can be used to validate response |
Example Authorization Request
GET https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?
client_id=06b9debd-a372-496f-916c-856dc9dd1f8a
&response_type=code
&redirect_uri=http%3A%2F%2Flocalhost%2F
&response_mode=query
&scope=user.read
&state=demo
Example Authorization Response
GET http://localhost?
code=6a3095c1-48ca-4d00-939e-eca0e5b8f1a4
&state=demo
Acquire a Bearer Token using OAuth 2.0
- Send a POST request to the \/token endpoint for login.microsoftonline.com
- Provide appropriate form parameters
client_id: Unique Client Id for application registrationredirect_uri: One of the Redirect Uris specified in application registration processscope: List of permissions that you are requesting consent tocode: Use the value of the code from the authorization requestgrant_type: Useauthorization_code
- Provide appropriate form parameters
- Observe the response
- The
access_tokenproperty has your OAuth 2.0 Bearer token
- The
Token Query String and URI Parameters
| Parameter | Description |
|---|---|
client_id |
AAD application unique identifier |
code |
Code from previous request |
grant_type |
authorization_code |
redirect_uri |
Where to go after authentication |
scope |
What permissions are required |
Example Token Request
POST https://login.microsoftonline.com/organizations/oauth2/v2.0/token?
client_id=06b9debd-a372-496f-916c-856dc9dd1f8a
&redirect_uri=http%3A%2F%2Flocalhost%2F
&grant_type=authorization_code
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
::: notes
The code value has been concatenated for brevity.
:::
Example Token Response
{
"token_type": "Bearer",
"scope": "user.read",
"expires_in": 3600,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
"refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4..."
}
::: notes
The access_token and refresh_token values have been concatenated for brevity.
:::
Demo: Manually acquiring a token from Microsoft
::: notes
-
Open a browser and navigate to https://portal.azure.com
-
Navigate to Azure Active Directory
-
Native to your recently created application registration
-
Record the value of the Client Id field
-
Build a URL using the following steps:
-
Start with
https://login.microsoftonline.com/common/oauth2/v2.0/authorize -
Add the
client_id=query string value with your unique Client Id from the application registration -
Add the
&redirect_uri=http%3A%2F%2Flocalhost%2Fquery string parameter -
Add the
&scope=user.readquery string parameter -
Add the
&response_type=codequery string parameter -
Add the
&response_mode=queryquery string parameter
-
-
Open a browser and navigate to the URL that you just built
-
Login using any organizational (work/school) account
-
Consent to the application’s request to view your user profile information (
user.read) -
Azure AD will redirect to localhost which should return a HTTP 404 error
-
Record the value of the redirect URL that is in the browser address bar
-
Record the value of the
codequery string parameter in the response -
Open a HTTP request tool
- Note: It is recommended to use Postman to demo the HTTP POST request
-
Build a HTTP POST request using the endpoint
https://login.microsoftonline.com/common/oauth2/v2.0/tokenand following these steps:-
Add a
client_idparameter with your unique Client Id from the application registration -
Add a
codeparameter with the code you recorded earlier in this lab -
Add a
redirect_uriparameter with a value ofhttp://localhost -
Add a
scopeparameter with a value ofuser.read -
Add a
grant_typeparameter with a value ofauthorization_code -
Issue the HTTP POST request
-
-
Observe the JSON response of the request, it should contain an
access_tokenproperty with your MSAL token -
Build a HTTP GET request using the endpoint
https://graph.microsoft.com/beta/meand following these steps:-
Add an OAuth 2.0 bearer token header using your Access Token created earlier.
-
Issue the HTTP GET request
-
-
Observe the result of the request
:::
Microsoft Authentication Library (MSAL)
MSAL SDK
https://docs.microsoft.com/azure/active-directory/develop/msal-overview
- Consistent single library for authentication with all Microsoft identities
- Can be used to access:
- Microsoft Graph
- other Microsoft APIs
- third-party Web APIs
- your own APIs
- Available in various programming languages and platforms:
- .NET
- JavaScript
- Python
- Java
- Android/iOS
NuGet
- Available on NuGet
Provider model
- Public client applications
- Applications always sign-in users
- Uses the MSAL
PublicClientApplicationclass - Examples:
- Desktop apps calling web APIs on behalf of the signed-in user
- Mobile apps
- Apps running on devices that don’t have a browser, like those running on iOT
- Confidential client applications
- Applications may sign-in automatically
- Uses the MSAL
ConfidentialClientApplicationclass - Examples:
- Web apps calling a web API
- Web APIs calling a web API
- Daemon apps, even when implemented as a console service like a Linux daemon or a Windows service
Builder model
var clientApp = PublicClientApplicationBuilder.Create(client_id)
.Build();
Authority modifier
var clientApp = PublicClientApplicationBuilder.Create(client_id)
.WithAuthority(AzureCloudInstance.AzurePublic, tenant_id)
.Build();
Redirect URI modifier
var clientApp = PublicClientApplicationBuilder.Create(client_id)
.WithAuthority(AzureCloudInstance.AzurePublic, tenant_id)
.WithRedirectUri("http://localhost")
.Build();
Acquring a token interactively
string[] scopes = { "user.read" };
var authResult = await clientApp
.AcquireTokenInteractive(scopes)
.ExecuteAsync();
string token = authResult.AccessToken;
Demo: Interactive authentication using MSAL.NET
::: notes
-
Open a browser and navigate to https://portal.azure.com
-
Navigate to Azure Active Directory
-
Native to your recently created application registration
-
Record the value of the Client Id field
-
Open Visual Studio Code
-
Using a terminal, create a new .NET project named MsalDemo:
dotnet new console --name MsalDemo --output . -
Import the Microsoft.Identity.Client package from NuGet:
dotnet add package Microsoft.Identity.Client -
Open the Program.cs file
-
Add the following using statements:
using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Identity.Client; -
Update the Main method to be an asynchronous entry point:
static async Task Main(string[] args) -
Within the Main method, add the following code:
string clientId = "<client-id>"; var app = PublicClientApplicationBuilder .Create(clientId) .WithAuthority("https://login.microsoftonline.com/common") .WithRedirectUri("http://localhost") .Build(); List<string> scopes = new List<string> { "user.read" }; var result = await app.AcquireTokenInteractive(scopes) .ExecuteAsync(); Console.WriteLine(result.AccessToken); -
Using a terminal, build and run the application:
dotnet run -
Observe the updated messages in the console
-
Return to Visual Studio Code and run the following command in the terminal to import the Flurl.Http package:
dotnet add package Flurl.Http -
Return to the Program.cs file and add the following using statements:
using Flurl.Http; -
Within the Main method, add the following code:
string json = await "https://graph.microsoft.com/beta/me" .WithOAuthBearerToken(result.AccessToken) .GetStringAsync(); Console.WriteLine(json); -
Using a terminal, build and run the application:
dotnet run -
Observe the updated messages in the console
:::