ADAL v3: 如何使用 UserPasswordCredential 进行身份验证?

7

ADAL v3中有一个UserPasswordCredential类,但我找不到一个可用的实现。没有AcquireToken重载方法接受UserPasswordCredential或UserCredential类型。在ADAL v3中执行用户名和密码流的正确方法是什么?这段代码使用的是完整的.Net 4.5。

2个回答

5
为了阐述被接受答案的第二部分,这里提供一个实现来进行POST请求:
    From SettingHelper: public static string GetAuthorityEndpoint(string azuretenantId) => $"https://login.microsoftonline.com/{azuretenantId}/";

    private static async Task<OAuthResult> AuthenticateAsync(string resource = "https://yourAzureADProtectedResource.url/")
    {
        var oauthEndpoint = new Uri(new Uri(SettingsHelper.GetAuthorityEndpoint("your AAD Tenent ID")), "oauth2/token");

        using (var client = new HttpClient())
        {
            var result = await client.PostAsync(oauthEndpoint, new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("resource", resource),
                new KeyValuePair<string, string>("client_id", "your AAD App Id"),
                new KeyValuePair<string, string>("grant_type", "password"),
                new KeyValuePair<string, string>("username", "your.user@yourtenent.url"),
                new KeyValuePair<string, string>("password", "your password"),
                new KeyValuePair<string, string>("scope", "openid"),
                new KeyValuePair<string, string>("client_secret", "an access key for your AAD App"),
            }));

            var content = await result.Content.ReadAsStringAsync();
            var authResult = JsonConvert.DeserializeObject<OAuthResult>(content);
            return authResult;
        }
    }

    class OAuthResult
    {
        public string Token_Type { get; set; }
        public string Scope { get; set; }
        public int Expires_In { get; set; }
        public int Ext_Expires_In { get; set; }
        public int Expires_On { get; set; }
        public int Not_Before { get; set; }
        public Uri Resource { get; set; }
        public string Access_Token { get; set; }
    }

您可以按照以下方式使用身份验证结果:

您可以按以下方式使用Auth结果:

    private async Task<HttpClient> GetHttpClientWithAzureADAuthentication()
    {
        OAuthResult authResult;
        try
        {
            authResult = await AuthenticateAsync();
            var httpClient = GetHttpClient();
            httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {authResult.Access_Token}");

            return httpClient;
        }
        catch (Exception e)
        {
            Debug.WriteLine(e);
            throw;
        }
    }

显然,您不会在这里硬编码东西,它们在这里只是为了说明解决方案 :) - Ian Robertson
1
你刚刚救了我的命。 - Hieu Le
@Burf2000 我不知道为什么不行,你为什么不试着将此代码复制到控制台应用程序中并测试一下呢?我唯一能想到的阻止它工作的事情是如果Microsoft已经改变了他们允许通过这种机制进行身份验证的登录/凭据类型。 - Ian Robertson
我认为我们的应用程序是私有的,因此我们还没有成功地使其工作。 - Burf2000

4

如果您正在开发客户端应用程序,您可以参考下面的代码获取令牌:

string authority = "https://login.microsoftonline.com/xxxx.onmicrosoft.com";
string resrouce = "https://graph.windows.net";
string clientId = "";
string userName = "";
string password = "";
UserPasswordCredential userPasswordCredential = new UserPasswordCredential(userName,password);
AuthenticationContext authContext = new AuthenticationContext(authority);
var token= authContext.AcquireTokenAsync(resrouce,clientId, userPasswordCredential).Result.AccessToken;

如果你正在开发Web应用程序(这不是常见情况),则ADAL V3中没有支持此方案的方法。作为解决方法,你可以自己构建请求。以下是一个示例供参考:

POST: https://login.microsoftonline.com/xxxxx.onmicrosoft.com/oauth2/token

Content-Type: application/x-www-form-urlencoded
resource={resource}&client_id={clientId}&grant_type=password&username={userName}&password={password}&scope=openid&client_secret={clientSecret}

4
谢谢。我认为learn.microsoft.com上的新文档站点非常难以阅读,这使得使用adal v3变得不必要地困难。 - Trondh
在这种情况下,我们在哪里使用客户端密钥?我认为我们需要它。 - Kurkula
4
@Trondh 同感,我已经非常厌倦了花费大量时间追踪这些垃圾。 - Mikee
尝试时出现以下错误:请求正文必须包含以下参数:'client_secret或client_assertion'。 - Furqan Misarwala
能否使用证书而不是用户名和密码构建请求? - cty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接