From 55343df9c1f54113b5f2ed04cecfadf0670887c7 Mon Sep 17 00:00:00 2001 From: pennae Date: Sun, 17 Jul 2022 11:43:52 +0200 Subject: add dedicated types for all the tokens using SecretBytes for all of them isn't that great. --- src/api/auth/account.rs | 41 +++++++++++++++++++---------------------- src/api/auth/oauth.rs | 16 ++++++++-------- src/api/auth/password.rs | 39 +++++++++++++++++++++------------------ 3 files changed, 48 insertions(+), 48 deletions(-) (limited to 'src/api/auth') diff --git a/src/api/auth/account.rs b/src/api/auth/account.rs index 0f12d49..c0c2099 100644 --- a/src/api/auth/account.rs +++ b/src/api/auth/account.rs @@ -11,6 +11,7 @@ use serde::{Deserialize, Serialize}; use validator::Validate; use crate::api::{Empty, EMPTY}; +use crate::crypto::{KeyFetchToken, SessionToken}; use crate::db::{Db, DbConn}; use crate::mailer::Mailer; use crate::push::PushClient; @@ -21,7 +22,7 @@ use crate::{ api::{auth, serialize_dt}, auth::{AuthSource, Authenticated}, crypto::{AuthPW, KeyBundle, KeyFetchReq, SecretBytes, SessionCredentials}, - types::{HawkKey, KeyFetchID, OauthToken, SecretKey, SessionID, User, UserID, VerifyHash}, + types::{HawkKey, KeyFetchID, OauthToken, SecretKey, User, UserID, VerifyHash}, }; // TODO better error handling @@ -52,9 +53,9 @@ pub(crate) struct Create { #[serde(deny_unknown_fields)] pub(crate) struct CreateResp { uid: UserID, - sessionToken: SecretBytes<32>, + sessionToken: SessionToken, #[serde(skip_serializing_if = "Option::is_none")] - keyFetchToken: Option>, + keyFetchToken: Option, #[serde(serialize_with = "serialize_dt")] authAt: DateTime, // MISSING verificationMethod @@ -94,17 +95,16 @@ pub(crate) async fn create( let auth_salt = SaltString::generate(rand::rngs::OsRng); let stretched = data.authPW.stretch(auth_salt.as_salt())?; let verify_hash = stretched.verify_hash(); - let session_token = SecretBytes::generate(); - let session = SessionCredentials::derive(&session_token); + let session_token = SessionToken::generate(); + let session = SessionCredentials::derive_from(&session_token); let key_fetch_token = if keys { - let key_fetch_token = SecretBytes::generate(); - let req = KeyFetchReq::from_token(&key_fetch_token); + let key_fetch_token = KeyFetchToken::generate(); + let req = KeyFetchReq::derive_from(&key_fetch_token); let wrapped = req.derive_resp().wrap_keys(&KeyBundle { ka: ka.clone(), wrap_kb: stretched.decrypt_wwkb(&wrapwrap_kb), }); - db.add_key_fetch(KeyFetchID(req.token_id.0), &HawkKey(req.req_hmac_key.0), &wrapped) - .await?; + db.add_key_fetch(req.token_id, &HawkKey(req.req_hmac_key.0), &wrapped).await?; Some(key_fetch_token) } else { None @@ -120,12 +120,11 @@ pub(crate) async fn create( verified: false, }) .await?; - let session_id = SessionID(session.token_id.0); let auth_at = db - .add_session(session_id.clone(), &uid, HawkKey(session.req_hmac_key.0), false, None) + .add_session(session.token_id.clone(), &uid, HawkKey(session.req_hmac_key.0), false, None) .await?; let verify_code = hex::encode(&SecretBytes::<16>::generate().0); - db.add_verify_code(&uid, &session_id, &verify_code).await?; + db.add_verify_code(&uid, &session.token_id, &verify_code).await?; // NOTE we send the email in this context rather than a spawn to signal // send errors to the client. mailer.send_account_verify(&uid, &data.email, &verify_code).await.map_err(|e| { @@ -161,9 +160,9 @@ pub(crate) struct Login { #[serde(deny_unknown_fields)] pub(crate) struct LoginResp { uid: UserID, - sessionToken: SecretBytes<32>, + sessionToken: SessionToken, #[serde(skip_serializing_if = "Option::is_none")] - keyFetchToken: Option>, + keyFetchToken: Option, // MISSING verificationMethod // MISSING verificationReason // NOTE this is the *account* verified status, not the session status. @@ -200,27 +199,25 @@ pub(crate) async fn login( return Err(auth::Error::IncorrectPassword); } - let session_token = SecretBytes::generate(); - let session = SessionCredentials::derive(&session_token); + let session_token = SessionToken::generate(); + let session = SessionCredentials::derive_from(&session_token); let key_fetch_token = if keys { - let key_fetch_token = SecretBytes::generate(); - let req = KeyFetchReq::from_token(&key_fetch_token); + let key_fetch_token = KeyFetchToken::generate(); + let req = KeyFetchReq::derive_from(&key_fetch_token); let wrapped = req.derive_resp().wrap_keys(&KeyBundle { ka: SecretBytes(user.ka.0), wrap_kb: stretched.decrypt_wwkb(&SecretBytes(user.wrapwrap_kb.0)), }); - db.add_key_fetch(KeyFetchID(req.token_id.0), &HawkKey(req.req_hmac_key.0), &wrapped) - .await?; + db.add_key_fetch(req.token_id, &HawkKey(req.req_hmac_key.0), &wrapped).await?; Some(key_fetch_token) } else { None }; - let session_id = SessionID(session.token_id.0); let verify_code = format!("{:06}", thread_rng().gen_range(0..=999999)); let auth_at = db .add_session( - session_id.clone(), + session.token_id.clone(), &uid, HawkKey(session.req_hmac_key.0), false, diff --git a/src/api/auth/oauth.rs b/src/api/auth/oauth.rs index 6d2f700..c159352 100644 --- a/src/api/auth/oauth.rs +++ b/src/api/auth/oauth.rs @@ -9,12 +9,13 @@ use subtle::ConstantTimeEq; use crate::api::auth::WithVerifiedFxaLogin; use crate::api::{Empty, EMPTY}; +use crate::crypto::SessionToken; use crate::db::DbConn; use crate::types::oauth::{Scope, ScopeSet}; use crate::{ api::{auth, serialize_dt}, auth::Authenticated, - crypto::{SecretBytes, SessionCredentials}, + crypto::SessionCredentials, types::{ HawkKey, OauthAccessToken, OauthAccessType, OauthAuthorization, OauthAuthorizationID, OauthRefreshToken, OauthToken, OauthTokenID, SessionID, UserID, @@ -278,7 +279,7 @@ pub(crate) struct TokenResp { refresh_token: Option, // MISSING id_token #[serde(skip_serializing_if = "Option::is_none")] - session_token: Option, + session_token: Option, scope: ScopeSet, token_type: TokenType, expires_in: u32, @@ -391,18 +392,17 @@ async fn token_impl( let (refresh_token, session_token) = if access_type == Some(OauthAccessType::Offline) { let (session_token, session_id) = if scope.implies(&SESSION_SCOPE) { - let session_token = SecretBytes::generate(); - let session = SessionCredentials::derive(&session_token); - let session_id = SessionID(session.token_id.0); + let session_token = SessionToken::generate(); + let session = SessionCredentials::derive_from(&session_token); db.add_session( - session_id.clone(), + session.token_id.clone(), &user_id, HawkKey(session.req_hmac_key.0), true, None, ) .await?; - (Some(session_token.0), Some(SessionID(session.token_id.0))) + (Some(session_token), Some(session.token_id)) } else { (None, None) }; @@ -426,7 +426,7 @@ async fn token_impl( Ok(Json(TokenResp { access_token, refresh_token, - session_token: session_token.map(hex::encode), + session_token, scope: scope.remove(&SESSION_SCOPE), token_type: TokenType::Bearer, expires_in: ttl, diff --git a/src/api/auth/password.rs b/src/api/auth/password.rs index 56ad2a2..ae5bd6d 100644 --- a/src/api/auth/password.rs +++ b/src/api/auth/password.rs @@ -9,11 +9,14 @@ use validator::Validate; use crate::{ api::auth, auth::{AuthSource, Authenticated}, - crypto::{AccountResetReq, AuthPW, KeyBundle, KeyFetchReq, PasswordChangeReq, SecretBytes}, + crypto::{ + AccountResetReq, AccountResetToken, AuthPW, KeyBundle, KeyFetchReq, KeyFetchToken, + PasswordChangeReq, PasswordChangeToken, SecretBytes, + }, db::{Db, DbConn}, mailer::Mailer, types::{ - AccountResetID, HawkKey, KeyFetchID, OauthToken, PasswordChangeID, SecretKey, UserID, + HawkKey, OauthToken, PasswordChangeID, SecretKey, UserID, VerifyHash, }, }; @@ -34,8 +37,8 @@ pub(crate) struct ChangeStartReq { #[derive(Debug, Serialize)] #[allow(non_snake_case)] pub(crate) struct ChangeStartResp { - keyFetchToken: SecretBytes<32>, - passwordChangeToken: SecretBytes<32>, + keyFetchToken: KeyFetchToken, + passwordChangeToken: PasswordChangeToken, } #[post("/password/change/start", data = "")] @@ -59,19 +62,19 @@ pub(crate) async fn change_start( return Err(auth::Error::IncorrectPassword); } - let change_token = SecretBytes::generate(); - let change_req = PasswordChangeReq::from_change_token(&change_token); - let key_fetch_token = SecretBytes::generate(); - let key_req = KeyFetchReq::from_token(&key_fetch_token); + let change_token = PasswordChangeToken::generate(); + let change_req = PasswordChangeReq::derive_from_change_token(&change_token); + let key_fetch_token = KeyFetchToken::generate(); + let key_req = KeyFetchReq::derive_from(&key_fetch_token); let wrapped = key_req.derive_resp().wrap_keys(&KeyBundle { ka: SecretBytes(user.ka.0), wrap_kb: stretched.decrypt_wwkb(&SecretBytes(user.wrapwrap_kb.0)), }); - db.add_key_fetch(KeyFetchID(key_req.token_id.0), &HawkKey(key_req.req_hmac_key.0), &wrapped) + db.add_key_fetch(key_req.token_id, &HawkKey(key_req.req_hmac_key.0), &wrapped) .await?; db.add_password_change( &uid, - &PasswordChangeID(change_req.token_id.0), + &change_req.token_id, &HawkKey(change_req.req_hmac_key.0), None, ) @@ -183,7 +186,7 @@ pub(crate) struct ForgotStartReq { #[derive(Debug, Serialize)] #[allow(non_snake_case)] pub(crate) struct ForgotStartResp { - passwordForgotToken: SecretBytes<32>, + passwordForgotToken: PasswordChangeToken, ttl: u32, codeLength: u32, tries: u32, @@ -207,11 +210,11 @@ pub(crate) async fn forgot_start( } let forgot_code = hex::encode(SecretBytes::<16>::generate().0); - let forgot_token = SecretBytes::generate(); - let forgot_req = PasswordChangeReq::from_forgot_token(&forgot_token); + let forgot_token = PasswordChangeToken::generate(); + let forgot_req = PasswordChangeReq::derive_from_forgot_token(&forgot_token); db.add_password_change( &uid, - &PasswordChangeID(forgot_req.token_id.0), + &forgot_req.token_id, &HawkKey(forgot_req.req_hmac_key.0), Some(&forgot_code), ) @@ -238,7 +241,7 @@ pub(crate) struct ForgotFinishReq { #[derive(Debug, Serialize)] #[allow(non_snake_case)] pub(crate) struct ForgotFinishResp { - accountResetToken: SecretBytes<32>, + accountResetToken: AccountResetToken, } #[post("/password/forgot/verify_code", data = "")] @@ -250,11 +253,11 @@ pub(crate) async fn forgot_finish( return Err(auth::Error::InvalidVerificationCode); } - let reset_token = SecretBytes::generate(); - let reset_req = AccountResetReq::from_token(&reset_token); + let reset_token = AccountResetToken::generate(); + let reset_req = AccountResetReq::derive_from(&reset_token); db.add_account_reset( &data.context.0, - &AccountResetID(reset_req.token_id.0), + &reset_req.token_id, &HawkKey(reset_req.req_hmac_key.0), ) .await?; -- cgit v1.2.3