【问题标题】:Acces Azure stored web api from xamarin android从 xamarin android 访问 Azure 存储的 Web api
【发布时间】:2018-01-17 04:47:37
【问题描述】:

我现在正在努力尝试从 Xamarin Forms Android 应用程序访问 azure 存储的 web api(它是默认的 web api,带有值控制器等)。我找到了大量关于如何实现这一点的文档,但我不想使用“传统方式”,如处理 AuthenticationContext\Authentication Result。该请求是在应用程序中使用自定义登录表单,而不是 Microsoft、Google 等提供的登录表单。

我的登录是这样的:

    HttpClient client = new HttpClient();
    var tokenEndpoint = "https://login.microsoftonline.com/testdir.onmicrosoft.com/oauth2/token";
    var body = "resource=www.graph.microsoft.com&client_id=" + App.ClientId + "&grant_type=password&username=" + UsernameEntry.Text + "&password=" + PasswordEntry.Text + ""; 
    var stringContent = new StringContent(body, Encoding.UTF8, "application/x-www-form-urlencoded");
    var result = await client.PostAsync(tokenEndpoint, stringContent).ContinueWith<string>(response => response.Result.Content.ReadAsStringAsync().Result);
    var jobject = JObject.Parse(result);
    App.AccessToken = jobject["access_token"].Value<string>();

这就像一个魅力。我现在有了访问令牌,我可以使用它从 Azure AD 中检索用户或任何内容。

我想要一些类似的东西来从 web api 中检索数据。我希望在幕后进行登录,而不是通过提供 Microsoft 登录表单并提示用户登录。

我尝试过这样的事情:

    tokenEndpoint = "https://login.microsoftonline.com/testdir.onmicrosoft.com/oauth2/authorize";
    body = "client_id=xxxx&response_type=code&redirect_uri=https://testapi.azurewebsites.net/";
    result = await client.PostAsync(tokenEndpoint, stringContent).ContinueWith<string>(response =>   response.Result.Content.ReadAsStringAsync().Result);
    jobject = JObject.Parse(result);

但我总是收到一条错误消息,指出用户必须登录。 (我认为基本上它会尝试生成一个 Microsoft 登录表单,并且在成功尝试后它将直接使用访问 api 所需的授权代码)。

如果我能从一次调用中检索授权码,然后用它来查询 web api,那就太棒了。

以下是我发现的一些有用的问题,描述了类似的问题\场景,但我没有设法将所有信息包装成一段工作代码:

Getting Authorization has been denied for this request in Fiddler with Azure AD

Use OAuth2 for authentication against Azure AD to call WebAPI

Unable to use bearer token to access AAD-secure Web API

任何帮助将不胜感激。谢谢!

【问题讨论】:

    标签: oauth-2.0 xamarin.android asp.net-web-api2 azure-active-directory


    【解决方案1】:

    花了很长时间,但我终于让它工作了。我使用了与登录部分几乎相同的方法,但有所不同(要查看有效登录机制的代码示例,请参阅问题的第一部分)。 使用以下代码 sn-p 我能够获取一个令牌,然后使用它来访问我的自定义 API:

    var clientId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
    var client_secret = "yyyy";
    HttpClient client = new HttpClient();
    string tokenEndpoint = "https://login.microsoftonline.com/testTenant.onmicrosoft.com/oauth2/token";
    var body = "resource=" + clientId + "&client_id=" + clientId + "&client_secret=" + client_secret + "&grant_type=password&username=" + username + "&password=" + password + "";
    var stringContent = new StringContent(body, Encoding.UTF8, "application/x-www-form-urlencoded");
    var result = await client.PostAsync(tokenEndpoint, stringContent).ContinueWith<string>(response => response.Result.Content.ReadAsStringAsync().Result);
            JObject jobject = JObject.Parse(result);
    var accessToken = jobject["access_token"].Value<string>();
    

    棘手的部分是弄清楚参数“resource”和“client_id”必须与 Azure 中注册的自定义 Web api 的 App ID 具有相同的值。就在我进行允许代码工作的更改之前,我收到了以下错误:

    1) 在名为 testTenant.onmicrosoft.com 的租户中找不到名为 https://customApi.azurewebsites.net/ 的应用程序。如果租户管理员未安装应用程序或未获得租户中任何用户的同意,则可能会发生这种情况。您可能已将身份验证请求发送给错误的租户。

    这里的问题是我使用“https://customApi.azurewebsites.net/”作为资源。

    2) 应用程序“xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”正在为自己请求令牌。仅当使用基于 GUID 的应用标识符指定资源时才支持此方案。

    在第一个错误之后,我尝试将资源替换为“https://testTenant.onmicrosoft.com/CustomApi”。看到错误信息,我用我的api的APP ID替换了链接。成功了。

    在某些情况下,尽管您生成了有效的密钥,但您可能还会收到一条错误消息,指出 client_secret 无效。我不得不重新生成几次密钥,然后它就起作用了。

    我还在MSDN 上发布了关于此问题的帖子。您可以在那里找到有用的资源。

    请记住,这不是推荐的方法,并且存在严重的安全风险。但这种情况可能很少见:

    “有时密码授予机制可能是“可接受的”——例如,在仅安装在批准的公司计算机上供内部用户使用的非公共应用程序中。”这正是我的情景。

    Shawn 提供了有价值的文档,说明了如何操作以及推荐的做法。

    【讨论】:

      【解决方案2】:

      您正在寻找Resource Owner Password Credentials Grant

      有一个关于这个流程的基本文档here

      您应该知道,通常情况下,Azure Active Directory 团队强烈反对使用此流程,因为它需要您的应用程序处理用户的用户名和密码,这会带来许多安全问题。

      请在此处阅读有关为什么不应该这样做的更多警告。

      Vittorio Bertocci - Using ADAL .NET to Authenticate Users via Username/Password

      Rich Randall - How to authenticate user with Azure Active Directory using OAuth 2.0?

      OAuth 2.0 Specification - Security Considerations

      总而言之:我已经向你展示了如何做到这一点......但你不应该这样做。

      【讨论】:

      • 谢谢肖恩。我已经使用文章中描述的机制来制作自定义登录表单。我正在努力从同样托管在 azure 中的自定义 Web api 中检索数据。我不知道如何检索所谓的“authorization_code”并在对我的自定义 api 的 http 请求中使用它。我知道不推荐我的方法,但我们的客户希望使用这种方法,因为实施的应用程序将在安全的内部网络中使用,并且应用程序只能在它们之间进行通信。
      • 抱歉,我不太了解您当前的问题。您不知道如何获取授权码然后​​获取访问令牌?授权码不能直接用于调用 API。它必须交换为访问令牌。您是否能够获得访问令牌?
      • 我能够从 microsoft graph 获取访问令牌并使用它登录 Azure AD。现在我想使用类似的机制来访问我实现的自定义 web api。如果我理解正确,您建议像我对登录场景 (https://login.microsoftonline.com/testdir.onmicrosoft.com/oauth2/token) 所做的那样使用对同一端点的调用,但将我创建的自定义 Web api 用作资源,而不是 microsoft graph,这将提供一个我可以的令牌用来访问我的api?我不知道如何用访问令牌交换授权码。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-27
      • 1970-01-01
      • 2020-06-03
      • 2021-12-18
      • 2017-02-24
      • 2017-07-24
      • 1970-01-01
      相关资源
      最近更新 更多