Merge pull request #3982 from SleeplessOne1917/bearer-token

feat: Replace ad hoc auth header with internet standard bearer token auth header
pull/3988/head^2
SleeplessOne1917 2023-09-26 00:59:55 +00:00 committed by GitHub
commit 9a9ece8fa4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 33 additions and 19 deletions

16
Cargo.lock generated
View File

@ -314,6 +314,21 @@ dependencies = [
"syn 1.0.103", "syn 1.0.103",
] ]
[[package]]
name = "actix-web-httpauth"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d613edf08a42ccc6864c941d30fe14e1b676a77d16f1dbadc1174d065a0a775"
dependencies = [
"actix-utils",
"actix-web",
"base64 0.21.2",
"futures-core",
"futures-util",
"log",
"pin-project-lite",
]
[[package]] [[package]]
name = "actix-web-prom" name = "actix-web-prom"
version = "0.6.0" version = "0.6.0"
@ -2867,6 +2882,7 @@ dependencies = [
"activitypub_federation", "activitypub_federation",
"actix-cors", "actix-cors",
"actix-web", "actix-web",
"actix-web-httpauth",
"actix-web-prom", "actix-web-prom",
"chrono", "chrono",
"clap", "clap",

View File

@ -168,4 +168,5 @@ prometheus = { version = "0.13.3", features = ["process"], optional = true }
actix-web-prom = { version = "0.6.0", optional = true } actix-web-prom = { version = "0.6.0", optional = true }
serial_test = { workspace = true } serial_test = { workspace = true }
clap = { version = "4.3.19", features = ["derive"] } clap = { version = "4.3.19", features = ["derive"] }
actix-web-httpauth = "0.8.1"
lemmy_federate = { version = "0.18.4", path = "crates/federate" } lemmy_federate = { version = "0.18.4", path = "crates/federate" }

View File

@ -229,7 +229,7 @@ test.skip("Remove a comment from admin and community on the same instance", asyn
test("Remove a comment from admin and community on different instance", async () => { test("Remove a comment from admin and community on different instance", async () => {
let alpha_user = await registerUser(alpha); let alpha_user = await registerUser(alpha);
let newAlphaApi = new LemmyHttp(alphaUrl, { let newAlphaApi = new LemmyHttp(alphaUrl, {
headers: { auth: alpha_user.jwt ?? "" }, headers: { Authorization: `Bearer ${alpha_user.jwt ?? ""}` },
}); });
// New alpha user creates a community, post, and comment. // New alpha user creates a community, post, and comment.

View File

@ -252,7 +252,7 @@ test("moderator view", async () => {
// register a new user with their own community on alpha and post to it // register a new user with their own community on alpha and post to it
let registerUserRes = await registerUser(alpha); let registerUserRes = await registerUser(alpha);
let otherUser = new LemmyHttp(alphaUrl, { let otherUser = new LemmyHttp(alphaUrl, {
headers: { auth: registerUserRes.jwt ?? "" }, headers: { Authorization: `Bearer ${registerUserRes.jwt ?? ""}` },
}); });
let otherCommunity = (await createCommunity(otherUser)).community_view; let otherCommunity = (await createCommunity(otherUser)).community_view;

View File

@ -382,7 +382,7 @@ test("Enforce site ban for federated user", async () => {
let alphaUserJwt = await registerUser(alpha); let alphaUserJwt = await registerUser(alpha);
expect(alphaUserJwt).toBeDefined(); expect(alphaUserJwt).toBeDefined();
let alpha_user = new LemmyHttp(alphaUrl, { let alpha_user = new LemmyHttp(alphaUrl, {
headers: { auth: alphaUserJwt.jwt ?? "" }, headers: { Authorization: `Bearer ${alphaUserJwt.jwt ?? ""}` },
}); });
let alphaUserActorId = (await getSite(alpha_user)).my_user?.local_user_view let alphaUserActorId = (await getSite(alpha_user)).my_user?.local_user_view
.person.actor_id; .person.actor_id;

View File

@ -124,11 +124,11 @@ export async function setupLogins() {
resDelta, resDelta,
resEpsilon, resEpsilon,
]); ]);
alpha.setHeaders({ auth: res[0].jwt ?? "" }); alpha.setHeaders({ Authorization: `Bearer ${res[0].jwt ?? ""}` });
beta.setHeaders({ auth: res[1].jwt ?? "" }); beta.setHeaders({ Authorization: `Bearer ${res[1].jwt ?? ""}` });
gamma.setHeaders({ auth: res[2].jwt ?? "" }); gamma.setHeaders({ Authorization: `Bearer ${res[2].jwt ?? ""}` });
delta.setHeaders({ auth: res[3].jwt ?? "" }); delta.setHeaders({ Authorization: `Bearer ${res[3].jwt ?? ""}` });
epsilon.setHeaders({ auth: res[4].jwt ?? "" }); epsilon.setHeaders({ Authorization: `Bearer ${res[4].jwt ?? ""}` });
// Registration applications are now enabled by default, need to disable them // Registration applications are now enabled by default, need to disable them
let editSiteForm: EditSite = { let editSiteForm: EditSite = {

View File

@ -41,7 +41,7 @@ test("Create user", async () => {
let userRes = await registerUser(alpha); let userRes = await registerUser(alpha);
expect(userRes.jwt).toBeDefined(); expect(userRes.jwt).toBeDefined();
let user = new LemmyHttp(alphaUrl, { let user = new LemmyHttp(alphaUrl, {
headers: { auth: userRes.jwt ?? "" }, headers: { Authorization: `Bearer ${userRes.jwt ?? ""}` },
}); });
let site = await getSite(user); let site = await getSite(user);
@ -63,7 +63,7 @@ test("Delete user", async () => {
let userRes = await registerUser(alpha); let userRes = await registerUser(alpha);
expect(userRes.jwt).toBeDefined(); expect(userRes.jwt).toBeDefined();
let user = new LemmyHttp(alphaUrl, { let user = new LemmyHttp(alphaUrl, {
headers: { auth: userRes.jwt ?? "" }, headers: { Authorization: `Bearer ${userRes.jwt ?? ""}` },
}); });
// make a local post and comment // make a local post and comment
@ -109,7 +109,7 @@ test("Delete user", async () => {
test("Requests with invalid auth should be treated as unauthenticated", async () => { test("Requests with invalid auth should be treated as unauthenticated", async () => {
let invalid_auth = new LemmyHttp(alphaUrl, { let invalid_auth = new LemmyHttp(alphaUrl, {
headers: { auth: "" }, headers: { Authorization: "Bearer foobar" },
}); });
let site = await getSite(invalid_auth); let site = await getSite(invalid_auth);
expect(site.my_user).toBeUndefined(); expect(site.my_user).toBeUndefined();

@ -1 +1 @@
Subproject commit 839f1097d07ba9d730e31f58c892de491442e490 Subproject commit de9de2c53bee034d3824ecaa9a2104f8f341332e

View File

@ -2,10 +2,11 @@ use actix_web::{
body::MessageBody, body::MessageBody,
cookie::SameSite, cookie::SameSite,
dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform}, dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform},
http::header::CACHE_CONTROL, http::header::{Header, CACHE_CONTROL},
Error, Error,
HttpMessage, HttpMessage,
}; };
use actix_web_httpauth::headers::authorization::{Authorization, Bearer};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use core::future::Ready; use core::future::Ready;
use futures_util::future::LocalBoxFuture; use futures_util::future::LocalBoxFuture;
@ -76,13 +77,9 @@ where
let context = self.context.clone(); let context = self.context.clone();
Box::pin(async move { Box::pin(async move {
// Try reading jwt from auth header let auth_header = Authorization::<Bearer>::parse(&req).ok();
let auth_header = req
.headers()
.get(AUTH_COOKIE_NAME)
.and_then(|h| h.to_str().ok());
let jwt = if let Some(a) = auth_header { let jwt = if let Some(a) = auth_header {
Some(a.to_string()) Some(a.as_ref().token().to_string())
} }
// If that fails, try auth cookie. Dont use the `jwt` cookie from lemmy-ui because // If that fails, try auth cookie. Dont use the `jwt` cookie from lemmy-ui because
// its not http-only. // its not http-only.