如何将不记名令牌转换为 MVC 应用程序的身份验证 cookie

How to convert bearer token into authentication cookie for MVC app

我有一个 3 层应用程序结构。有一个面向最终用户的 cordova js 应用程序,一个用作 OpenID 授权机构的 identityserver3 的实现,以及一个将通过 cordova 应用程序中的应用程序内浏览器访问的 MVC 应用程序。

用户的起始入口点是 cordova 应用程序。他们通过应用内浏览器登录,然后可以访问应用程序功能或单击 link 打开应用内浏览器并访问 MVC 应用。

我们保护 MVC 网站的策略是使用不记名令牌身份验证,因为我们已经从应用程序登录过一次,并且不想在用户被定向到 MVC 应用程序时提示他们再次登录:

app.Map("/account", account =>
{
    account.UseIdentityServerBearerTokenAuthentication(new IdentityServer3.AccessTokenValidation.IdentityServerBearerTokenAuthenticationOptions()
    {
        Authority = "https://localhost:44333/core",
        RequiredScopes = new string[] { "scope" },
        DelayLoadMetadata = true,
        TokenProvider = new QueryStringOAuthBearerProvider(),
        ValidationMode = ValidationMode.ValidationEndpoint, 
    });
}

由于在查询字符串上保留 access_token 很痛苦,我实现了自定义 OAuthBearerAuthenticationProvider:

public class QueryStringOAuthBearerProvider : OAuthBearerAuthenticationProvider
{
    private static ILog logger = LogManager.GetLogger(typeof(QueryStringOAuthBearerProvider));
    public override Task RequestToken(OAuthRequestTokenContext context)
    {
        logger.Debug($"Searching for query-string bearer token for authorization on request {context.Request.Path}");

        string value = GetAccessTokenFromQueryString(context.Request);

        if (!string.IsNullOrEmpty(value))
        {
            context.Token = value;
            //Save the token as a cookie so the URLs doesn't need to continue passing the access_token
            SaveAccessTokenToCookie(context.Request, context.Response, value);
        }
        else
        {
            //Check for the cookie
            value = GetAccessTokenFromCookie(context.Request);
            if (!string.IsNullOrEmpty(value))
            {
                context.Token = value;
            }
        }

        return Task.FromResult<object>(null);
    }
    [cookie access methods not very interesting]
}

这有效,并允许 MVC 应用程序不必将访问令牌保存到每个请求中,但将访问令牌存储为通用 cookie 似乎是错误的。

我真正想做的是使用访问令牌与 OpenID 端点一起工作,并发出一个表单身份验证样式的 cookie,它响应注销。我发现我可以添加 account.UseOpenIdConnectAuthentication(..),但如果我通过 access_token 进行身份验证,OpenIdConnectAuthentication 位将被简单地跳过。有什么想法吗?

您不需要——访问令牌旨在用于调用网络 API。您使用来自 OIDC 的 id_token 对用户进行身份验证,并从内部的声明中发出您的本地身份验证 cookie。 Microsoft OpenIdConnect 身份验证中间件将为您完成大部分繁重工作。