summaryrefslogtreecommitdiff
path: root/src/repo/token.rs
diff options
context:
space:
mode:
authorOwen Jacobson <owen@grimoire.ca>2024-09-28 01:40:22 -0400
committerOwen Jacobson <owen@grimoire.ca>2024-09-28 20:48:40 -0400
commit4d0bb0709b168a24ab6a8dbc86da45d7503596ee (patch)
tree031f2e35f07cef7305809e3a1d310bf304d15460 /src/repo/token.rs
parent72efedf8e96ca6e159ce6146809ee6d3a9e5a0e7 (diff)
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.
Diffstat (limited to 'src/repo/token.rs')
-rw-r--r--src/repo/token.rs10
1 files changed, 5 insertions, 5 deletions
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<String, sqlx::Error> {
+ ) -> Result<IdentitySecret, sqlx::Error> {
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<Login, sqlx::Error> {
// I would use `update … returning` to do this in one query, but