feat(api): add return_session login for cross-origin clients
Return the session token in the login response instead of a cookie, and accept it as a Bearer token without CSRF.
This commit is contained in:
1 parent
193fc3a95c
commit
91c63d0cf2
5 files changed
+90
-20
No files matched your search
@@ -44,24 +44,35 @@ public static class AuthEndpoints
|
||||
return Problems.From(http, error);
|
||||
}
|
||||
|
||||
http.Response.Cookies.Append(
|
||||
PrincipalResolver.SessionCookie,
|
||||
login.SessionToken,
|
||||
new CookieOptions
|
||||
{
|
||||
HttpOnly = true,
|
||||
Secure = options.SecureCookies,
|
||||
SameSite = SameSiteMode.Strict,
|
||||
Path = "/",
|
||||
Expires = DateTimeOffset.FromUnixTimeMilliseconds(login.ExpiresAtMs),
|
||||
});
|
||||
// 跨域的前端(return_session)不用 Cookie:会话令牌放在响应里,之后用 Bearer 带上
|
||||
bool returnSession = request.ReturnSession == true;
|
||||
if (!returnSession)
|
||||
{
|
||||
http.Response.Cookies.Append(
|
||||
PrincipalResolver.SessionCookie,
|
||||
login.SessionToken,
|
||||
new CookieOptions
|
||||
{
|
||||
HttpOnly = true,
|
||||
Secure = options.SecureCookies,
|
||||
SameSite = SameSiteMode.Strict,
|
||||
Path = "/",
|
||||
Expires = DateTimeOffset.FromUnixTimeMilliseconds(login.ExpiresAtMs),
|
||||
});
|
||||
}
|
||||
|
||||
http.Response.Headers.CacheControl = "no-store";
|
||||
return TypedResults.Json(new LoginResponse(login.UserId, login.Username, login.CsrfToken, Mappers.Time(login.ExpiresAtMs)), ApiJsonContext.Default.LoginResponse);
|
||||
return TypedResults.Json(new LoginResponse(login.UserId, login.Username, login.CsrfToken, Mappers.Time(login.ExpiresAtMs), returnSession ? login.SessionToken : null), ApiJsonContext.Default.LoginResponse);
|
||||
}
|
||||
|
||||
private static async Task<IResult> LogoutAsync(HttpContext http, AuthService auth)
|
||||
{
|
||||
if (http.Request.Cookies.TryGetValue(PrincipalResolver.SessionCookie, out string? session))
|
||||
string? bearer = PrincipalResolver.BearerOf(http);
|
||||
if (bearer is not null)
|
||||
{
|
||||
await auth.LogoutAsync(bearer, http.RequestAborted); // 登录时 return_session 拿到的会话令牌;API 令牌不是会话,这里什么也不会发生
|
||||
}
|
||||
else if (http.Request.Cookies.TryGetValue(PrincipalResolver.SessionCookie, out string? session))
|
||||
{
|
||||
await auth.LogoutAsync(session, http.RequestAborted);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user