使用来自 Web api 的访问令牌在 Web 应用程序中授权

Authorize at web app with access token from web api

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

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

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

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

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

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

I thought, that the web app can use this access token for authorization, but I don't now how to set up the middleware in asp.net core.

ASP.NET Core 中没有任何内容可以帮助您实现 "resource owner password credentials grant" 客户端。幸运的是,您可以使用 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 以了解其工作原理。