简体   繁体   中英

Obtaining a token for a Web API using user credentials

I've created a new user account in my test AAD tenant, say testuser1@mytenant.onmicrosoft.com and set a password for it. This new account is a member of a security group that can access a specific Web API. I'm trying to write a test (a console program) that non-interactively obtains an access token using the user credentials and the app id as audience and then calls an endpoint.

How do I do that?

Update :

I'm trying to write a set of integration security tests for my Web API application. The application uses AAD groups it gets as a set of claims and treats them as roles. So I want a set of test user accounts with a known password with different roles to test behavior of an endpoint under different security contexts. The approach worked for me for years with classic AD (where I could impersonate a user using login/password pair and perform a SOAP call to a service with Windows Auth enabled).

Updated2:

I could use a set of app registrations instead of test user accounts and get a token without no problem using client_id/client_secret pair but assigning an enterprise application to a security group requires premium AAD tier which is very expensive :(

This is basically what Resource Owner Password Credentials (ROPC) grant flow is for. You give Azure AD your app's credentials with a user's credentials and you get an access token.

This flow should not be used for authentication typically, as it exists in the standard mainly as a legacy upgrade path. And it does not work with federated users, users with MFA or with an expired password. However, your case of an automated test is one of the scenarios where I think its usage is acceptable.

Here is an example of the call in C#:

string tokenUrl = $"https://login.microsoftonline.com/joonasapps.onmicrosoft.com/oauth2/token";
var req = new HttpRequestMessage(HttpMethod.Post, tokenUrl);

req.Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
    ["grant_type"] = "password",
    ["client_id"] = "23d3be1b-a671-4452-a928-78fb842cb969",
    ["client_secret"] = "REDACTED",
    ["resource"] = "https://graph.windows.net",
    ["username"] = "testuser@joonasapps.onmicrosoft.com",
    ["password"] = "REDACTED"
});

using (var client = new HttpClient())
{
    var res = await client.SendAsync(req);

    string json = await res.Content.ReadAsStringAsync();
}

ADAL.NET does not expose an overload for doing this AFAIK so you need to do it manually like this. You'll need to replace the parameters with your app's credentials + your user's credentials of course. The token URL also needs your tenant id or domain name. Change the resource parameter to your API's client id/app ID URI.

By "non-interactively" are you referring to the login window? If so given the flow and architecture you've described, this is not possible. How else would you get the users credentials?

You should use this article as a reference when building your solution so you understand the various OAuth 2.0 flows and options, including those for a native application.

https://docs.microsoft.com/en-us/azure/active-directory/develop/authentication-scenarios#native-application-to-web-api

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM