【问题标题】:Authorize at web app with access token from web api使用来自 web api 的访问令牌在 web 应用程序上授权
【发布时间】:2016-12-10 11:28:50
【问题描述】:

我有一个连接到数据库的 web api,它使用 OpenIddict 和密码流(资源所有者密码凭据授予)提供访问令牌:

services.AddOpenIddict<TestUser, IdentityRole<Guid>, CompleteContext, Guid>()
                .EnableTokenEndpoint("/connect/token")
                .AllowPasswordFlow()
                .AllowRefreshTokenFlow()
                .DisableHttpsRequirement()
                .AddEphemeralSigningKey();

Web api 具有受保护的操作,只能使用有效的访问令牌调用。这工作正常。

我有一个网络应用程序,它应该使用相同的访问令牌进行授权。用户输入他的凭据,Web 应用程序将它们发送到 API 以获取访问令牌。我以为网络应用程序可以使用此访问令牌进行授权,但我现在不知道如何在 asp.net 核心中设置中间件。

背景: web 应用程序和 web api 应该在不同的服务器上运行,稍后我想创建移动应用程序,它使用 web api 来访问数据。这就是我想使用令牌的原因。我希望 web api 成为唯一可以访问数据库的项目。

编辑更多背景: 该网络应用程序是一个 mvc 6 应用程序,具有标准用户功能:注册、登录、注销、电子邮件确认以及与用户生成内容的一些交互。所有这些内容都应该存储在数据库中。因为我以后可能需要添加一个移动应用程序,所以我想要一个单独的 web api 来存储和访问数据库中的数据。 Web api 的唯一目的是处理数据访问。 mvc web 应用程序应该与 web api 通信以获取和存储数据。用户必须经过身份验证才能使用 Web 应用程序,并且 Web 应用程序必须经过身份验证才能访问 Web api。没有第三方应用,这让我想到了密码流程。我想,用户在 Web 应用程序中输入他的凭据以从 Web api 获取访问令牌。我的计划是,访问令牌存储在 cookie 中,以便 web 应用程序可以在需要时使用它来访问 web api。我也可以使用此访问令牌在 Web 应用程序上进行身份验证和授权吗?可能类似于创建自定义 SignInManagerUserManager,或者授予 Web 应用程序数据库访问权限并使用标准 asp.net 身份。还是有其他更好的解决方案?

【问题讨论】:

    标签: c# oauth-2.0 authorization asp.net-core openiddict


    【解决方案1】:

    我以为网络应用可以使用此访问令牌进行授权,但我现在不知道如何在 asp.net core 中设置中间件。

    ASP.NET Core 中没有任何内容可以帮助您实现“资源所有者密码凭据授予”客户端。幸运的是,您可以使用HttpClient 轻松完成这项工作。以下是您可以这样做的方法(请注意,错误处理留作练习):

    public async Task<IActionResult> SignIn(string username, string password)
    {
        if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
        {
            return View("MissingCredentials");
        }
    
        var request = new HttpRequestMessage(HttpMethod.Post, "http://server.com/connect/token");
        request.Content = new FormUrlEncodedContent(new Dictionary<string, string>
        {
            ["client_id"] = "your client_id",
            ["client_secret"] = "your client_secret",
            ["grant_type"] = "password",
            ["username"] = "username",
            ["password"] = "password"
        });
    
        var response = await client.SendAsync(request, notification.Request.CallCancelled);
        response.EnsureSuccessStatusCode();
    
        var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
        var token = payload.Value<string>("access_token");
        if (string.IsNullOrEmpty(token))
        {
            return View("InvalidCredentials");
        }
    
        var identity = new ClaimsIdentity("Cookies");
        identity.AddClaim(new Claim("access_token", token));
    
        return SignIn(new ClaimsPrincipal(identity), "Cookies");
    }
    

    或者,您可以考虑使用授权代码之类的交互式流程,这将允许您使用由 ASP.NET 团队开发的 OpenID Connect 客户端中间件。你可以试试这个OpenIddict MVC sample 来了解它是如何工作的。

    【讨论】:

    • 感谢您的回复。我想我没有说清楚。我的 web api 和 web 应用程序是分开的。我可以使用 HttpClient 从我的 web api 接收访问令牌,但我想将此访问令牌用于 web 应用程序的授权,而不仅仅是 web api。但也许在这里使用标准的 asp.net 核心身份进行授权会更好,即使 web api 不再是唯一具有 db 访问权限的实例。
    • but I want to use this access token for the authorization at the web app and not only for the web api> 问题是“您希望如何将访问令牌从客户端传送到 Web 应用程序”?与身份验证 cookie 不同,访问令牌是客户端必须主动发送的东西(例如附加到 Authorization 标头或查询字符串)。
    • 是的,这是我的问题的一部分。我曾考虑将令牌保存在 cookie 中,但我不确定这是否是个好主意,因为通常您将访问令牌包含在请求的标头中。但是最好只有一个访问令牌,它可以用于 web 应用程序和 web api。我不确定最佳实践。我仍处于概念阶段,还可以在 Web 应用程序上实现 asp.net 核心身份,该身份使用在您的解决方案的帮助下获得的访问令牌连接到 api。但是有 2 种身份验证方式和两个具有 db 访问权限的实例。
    • 您真的应该更新您的问题,以包含有关您的要求的更多详细信息,这些细节确实不清楚:您的 Web 应用程序是 SPA 应用程序吗?一个好的旧 MVC 应用程序?会有 API 控制器吗?
    • 是的,你是对的。我刚刚用更多细节编辑了我的问题。
    猜你喜欢
    • 1970-01-01
    • 2015-04-24
    • 2019-03-22
    • 2012-09-24
    • 1970-01-01
    • 2012-06-14
    • 1970-01-01
    • 2021-03-25
    • 1970-01-01
    相关资源
    最近更新 更多