From 4d0bb0709b168a24ab6a8dbc86da45d7503596ee Mon Sep 17 00:00:00 2001 From: Owen Jacobson Date: Sat, 28 Sep 2024 01:40:22 -0400 Subject: Wrap credential and credential-holding types to prevent `Debug` leaks. The following values are considered confidential, and should never be logged, even by accident: * `Password`, which is a durable bearer token for a specific Login; * `IdentitySecret`, which is an ephemeral but potentially long-lived bearer token for a specific Login; or * `IdentityToken`, which may hold cookies containing an `IdentitySecret`. These values are now wrapped in types whose `Debug` impls output opaque values, so that they can be included in structs that `#[derive(Debug)]` without requiring any additional care. The wrappers also avoid implementing `Display`, to prevent inadvertent `to_string()`s. We don't bother obfuscating `IdentitySecret`s in memory or in the `.hi` database. There's no point: we'd also need to store the information needed to de-obfuscate them, and they can be freely invalidated and replaced by blanking that table and asking everyone to log in again. Passwords _are_ obfuscated for storage, as they're intended to be durable. --- src/repo/token.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/repo/token.rs') diff --git a/src/repo/token.rs b/src/repo/token.rs index 8276bea..15eef48 100644 --- a/src/repo/token.rs +++ b/src/repo/token.rs @@ -2,7 +2,7 @@ use sqlx::{sqlite::Sqlite, SqliteConnection, Transaction}; use uuid::Uuid; use super::login::{self, Login}; -use crate::clock::DateTime; +use crate::{clock::DateTime, login::extract::IdentitySecret}; pub trait Provider { fn tokens(&mut self) -> Tokens; @@ -23,7 +23,7 @@ impl<'c> Tokens<'c> { &mut self, login: &Login, issued_at: &DateTime, - ) -> Result { + ) -> Result { let secret = Uuid::new_v4().to_string(); let secret = sqlx::query_scalar!( @@ -31,7 +31,7 @@ impl<'c> Tokens<'c> { insert into token (secret, login, issued_at, last_used_at) values ($1, $2, $3, $3) - returning secret as "secret!" + returning secret as "secret!: IdentitySecret" "#, secret, login.id, @@ -44,7 +44,7 @@ impl<'c> Tokens<'c> { } // Revoke a token by its secret. - pub async fn revoke(&mut self, secret: &str) -> Result<(), sqlx::Error> { + pub async fn revoke(&mut self, secret: &IdentitySecret) -> Result<(), sqlx::Error> { sqlx::query!( r#" delete @@ -82,7 +82,7 @@ impl<'c> Tokens<'c> { // timestamp will be set to `used_at`. pub async fn validate( &mut self, - secret: &str, + secret: &IdentitySecret, used_at: &DateTime, ) -> Result { // I would use `update … returning` to do this in one query, but -- cgit v1.2.3