Acquire a token to call a web API using username and password (desktop app) - Microsoft identity platform (2024)

  • Article

In your desktop applications, you can use the username and password flow, also known as Resource Owner Password Credentials (ROPC), to acquire a token silently.

Warning

The username and password flow is not recommended as the application will be asking a user for their password directly, which is an insecure pattern. For more information about the risks and challenges the ROPC flow poses, refer to "What’s the solution to the growing problem of passwords?.

Additionally, by using a username and password, developers give up a number of things, including:

  • Core tenets of modern identity - A password can get phished and replayed because a shared secret can be intercepted.
  • Multi-factor authentication (MFA) - Users can't sign in because there's no interaction.
  • Single sign-on (SSO) capabilities.

The username and password flow also has the following constraints:

  • The username and password flow isn't compatible with Conditional Access and multi-factor authentication. If your app runs in a Microsoft Entra tenant where the admin requires multi-factor authentication, like most organizations do, you can't use this flow.
  • It only works for work and school accounts, not personal Microsoft Accounts.
  • The flow is available on .NET desktop and .NET, but not on UWP.

Using a username and password is useful in some cases, such as DevOps scenarios. However, if you want to use a username and password in interactive scenarios where you provide your own UI, consider moving away from it.

The preferred flow for acquiring a token silently on Windows is using the Windows authentication broker. Alternatively, developers can also use the Device code flow on devices without access to the web browser.

If you're building a desktop application that signs in users with social identities using the Resource Owner Password Credentials (ROPC) flow, see how to sign in users with social identities by using Azure AD B2C

Use the ROPC flow

  • .NET
  • Java
  • macOS
  • Node.js
  • Python

IPublicClientApplicationcontains the method AcquireTokenByUsernamePassword.

The following sample presents a simplified case.

static async Task GetATokenForGraph(){ string authority = "https://login.microsoftonline.com/contoso.com"; string[] scopes = new string[] { "user.read" }; IPublicClientApplication app; app = PublicClientApplicationBuilder.Create(clientId) .WithAuthority(authority) .Build(); var accounts = await app.GetAccountsAsync(); AuthenticationResult result = null; if (accounts.Any()) { result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault()) .ExecuteAsync(); } else { try { var securePassword = new SecureString(); foreach (char c in "dummy") // you should fetch the password securePassword.AppendChar(c); // keystroke by keystroke result = await app.AcquireTokenByUsernamePassword(scopes, "[email protected]", securePassword) .ExecuteAsync(); } catch(MsalException) { // See details below } } Console.WriteLine(result.Account.Username);}

The following sample presents the most current case, with explanations of the kind of exceptions you can get and their mitigations.

static async Task GetATokenForGraph(){ string authority = "https://login.microsoftonline.com/contoso.com"; string[] scopes = new string[] { "user.read" }; IPublicClientApplication app; app = PublicClientApplicationBuilder.Create(clientId) .WithAuthority(authority) .Build(); var accounts = await app.GetAccountsAsync(); AuthenticationResult result = null; if (accounts.Any()) { result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault()) .ExecuteAsync(); } else { try { var securePassword = new SecureString(); foreach (char c in "dummy") // you should fetch the password keystroke securePassword.AppendChar(c); // by keystroke result = await app.AcquireTokenByUsernamePassword(scopes, "[email protected]", securePassword) .ExecuteAsync(); } catch (MsalUiRequiredException ex) when (ex.Message.Contains("AADSTS65001")) { // Here are the kind of error messages you could have, and possible mitigations // ------------------------------------------------------------------------ // MsalUiRequiredException: AADSTS65001: The user or administrator has not consented to use the application // with ID '{appId}' named '{appName}'. Send an interactive authorization request for this user and resource. // Mitigation: you need to get user consent first. This can be done either statically (through the portal), /// or dynamically (but this requires an interaction with Azure AD, which is not possible with // the username/password flow) // Statically: in the portal by doing the following in the "API permissions" tab of the application registration: // 1. Click "Add a permission" and add all the delegated permissions corresponding to the scopes you want (for instance // User.Read and User.ReadBasic.All) // 2. Click "Grant/revoke admin consent for <tenant>") and click "yes". // Dynamically, if you are not using .NET (which does not have any Web UI) by // calling (once only) AcquireTokenInteractive. // remember that Username/password is for public client applications that is desktop/mobile applications. // If you are using .NET or don't want to call AcquireTokenInteractive, you might want to: // - use device code flow (See https://aka.ms/msal-net-device-code-flow) // - or suggest the user to navigate to a URL to consent: https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id={clientId}&response_type=code&scope=user.read // ------------------------------------------------------------------------ // ------------------------------------------------------------------------ // ErrorCode: invalid_grant // SubError: basic_action // MsalUiRequiredException: AADSTS50079: The user is required to use multi-factor authentication. // The tenant admin for your organization has chosen to oblige users to perform multi-factor authentication. // Mitigation: none for this flow // Your application cannot use the Username/Password grant. // Like in the previous case, you might want to use an interactive flow (AcquireTokenInteractive()), // or Device Code Flow instead. // Note this is one of the reason why using username/password is not recommended; // ------------------------------------------------------------------------ // ------------------------------------------------------------------------ // ex.ErrorCode: invalid_grant // subError: null // Message = "AADSTS70002: Error validating credentials. // AADSTS50126: Invalid username or password // In the case of a managed user (user from an Azure AD tenant opposed to a // federated user, which would be owned // in another IdP through ADFS), the user has entered the wrong password // Mitigation: ask the user to re-enter the password // ------------------------------------------------------------------------ // ------------------------------------------------------------------------ // ex.ErrorCode: invalid_grant // subError: null // MsalServiceException: ADSTS50034: To sign into this application the account must be added to // the {domainName} directory. // or The user account does not exist in the {domainName} directory. To sign into this application, // the account must be added to the directory. // The user was not found in the directory // Explanation: wrong username // Mitigation: ask the user to re-enter the username. // ------------------------------------------------------------------------ } catch (MsalServiceException ex) when (ex.ErrorCode == "invalid_request") { // ------------------------------------------------------------------------ // AADSTS90010: The grant type is not supported over the /common or /consumers endpoints. // Please use the /organizations or tenant-specific endpoint. // you used common. // Mitigation: as explained in the message from Azure AD, the authority you use in the application needs // to be tenanted or otherwise "organizations". change the // "Tenant": property in the appsettings.json to be a GUID (tenant Id), or domain name (contoso.com) // if such a domain is registered with your tenant // or "organizations", if you want this application to sign-in users in any Work and School accounts. // ------------------------------------------------------------------------ } catch (MsalServiceException ex) when (ex.ErrorCode == "unauthorized_client") { // ------------------------------------------------------------------------ // AADSTS700016: Application with identifier '{clientId}' was not found in the directory '{domain}'. // This can happen if the application has not been installed by the administrator of the tenant or consented // to by any user in the tenant. // You may have sent your authentication request to the wrong tenant // Cause: The clientId in the appsettings.json might be wrong // Mitigation: check the clientId and the app registration // ------------------------------------------------------------------------ } catch (MsalServiceException ex) when (ex.ErrorCode == "invalid_client") { // ------------------------------------------------------------------------ // AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'. // Explanation: this can happen if your application was not registered as a public client application in Azure AD // Mitigation: in the Azure portal, edit the manifest for your application and set the `allowPublicClient` to `true` // ------------------------------------------------------------------------ } catch (MsalServiceException) { throw; } catch (MsalClientException ex) when (ex.ErrorCode == "unknown_user_type") { // Message = "Unsupported User Type 'Unknown'. Please see https://aka.ms/msal-net-up" // The user is not recognized as a managed user, or a federated user. Azure AD was not // able to identify the IdP that needs to process the user throw new ArgumentException("U/P: Wrong username", ex); } catch (MsalClientException ex) when (ex.ErrorCode == "user_realm_discovery_failed") { // The user is not recognized as a managed user, or a federated user. Azure AD was not // able to identify the IdP that needs to process the user. That's for instance the case // if you use a phone number throw new ArgumentException("U/P: Wrong username", ex); } catch (MsalClientException ex) when (ex.ErrorCode == "unknown_user") { // the username was probably empty // ex.Message = "Could not identify the user logged into the OS. See https://aka.ms/msal-net-iwa for details." throw new ArgumentException("U/P: Wrong username", ex); } catch (MsalClientException ex) when (ex.ErrorCode == "parsing_wstrust_response_failed") { // ------------------------------------------------------------------------ // In the case of a Federated user (that is owned by a federated IdP, as opposed to a managed user owned in an Azure AD tenant) // ID3242: The security token could not be authenticated or authorized. // The user does not exist or has entered the wrong password // ------------------------------------------------------------------------ } } Console.WriteLine(result.Account.Username);}

For more information on all the modifiers that can be applied to AcquireTokenByUsernamePassword, see AcquireTokenByUsernamePasswordParameterBuilder.

Next steps

Move on to the next article in this scenario,Call a web API from the desktop app.

Acquire a token to call a web API using username and password (desktop app) - Microsoft identity platform (2024)
Top Articles
How To Create a Pitch Deck for M&A Deals | CapLinked
Gnosis (GNO) Price Prediction 2024, 2025–2030 | CoinCodex
Craigslist Houses For Rent In Denver Colorado
Mopaga Game
Shs Games 1V1 Lol
Doublelist Paducah Ky
Cosentyx® 75 mg Injektionslösung in einer Fertigspritze - PatientenInfo-Service
Slapstick Sound Effect Crossword
Draconic Treatise On Mining
Sunday World Northern Ireland
Carter Joseph Hopf
ATV Blue Book - Values & Used Prices
OpenXR support for IL-2 and DCS for Windows Mixed Reality VR headsets
Local Collector Buying Old Motorcycles Z1 KZ900 KZ 900 KZ1000 Kawasaki - wanted - by dealer - sale - craigslist
Most McDonald's by Country 2024
Eva Mastromatteo Erie Pa
Ess.compass Associate Login
Race Karts For Sale Near Me
How to Watch the Fifty Shades Trilogy and Rom-Coms
Nevermore: What Doesn't Kill
Closest Bj Near Me
Panolian Batesville Ms Obituaries 2022
Craigslist Battle Ground Washington
How to Watch Every NFL Football Game on a Streaming Service
The Boogeyman (Film, 2023) - MovieMeter.nl
Cognitive Science Cornell
Cardaras Funeral Homes
Rs3 Bring Leela To The Tomb
Gt7 Roadster Shop Rampage Engine Swap
Christmas Days Away
60 Second Burger Run Unblocked
What Happened To Father Anthony Mary Ewtn
Myhrconnect Kp
Great Clips On Alameda
Roto-Rooter Plumbing and Drain Service hiring General Manager in Cincinnati Metropolitan Area | LinkedIn
Tenant Vs. Occupant: Is There Really A Difference Between Them?
Usf Football Wiki
Craigslist Pets Huntsville Alabama
Culvers Lyons Flavor Of The Day
Trivago Myrtle Beach Hotels
Frommer's Philadelphia &amp; the Amish Country (2007) (Frommer's Complete) - PDF Free Download
Gateway Bible Passage Lookup
11526 Lake Ave Cleveland Oh 44102
Bob And Jeff's Monticello Fl
Directions To The Closest Auto Parts Store
Arcane Bloodline Pathfinder
Ehc Workspace Login
Aurora Southeast Recreation Center And Fieldhouse Reviews
Gander Mountain Mastercard Login
Minecraft: Piglin Trade List (What Can You Get & How)
Shiftselect Carolinas
Grace Family Church Land O Lakes
Latest Posts
Article information

Author: Duncan Muller

Last Updated:

Views: 5887

Rating: 4.9 / 5 (79 voted)

Reviews: 86% of readers found this page helpful

Author information

Name: Duncan Muller

Birthday: 1997-01-13

Address: Apt. 505 914 Phillip Crossroad, O'Konborough, NV 62411

Phone: +8555305800947

Job: Construction Agent

Hobby: Shopping, Table tennis, Snowboarding, Rafting, Motor sports, Homebrewing, Taxidermy

Introduction: My name is Duncan Muller, I am a enchanting, good, gentle, modern, tasty, nice, elegant person who loves writing and wants to share my knowledge and understanding with you.