我有一个由 Vue.js 客户端应用程序和 ASP.NET Core 9 后端组成的系统。该后端使用
app.MapFallbackToFile("/index.html").RequireAuthorization();
仅向授权用户提供客户端应用程序。必须使用 LTI 身份验证从第三个应用程序调用我。他们仅在第一次向我发送 JWT 令牌,我可以使用该令牌进行身份验证:
// In building I use
.AddJwtBearer(async opt =>
{
opt.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = jwtSection.Issuer,
ValidateAudience = true,
ValidAudience = jwtSection.Audience,
ValidateLifetime = true,
IssuerSigningKeys = keys
};
opt.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
if (context.Request.ContentType == "application/x-www-form-urlencoded")
{
if (context.Request.Form.Any(f => f.Key == jwtSection.TokenField))
{
var token = context.Request.Form[jwtSection.TokenField];
// Set jwt cookie
context.Response.Cookies.Append("jwt", token, new CookieOptions
{
HttpOnly = true,
Secure = true,
SameSite = SameSiteMode.None
});
context.Token = token;
}
}
if (context.Request.Cookies.TryGetValue("token", out var jwt))
{
context.Token = jwt;
}
return Task.CompletedTask;
}
};
});
// In startup I use this
app.UseCookiePolicy(new CookiePolicyOptions
{
HttpOnly = Microsoft.AspNetCore.CookiePolicy.HttpOnlyPolicy.Always,
Secure = CookieSecurePolicy.SameAsRequest,
MinimumSameSitePolicy = SameSiteMode.None,
});
app.MapGet("vue/api/me", (HttpContext context) =>
{
return new { name = context.User.Claims.FirstOrDefault(f => f.Type == "name") };
}).RequireAuthorization();
app.MapFallbackToFile("/index.html").RequireAuthorization();
但是当我尝试在响应中设置 cookie 时,我在 iframe 内的客户端应用程序中看不到它以及来自我的 asp.net core 后端的任何其他 cookie
https://saltire.lti.app/platform
:
<iframe name="connectframe" id="id_toolframe" src="about:blank"
width="100%" scrolling="auto" frameborder="1" height="693px"></iframe>
如果我在新选项卡而不是 iframe 中加载应用程序,我会看到来自后端的许多 cookie,但看不到我的 JWT cookie。
/me
呼叫也未获得授权。
知道如何在客户端应用程序中存储 JWT 令牌并将其用于将来的身份验证吗?没有必要使用响应 cookie,我需要验证我的 Vue.js 应用程序,无论需要什么......
在 LTI 流程中,他们在此操作中调用我的后端:
[HttpPost("launch")]
[Authorize]
[Consumes("application/x-www-form-urlencoded")]
public async Task<IActionResult> PostLaunch([FromForm] JwtPayload request)
{
await Task.CompletedTask;
if (HttpContext.User.Identity?.IsAuthenticated == true)
{
return this.RedirectPreserveMethod("/");
}
}
这是授权的最后一个操作(这是我从 lti 接收 JWT 令牌的地方)。这条指令
this.RedirectPreserveMethod("/");
让我将 Vue.js 应用程序返回给调用者。
编辑1:我在
saltire.lti.app
域中开始我的旅程,我使用 ngrok 为我的本地计算机建立隧道,因此公共 url 为 https://15e1-93-41-196-8.ngrok-free.app
,ngrok 将流量转发到我的 dotnet 后端,在 https://localhost:7093
提供服务,但我的 vue. Node.js 应用程序在 https://localhost:64928
提供服务。在浏览器控制台中,我看到三个不同的域,控制台回复我此错误:Cookie “jwt” has been rejected for invalid domain
。我收到此标题:jwt=...; domain=https://15e1-93-41-196-8.ngrok-free.app; path=/; secure; samesite=none; httponly
。
我用这个代码创建了cookie:
HttpContext.Response.Cookies.Append("jwt", written, new CookieOptions
{
HttpOnly = true,
Secure = true,
SameSite = SameSiteMode.None,
Domain = "https://15e1-93-41-196-8.ngrok-free.app"
});
即使使用
localhost
作为域也不起作用,浏览器控制台中出现错误。
保存 jwt 令牌的 cookie 位于 localhost 域中,与 saltire.lti.app 域完全不同
cookie 可以在同一域但不同子域(例如
app1.myapp.com
和 app1.myapp.com
)的应用程序之间共享,配置为:options.Cookie.Domain = ".myapp.com";
您必须在本地主机上运行其他应用程序,或者将您的.net后端应用程序与其他应用程序托管在同一域中,并按上述配置cookie来解决问题