【问题标题】:ADAL v3: How to authenticate using UserPasswordCredential?ADAL v3:如何使用 UserPasswordCredential 进行身份验证?
【发布时间】:2017-03-22 18:09:26
【问题描述】:

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

【问题讨论】:

    标签: adal


    【解决方案1】:

    为了详细说明已接受答案的第二部分,这里是发出 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;
            }
        }
    

    【讨论】:

    • 显然你不会在这里硬编码东西,他们在这里说明解决方案:)
    • 你救了我的命
    • @Burf2000 我不明白为什么不 - 为什么不尝试将此代码复制到控制台应用程序并进行测试?我唯一能看到它停止工作的是,如果微软改变了他们将允许通过这种机制进行身份验证的登录/凭据类型。
    • 我认为我们的应用是私有的,所以我们没有设法让它工作
    【解决方案2】:

    如果您使用客户端应用程序进行开发,您可以参考以下代码获取令牌:

    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}
    

    【讨论】:

    • 谢谢。 docs.microsoft.com 上的新文档站点非常难以阅读,这使得 adal v3 变得不必要难以使用,恕我直言。
    • 在这种情况下我们在哪里使用客户端密码?我认为我们需要它。
    • @Trondh DITTO,我已经厌倦了浪费这么多时间去追这个废话
    • 已尝试,出现以下错误请求正文必须包含以下参数:'client_secret or client_assertion'
    • 是否可以使用证书而不是用户名和密码构造请求?
    猜你喜欢
    • 1970-01-01
    • 2018-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多