如何将不记名令牌转换为 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 身份验证中间件将为您完成大部分繁重工作。
我有一个 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 身份验证中间件将为您完成大部分繁重工作。