Skip to content

Commit

Permalink
🚑 Allow token revocation using a revoked_tokens.txt file at website…
Browse files Browse the repository at this point in the history
… root
  • Loading branch information
RemiBardon committed Aug 10, 2024
1 parent 220342b commit 3bd8bed
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 31 additions & 1 deletion src/helpers/src/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -141,6 +141,36 @@ fn _update_submodules() -> Result<(), Error> {
}
}

fn read_file_to_set_(file: File) -> io::Result<HashSet<Vec<u8>>> {
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<HashSet<Vec<u8>>, 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…");

Expand Down
2 changes: 1 addition & 1 deletion src/orangutan-server/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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
Expand Down
24 changes: 23 additions & 1 deletion src/orangutan-server/src/routes/auth_routes.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand All @@ -16,6 +17,10 @@ use crate::{
util::{add_cookie, add_padding},
};

lazy_static! {
pub(super) static ref REVOKED_TOKENS: RwLock<HashSet<Vec<u8>>> = RwLock::default();
}

pub(super) fn routes() -> Vec<Route> {
routes![handle_refresh_token]
}
Expand Down Expand Up @@ -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::<HashSet<Vec<u8>>>()
.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("<could not format>".to_string()),
);
return Err(Status::Forbidden);
}

trace!("Checking if refresh token is valid or not");
let authorizer = authorizer!(
r#"
Expand Down
8 changes: 8 additions & 0 deletions src/orangutan-server/src/routes/update_content_routes.rs
Original file line number Diff line number Diff line change
@@ -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<Route> {
Expand All @@ -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)?;

Expand All @@ -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}")]
Expand Down

0 comments on commit 3bd8bed

Please sign in to comment.