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 tocode
redirect_uri
: One of the Redirect Uris specified in application registration processscope
: List of permissions that you are requesting consent toresponse_mode
: Eitherform_post
orquery
- (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_token
property 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%2F
query string parameter -
Add the
&scope=user.read
query string parameter -
Add the
&response_type=code
query string parameter -
Add the
&response_mode=query
query 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
code
query 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/token
and following these steps:-
Add a
client_id
parameter with your unique Client Id from the application registration -
Add a
code
parameter with the code you recorded earlier in this lab -
Add a
redirect_uri
parameter with a value ofhttp://localhost
-
Add a
scope
parameter with a value ofuser.read
-
Add a
grant_type
parameter with a value ofauthorization_code
-
Issue the HTTP POST request
-
-
Observe the JSON response of the request, it should contain an
access_token
property with your MSAL token -
Build a HTTP GET request using the endpoint
https://graph.microsoft.com/beta/me
and 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
PublicClientApplication
class - 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
ConfidentialClientApplication
class - 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
:::