使用 MVC Client 4.7.1 和 IdentityServer4 进行身份验证
Authentication with MVC Client 4.7.1 and IdentityServer4
我正在尝试在 MVC 4.7.1 客户端和 ASP.NET Core 3.1 IdentityServer4 & ASP.NET 身份服务之间集成用户身份验证。
我一直在按照本教程进行 cookie 发布的身份验证:Refreshing your Legacy ASP.NET IdentityServer Client Applications (with PKCE)
到目前为止,MVC 客户端能够重定向到登录页面。登录后,我在以下函数中出现空错误:
private string RetrieveCodeVerifier(AuthorizationCodeReceivedNotification n)
{
string key = GetCodeVerifierKey(n.ProtocolMessage.State);
string codeVerifierCookie = n.Options.CookieManager.GetRequestCookie(n.OwinContext, key);
if (codeVerifierCookie != null)
{
var cookieOptions = new CookieOptions
{
SameSite = SameSiteMode.None,
HttpOnly = true,
Secure = n.Request.IsSecure
};
n.Options.CookieManager.DeleteCookie(n.OwinContext, key, cookieOptions);
}
string codeVerifier;
var cookieProperties = n.Options.StateDataFormat.Unprotect(Encoding.UTF8.GetString(Convert.FromBase64String(codeVerifierCookie)));
cookieProperties.Dictionary.TryGetValue("cv", out codeVerifier);
return codeVerifier;
}
显然 codeVerifierCookie 为空。
其余配置如下
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "cookie"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = "mvc.owin",
Authority = "https://localhost:44355",
RedirectUri = "http://localhost:5001/Auth/",
Scope = "openid profile scope1",
SignInAsAuthenticationType = "cookie",
RequireHttpsMetadata = false,
UseTokenLifetime = false,
RedeemCode = true,
SaveTokens = true,
ClientSecret = "secret",
ResponseType = "code",
ResponseMode = "query",
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
{
// set PKCE parameters
var codeVerifier = CryptoRandom.CreateUniqueId(32);
string codeChallenge;
using (var sha256 = SHA256.Create())
{
var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
codeChallenge = Base64Url.Encode(challengeBytes);
}
n.ProtocolMessage.SetParameter("code_challenge", codeChallenge);
n.ProtocolMessage.SetParameter("code_challenge_method", "S256");
// remember code_verifier (adapted from OWIN nonce cookie)
RememberCodeVerifier(n, codeVerifier);
}
return Task.CompletedTask;
},
AuthorizationCodeReceived = n =>
{
// get code_verifier
var codeVerifier = RetrieveCodeVerifier(n);
// attach code_verifier
n.TokenEndpointRequest.SetParameter("code_verifier", codeVerifier);
return Task.CompletedTask;
}
}
});
并且在 IdentityServer4 ConfigureServices 上:
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
var builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
// see https://identityserver4.readthedocs.io/en/latest/topics/resources.html
options.EmitStaticAudienceClaim = true;
})
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddInMemoryClients(Config.Clients)
.AddAspNetIdentity<ApplicationUser>();
最后,在IdentityServer4端Client.cs配置:
new Client
{
ClientId = "mvc.owin",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.Code,
ClientSecrets = {new Secret("secret".Sha256())},
RedirectUris = {"http://localhost:5001/Auth/"},
AllowedScopes = {"openid", "profile", "scope1"},
AllowPlainTextPkce = false,
RequirePkce = true,
RequireConsent = false,
// Token lifetimes
AuthorizationCodeLifetime = 60,
AccessTokenLifetime = 60,
IdentityTokenLifetime = 60
}
AccountController 其余的几乎都是基本的 IdentityServer4.Template,特别是 is4aspid.
- 有人试过同样的方法,知道什么地方失败了吗?
- 有没有办法用 JWT 代替 Cookies 来做到这一点?还有,缺点是什么?
编辑: 显然,此配置适用于 Firefox,我怀疑这是 Chrome 的 Same-Site cookie 策略的问题,因此 null 在 GetRequestCookie 中。问题是,IdentityServer4 在 HTTPS 上是 运行(否则,还有其他),而 MVC 客户端应用程序在 HTTP 上是 运行(注意:两者都在本地主机上)。我曾尝试使用 SameSite 策略 None、Lax、Strict,反之亦然,但均未成功。我不确定还能尝试什么。
最好的,
姆卡纳基斯。
声明 SameSite=None
的 Cookie 也必须标记为安全,这意味着您需要使用 https
阅读更多here
我正在尝试在 MVC 4.7.1 客户端和 ASP.NET Core 3.1 IdentityServer4 & ASP.NET 身份服务之间集成用户身份验证。
我一直在按照本教程进行 cookie 发布的身份验证:Refreshing your Legacy ASP.NET IdentityServer Client Applications (with PKCE)
到目前为止,MVC 客户端能够重定向到登录页面。登录后,我在以下函数中出现空错误:
private string RetrieveCodeVerifier(AuthorizationCodeReceivedNotification n)
{
string key = GetCodeVerifierKey(n.ProtocolMessage.State);
string codeVerifierCookie = n.Options.CookieManager.GetRequestCookie(n.OwinContext, key);
if (codeVerifierCookie != null)
{
var cookieOptions = new CookieOptions
{
SameSite = SameSiteMode.None,
HttpOnly = true,
Secure = n.Request.IsSecure
};
n.Options.CookieManager.DeleteCookie(n.OwinContext, key, cookieOptions);
}
string codeVerifier;
var cookieProperties = n.Options.StateDataFormat.Unprotect(Encoding.UTF8.GetString(Convert.FromBase64String(codeVerifierCookie)));
cookieProperties.Dictionary.TryGetValue("cv", out codeVerifier);
return codeVerifier;
}
显然 codeVerifierCookie 为空。
其余配置如下
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "cookie"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = "mvc.owin",
Authority = "https://localhost:44355",
RedirectUri = "http://localhost:5001/Auth/",
Scope = "openid profile scope1",
SignInAsAuthenticationType = "cookie",
RequireHttpsMetadata = false,
UseTokenLifetime = false,
RedeemCode = true,
SaveTokens = true,
ClientSecret = "secret",
ResponseType = "code",
ResponseMode = "query",
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
{
// set PKCE parameters
var codeVerifier = CryptoRandom.CreateUniqueId(32);
string codeChallenge;
using (var sha256 = SHA256.Create())
{
var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
codeChallenge = Base64Url.Encode(challengeBytes);
}
n.ProtocolMessage.SetParameter("code_challenge", codeChallenge);
n.ProtocolMessage.SetParameter("code_challenge_method", "S256");
// remember code_verifier (adapted from OWIN nonce cookie)
RememberCodeVerifier(n, codeVerifier);
}
return Task.CompletedTask;
},
AuthorizationCodeReceived = n =>
{
// get code_verifier
var codeVerifier = RetrieveCodeVerifier(n);
// attach code_verifier
n.TokenEndpointRequest.SetParameter("code_verifier", codeVerifier);
return Task.CompletedTask;
}
}
});
并且在 IdentityServer4 ConfigureServices 上:
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
var builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
// see https://identityserver4.readthedocs.io/en/latest/topics/resources.html
options.EmitStaticAudienceClaim = true;
})
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddInMemoryClients(Config.Clients)
.AddAspNetIdentity<ApplicationUser>();
最后,在IdentityServer4端Client.cs配置:
new Client
{
ClientId = "mvc.owin",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.Code,
ClientSecrets = {new Secret("secret".Sha256())},
RedirectUris = {"http://localhost:5001/Auth/"},
AllowedScopes = {"openid", "profile", "scope1"},
AllowPlainTextPkce = false,
RequirePkce = true,
RequireConsent = false,
// Token lifetimes
AuthorizationCodeLifetime = 60,
AccessTokenLifetime = 60,
IdentityTokenLifetime = 60
}
AccountController 其余的几乎都是基本的 IdentityServer4.Template,特别是 is4aspid.
- 有人试过同样的方法,知道什么地方失败了吗?
- 有没有办法用 JWT 代替 Cookies 来做到这一点?还有,缺点是什么?
编辑: 显然,此配置适用于 Firefox,我怀疑这是 Chrome 的 Same-Site cookie 策略的问题,因此 null 在 GetRequestCookie 中。问题是,IdentityServer4 在 HTTPS 上是 运行(否则,还有其他),而 MVC 客户端应用程序在 HTTP 上是 运行(注意:两者都在本地主机上)。我曾尝试使用 SameSite 策略 None、Lax、Strict,反之亦然,但均未成功。我不确定还能尝试什么。
最好的, 姆卡纳基斯。
声明 SameSite=None
的 Cookie 也必须标记为安全,这意味着您需要使用 https
阅读更多here