From 3bd8bedc4826d913665af643f292d987b755239c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bardon?= Date: Sat, 10 Aug 2024 19:56:25 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=91=20Allow=20token=20revocation=20usi?= =?UTF-8?q?ng=20a=20`revoked=5Ftokens.txt`=20file=20at=20website=20root?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Cargo.lock | 2 +- src/helpers/src/generate.rs | 32 ++++++++++++++++++- src/orangutan-server/Cargo.toml | 2 +- .../src/routes/auth_routes.rs | 24 +++++++++++++- .../src/routes/update_content_routes.rs | 8 +++++ 5 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 00a7284..e8fa977 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1145,7 +1145,7 @@ dependencies = [ [[package]] name = "orangutan-server" -version = "0.4.10" +version = "0.4.11" dependencies = [ "base64 0.22.1", "biscuit-auth", diff --git a/src/helpers/src/generate.rs b/src/helpers/src/generate.rs index 1f68a1b..ed0348e 100644 --- a/src/helpers/src/generate.rs +++ b/src/helpers/src/generate.rs @@ -2,7 +2,7 @@ use std::{ collections::HashSet, env, fs::{self, File}, - io::{self, Write}, + io::{self, BufRead as _, BufReader, Write}, path::PathBuf, process::{Command, Output, Stdio}, sync::{ @@ -141,6 +141,36 @@ fn _update_submodules() -> Result<(), Error> { } } +fn read_file_to_set_(file: File) -> io::Result>> { + let reader = BufReader::new(file); + + let mut set = HashSet::new(); + + for line in reader.lines() { + let line = line?; + if !line.is_empty() { + set.insert(line.into_bytes()); + } + } + + Ok(set) +} + +// NOTE: This is just a hotfix. I had to quickly revoke a token. I'll improve this one day. +pub fn read_revoked_tokens() -> Result>, Error> { + let revoked_tokens_file_path = WEBSITE_ROOT.join("revoked_tokens.txt"); + let Ok(revoked_tokens_file) = File::open(&revoked_tokens_file_path) else { + info!( + "Revoked tokens file not found at <{}>. Considering no revoked token.", + revoked_tokens_file_path.display(), + ); + return Ok(HashSet::new()); + }; + let revoked_tokens = read_file_to_set_(revoked_tokens_file)?; + info!("Found {} revoked token(s).", revoked_tokens.len()); + Ok(revoked_tokens) +} + fn _copy_hugo_config() -> Result<(), Error> { debug!("Copying hugo config…"); diff --git a/src/orangutan-server/Cargo.toml b/src/orangutan-server/Cargo.toml index 99abd4c..9a8a0e0 100644 --- a/src/orangutan-server/Cargo.toml +++ b/src/orangutan-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "orangutan-server" -version = "0.4.10" +version = "0.4.11" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/orangutan-server/src/routes/auth_routes.rs b/src/orangutan-server/src/routes/auth_routes.rs index 7483cbf..248582d 100644 --- a/src/orangutan-server/src/routes/auth_routes.rs +++ b/src/orangutan-server/src/routes/auth_routes.rs @@ -1,6 +1,7 @@ -use std::time::SystemTime; +use std::{collections::HashSet, sync::RwLock, time::SystemTime}; use biscuit_auth::{macros::authorizer, Biscuit}; +use lazy_static::lazy_static; use rocket::{ get, http::{uri::Origin, CookieJar, Status}, @@ -16,6 +17,10 @@ use crate::{ util::{add_cookie, add_padding}, }; +lazy_static! { + pub(super) static ref REVOKED_TOKENS: RwLock>> = RwLock::default(); +} + pub(super) fn routes() -> Vec { routes![handle_refresh_token] } @@ -44,6 +49,23 @@ fn handle_refresh_token( }, }; + // NOTE: This is just a hotfix. I had to quickly revoke a token. I'll improve this one day. + trace!("Checking if refresh token is revoked"); + let revoked_id = refresh_biscuit + .revocation_identifiers() + .into_iter() + .collect::>>() + .intersection(&REVOKED_TOKENS.read().unwrap()) + .next() + .cloned(); + if let Some(revoked_id) = revoked_id { + debug!( + "Refresh token has been revoked ({})", + String::from_utf8(revoked_id).unwrap_or("".to_string()), + ); + return Err(Status::Forbidden); + } + trace!("Checking if refresh token is valid or not"); let authorizer = authorizer!( r#" diff --git a/src/orangutan-server/src/routes/update_content_routes.rs b/src/orangutan-server/src/routes/update_content_routes.rs index 5643f80..276485e 100644 --- a/src/orangutan-server/src/routes/update_content_routes.rs +++ b/src/orangutan-server/src/routes/update_content_routes.rs @@ -1,6 +1,7 @@ use orangutan_helpers::generate::{self, *}; use rocket::{post, response::status::BadRequest, routes, Route}; +use super::auth_routes::REVOKED_TOKENS; use crate::error; pub(super) fn routes() -> Vec { @@ -13,6 +14,11 @@ fn update_content_github() -> Result<(), crate::Error> { // Update repository pull_repository().map_err(Error::CannotPullOutdatedRepository)?; + // Read revoked tokens list + // FIXME: This cannot be reverted + *REVOKED_TOKENS.write().unwrap() = + read_revoked_tokens().map_err(Error::CannotReadRevokedTokens)?; + // Remove outdated websites let state = trash_outdated_websites().map_err(Error::CannotTrashOutdatedWebsites)?; @@ -39,6 +45,8 @@ pub enum Error { WebsiteGenerationError(generate::Error), #[error("Cannot pull outdated repository: {0}")] CannotPullOutdatedRepository(generate::Error), + #[error("Cannot read revoked tokens: {0}")] + CannotReadRevokedTokens(generate::Error), #[error("Cannot trash outdated websites: {0}")] CannotTrashOutdatedWebsites(generate::Error), #[error("Cannot recover trash: {0}")]