summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpennae <github@quasiparticle.net>2022-07-17 13:21:16 +0200
committerpennae <github@quasiparticle.net>2022-07-17 17:25:48 +0200
commit5d7f509f1a98c2d45870e3877b4d7bfa756d2d2a (patch)
tree10da9b0614c5f1f98d4edc82e96a798e25971bc0
parent55343df9c1f54113b5f2ed04cecfadf0670887c7 (diff)
downloadminor-skulk-5d7f509f1a98c2d45870e3877b4d7bfa756d2d2a.tar.gz
minor-skulk-5d7f509f1a98c2d45870e3877b4d7bfa756d2d2a.tar.xz
minor-skulk-5d7f509f1a98c2d45870e3877b4d7bfa756d2d2a.zip
use HawkKey everywhere hawk keys are handled
the db already does this, crypto did not.
-rw-r--r--src/api/auth/account.rs26
-rw-r--r--src/api/auth/mod.rs25
-rw-r--r--src/api/auth/oauth.rs12
-rw-r--r--src/api/auth/password.rs35
-rw-r--r--src/auth.rs7
-rw-r--r--src/crypto.rs24
6 files changed, 44 insertions, 85 deletions
diff --git a/src/api/auth/account.rs b/src/api/auth/account.rs
index c0c2099..bff2a66 100644
--- a/src/api/auth/account.rs
+++ b/src/api/auth/account.rs
@@ -15,14 +15,14 @@ use crate::crypto::{KeyFetchToken, SessionToken};
use crate::db::{Db, DbConn};
use crate::mailer::Mailer;
use crate::push::PushClient;
-use crate::types::AccountResetID;
+use crate::types::{AccountResetID, HawkKey};
use crate::utils::DeferAction;
use crate::Config;
use crate::{
api::{auth, serialize_dt},
auth::{AuthSource, Authenticated},
crypto::{AuthPW, KeyBundle, KeyFetchReq, SecretBytes, SessionCredentials},
- types::{HawkKey, KeyFetchID, OauthToken, SecretKey, User, UserID, VerifyHash},
+ types::{KeyFetchID, OauthToken, SecretKey, User, UserID, VerifyHash},
};
// TODO better error handling
@@ -104,7 +104,7 @@ pub(crate) async fn create(
ka: ka.clone(),
wrap_kb: stretched.decrypt_wwkb(&wrapwrap_kb),
});
- db.add_key_fetch(req.token_id, &HawkKey(req.req_hmac_key.0), &wrapped).await?;
+ db.add_key_fetch(req.token_id, &req.req_hmac_key, &wrapped).await?;
Some(key_fetch_token)
} else {
None
@@ -120,9 +120,8 @@ pub(crate) async fn create(
verified: false,
})
.await?;
- let auth_at = db
- .add_session(session.token_id.clone(), &uid, HawkKey(session.req_hmac_key.0), false, None)
- .await?;
+ let auth_at =
+ db.add_session(session.token_id.clone(), &uid, session.req_hmac_key, false, None).await?;
let verify_code = hex::encode(&SecretBytes::<16>::generate().0);
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
@@ -208,7 +207,7 @@ pub(crate) async fn login(
ka: SecretBytes(user.ka.0),
wrap_kb: stretched.decrypt_wwkb(&SecretBytes(user.wrapwrap_kb.0)),
});
- db.add_key_fetch(req.token_id, &HawkKey(req.req_hmac_key.0), &wrapped).await?;
+ db.add_key_fetch(req.token_id, &req.req_hmac_key, &wrapped).await?;
Some(key_fetch_token)
} else {
None
@@ -219,7 +218,7 @@ pub(crate) async fn login(
.add_session(
session.token_id.clone(),
&uid,
- HawkKey(session.req_hmac_key.0),
+ session.req_hmac_key,
false,
Some(&verify_code),
)
@@ -308,10 +307,10 @@ pub(crate) struct WithKeyFetch;
impl AuthSource for WithKeyFetch {
type ID = KeyFetchID;
type Context = Vec<u8>;
- async fn hawk(r: &Request<'_>, id: &KeyFetchID) -> Result<(SecretBytes<32>, Self::Context)> {
+ async fn hawk(r: &Request<'_>, id: &KeyFetchID) -> Result<(HawkKey, Self::Context)> {
let db = Authenticated::<(), Self>::get_conn(r).await?;
db.always_commit().await?;
- Ok(db.finish_key_fetch(id).await.map(|(h, ks)| (SecretBytes(h.0), ks))?)
+ Ok(db.finish_key_fetch(id).await?)
}
async fn bearer_token(_: &Request<'_>, _: &OauthToken) -> Result<(KeyFetchID, Self::Context)> {
// key fetch tokens are only valid in hawk requests
@@ -335,17 +334,14 @@ pub(crate) struct WithResetToken;
impl AuthSource for WithResetToken {
type ID = AccountResetID;
type Context = UserID;
- async fn hawk(
- r: &Request<'_>,
- id: &AccountResetID,
- ) -> Result<(SecretBytes<32>, Self::Context)> {
+ async fn hawk(r: &Request<'_>, id: &AccountResetID) -> Result<(HawkKey, Self::Context)> {
// unlike key fetch we'll use a separate transaction here since the body of the
// handler can fail.
let pool = <&Db as FromRequest>::from_request(r)
.await
.success_or_else(|| anyhow!("could not open db connection"))?;
let db = pool.begin().await?;
- let result = db.finish_account_reset(id).await.map(|(h, ctx)| (SecretBytes(h.0), ctx))?;
+ let result = db.finish_account_reset(id).await?;
db.commit().await?;
Ok(result)
}
diff --git a/src/api/auth/mod.rs b/src/api/auth/mod.rs
index d50dcc2..a2a94e0 100644
--- a/src/api/auth/mod.rs
+++ b/src/api/auth/mod.rs
@@ -8,8 +8,7 @@ use serde_json::json;
use crate::{
auth::Authenticated,
- crypto::SecretBytes,
- types::{OauthToken, SessionID, UserSession},
+ types::{HawkKey, OauthToken, SessionID, UserSession},
};
pub(crate) mod account;
@@ -140,13 +139,10 @@ pub(crate) struct WithFxaLogin;
impl crate::auth::AuthSource for WithFxaLogin {
type ID = SessionID;
type Context = UserSession;
- async fn hawk(
- r: &Request<'_>,
- id: &SessionID,
- ) -> anyhow::Result<(SecretBytes<32>, Self::Context)> {
+ async fn hawk(r: &Request<'_>, id: &SessionID) -> anyhow::Result<(HawkKey, Self::Context)> {
let db = Authenticated::<(), Self>::get_conn(r).await?;
let k = db.use_session(id).await?;
- Ok((SecretBytes(k.req_hmac_key.0), k))
+ Ok((k.req_hmac_key.clone(), k))
}
async fn bearer_token(
_: &Request<'_>,
@@ -163,10 +159,7 @@ pub(crate) struct WithVerifiedFxaLogin;
impl crate::auth::AuthSource for WithVerifiedFxaLogin {
type ID = SessionID;
type Context = UserSession;
- async fn hawk(
- r: &Request<'_>,
- id: &SessionID,
- ) -> anyhow::Result<(SecretBytes<32>, Self::Context)> {
+ async fn hawk(r: &Request<'_>, id: &SessionID) -> anyhow::Result<(HawkKey, Self::Context)> {
let res = WithFxaLogin::hawk(r, id).await?;
match res.1.verified {
true => Ok(res),
@@ -191,10 +184,7 @@ pub(crate) struct WithSession;
impl crate::auth::AuthSource for WithSession {
type ID = SessionID;
type Context = UserSession;
- async fn hawk(
- r: &Request<'_>,
- id: &SessionID,
- ) -> anyhow::Result<(SecretBytes<32>, Self::Context)> {
+ async fn hawk(r: &Request<'_>, id: &SessionID) -> anyhow::Result<(HawkKey, Self::Context)> {
WithFxaLogin::hawk(r, id).await
}
async fn bearer_token(
@@ -213,10 +203,7 @@ pub(crate) struct WithVerifiedSession;
impl crate::auth::AuthSource for WithVerifiedSession {
type ID = SessionID;
type Context = UserSession;
- async fn hawk(
- r: &Request<'_>,
- id: &SessionID,
- ) -> anyhow::Result<(SecretBytes<32>, Self::Context)> {
+ async fn hawk(r: &Request<'_>, id: &SessionID) -> anyhow::Result<(HawkKey, Self::Context)> {
WithVerifiedFxaLogin::hawk(r, id).await
}
async fn bearer_token(
diff --git a/src/api/auth/oauth.rs b/src/api/auth/oauth.rs
index c159352..28d9fb2 100644
--- a/src/api/auth/oauth.rs
+++ b/src/api/auth/oauth.rs
@@ -17,7 +17,7 @@ use crate::{
auth::Authenticated,
crypto::SessionCredentials,
types::{
- HawkKey, OauthAccessToken, OauthAccessType, OauthAuthorization, OauthAuthorizationID,
+ OauthAccessToken, OauthAccessType, OauthAuthorization, OauthAuthorizationID,
OauthRefreshToken, OauthToken, OauthTokenID, SessionID, UserID,
},
};
@@ -394,14 +394,8 @@ async fn token_impl(
let (session_token, session_id) = if scope.implies(&SESSION_SCOPE) {
let session_token = SessionToken::generate();
let session = SessionCredentials::derive_from(&session_token);
- db.add_session(
- session.token_id.clone(),
- &user_id,
- HawkKey(session.req_hmac_key.0),
- true,
- None,
- )
- .await?;
+ db.add_session(session.token_id.clone(), &user_id, session.req_hmac_key, true, None)
+ .await?;
(Some(session_token), Some(session.token_id))
} else {
(None, None)
diff --git a/src/api/auth/password.rs b/src/api/auth/password.rs
index ae5bd6d..e389261 100644
--- a/src/api/auth/password.rs
+++ b/src/api/auth/password.rs
@@ -15,10 +15,7 @@ use crate::{
},
db::{Db, DbConn},
mailer::Mailer,
- types::{
- HawkKey, OauthToken, PasswordChangeID, SecretKey, UserID,
- VerifyHash,
- },
+ types::{HawkKey, OauthToken, PasswordChangeID, SecretKey, UserID, VerifyHash},
};
// MISSING get /password/forgot/status
@@ -70,15 +67,8 @@ pub(crate) async fn change_start(
ka: SecretBytes(user.ka.0),
wrap_kb: stretched.decrypt_wwkb(&SecretBytes(user.wrapwrap_kb.0)),
});
- db.add_key_fetch(key_req.token_id, &HawkKey(key_req.req_hmac_key.0), &wrapped)
- .await?;
- db.add_password_change(
- &uid,
- &change_req.token_id,
- &HawkKey(change_req.req_hmac_key.0),
- None,
- )
- .await?;
+ db.add_key_fetch(key_req.token_id, &key_req.req_hmac_key, &wrapped).await?;
+ db.add_password_change(&uid, &change_req.token_id, &change_req.req_hmac_key, None).await?;
Ok(Json(ChangeStartResp { keyFetchToken: key_fetch_token, passwordChangeToken: change_token }))
}
@@ -92,20 +82,14 @@ pub(crate) struct WithChangeToken<const IS_FORGOT: bool>;
impl<const IS_FORGOT: bool> AuthSource for WithChangeToken<IS_FORGOT> {
type ID = PasswordChangeID;
type Context = (UserID, Option<String>);
- async fn hawk(
- r: &Request<'_>,
- id: &PasswordChangeID,
- ) -> Result<(SecretBytes<32>, Self::Context)> {
+ async fn hawk(r: &Request<'_>, id: &PasswordChangeID) -> Result<(HawkKey, Self::Context)> {
// unlike key fetch we'll use a separate transaction here since the body of the
// handler can fail.
let pool = <&Db as FromRequest>::from_request(r)
.await
.success_or_else(|| anyhow!("could not open db connection"))?;
let db = pool.begin().await?;
- let result = db
- .finish_password_change(id, IS_FORGOT)
- .await
- .map(|(h, ctx)| (SecretBytes(h.0), ctx))?;
+ let result = db.finish_password_change(id, IS_FORGOT).await?;
db.commit().await?;
Ok(result)
}
@@ -215,7 +199,7 @@ pub(crate) async fn forgot_start(
db.add_password_change(
&uid,
&forgot_req.token_id,
- &HawkKey(forgot_req.req_hmac_key.0),
+ &forgot_req.req_hmac_key,
Some(&forgot_code),
)
.await?;
@@ -255,12 +239,7 @@ pub(crate) async fn forgot_finish(
let reset_token = AccountResetToken::generate();
let reset_req = AccountResetReq::derive_from(&reset_token);
- db.add_account_reset(
- &data.context.0,
- &reset_req.token_id,
- &HawkKey(reset_req.req_hmac_key.0),
- )
- .await?;
+ db.add_account_reset(&data.context.0, &reset_req.token_id, &reset_req.req_hmac_key).await?;
Ok(Json(ForgotFinishResp { accountResetToken: reset_token }))
}
diff --git a/src/auth.rs b/src/auth.rs
index f56c5e2..304ab0f 100644
--- a/src/auth.rs
+++ b/src/auth.rs
@@ -11,17 +11,16 @@ use rocket::{request, Data, Ignite, Phase, Rocket, Sentinel};
use serde::Deserialize;
use serde_json::error::Category;
-use crate::crypto::SecretBytes;
use crate::db::DbConn;
use crate::types::oauth::ScopeSet;
-use crate::types::{OauthToken, UserID};
+use crate::types::{HawkKey, OauthToken, UserID};
use crate::Config;
#[rocket::async_trait]
pub(crate) trait AuthSource {
type ID: FromStr + Send + Sync + Clone;
type Context: Send + Sync;
- async fn hawk(r: &Request<'_>, id: &Self::ID) -> Result<(SecretBytes<32>, Self::Context)>;
+ async fn hawk(r: &Request<'_>, id: &Self::ID) -> Result<(HawkKey, Self::Context)>;
async fn bearer_token(r: &Request<'_>, id: &OauthToken) -> Result<(Self::ID, Self::Context)>;
}
@@ -227,7 +226,7 @@ pub(crate) struct WithBearer;
impl crate::auth::AuthSource for WithBearer {
type ID = UserID;
type Context = ScopeSet;
- async fn hawk(_r: &Request<'_>, _id: &Self::ID) -> Result<(SecretBytes<32>, Self::Context)> {
+ async fn hawk(_r: &Request<'_>, _id: &Self::ID) -> Result<(HawkKey, Self::Context)> {
bail!("hawk signatures not allowed here")
}
async fn bearer_token(
diff --git a/src/crypto.rs b/src/crypto.rs
index 7fba9cd..4413663 100644
--- a/src/crypto.rs
+++ b/src/crypto.rs
@@ -17,7 +17,7 @@ use sha2::Sha256;
use crate::{
serde::as_hex,
- types::{AccountResetID, KeyFetchID, PasswordChangeID, SessionID},
+ types::{AccountResetID, HawkKey, KeyFetchID, PasswordChangeID, SessionID},
};
const NAMESPACE: &[u8] = b"identity.mozilla.com/picl/v1/";
@@ -191,13 +191,13 @@ impl SessionToken {
pub(crate) struct SessionCredentials {
pub token_id: SessionID,
- pub req_hmac_key: SecretBytes<32>,
+ pub req_hmac_key: HawkKey,
}
impl SessionCredentials {
pub fn derive_from(seed: &SessionToken) -> Self {
let (token_id, req_hmac_key) = from_hkdf(&seed.0, &[NAMESPACE, b"sessionToken"]);
- Self { token_id: SessionID(token_id), req_hmac_key }
+ Self { token_id: SessionID(token_id), req_hmac_key: HawkKey(req_hmac_key) }
}
}
@@ -218,7 +218,7 @@ impl KeyFetchToken {
pub(crate) struct KeyFetchReq {
pub token_id: KeyFetchID,
- pub req_hmac_key: SecretBytes<32>,
+ pub req_hmac_key: HawkKey,
key_request_key: SecretBytes<32>,
}
@@ -226,7 +226,11 @@ impl KeyFetchReq {
pub fn derive_from(key_fetch_token: &KeyFetchToken) -> Self {
let (token_id, (req_hmac_key, key_request_key)) =
from_hkdf(&key_fetch_token.0, &[NAMESPACE, b"keyFetchToken"]);
- Self { token_id: KeyFetchID(token_id), req_hmac_key, key_request_key }
+ Self {
+ token_id: KeyFetchID(token_id),
+ req_hmac_key: HawkKey(req_hmac_key),
+ key_request_key,
+ }
}
pub fn derive_resp(&self) -> KeyFetchResp {
@@ -298,18 +302,18 @@ impl PasswordChangeToken {
pub(crate) struct PasswordChangeReq {
pub token_id: PasswordChangeID,
- pub req_hmac_key: SecretBytes<32>,
+ pub req_hmac_key: HawkKey,
}
impl PasswordChangeReq {
pub fn derive_from_change_token(token: &PasswordChangeToken) -> Self {
let (token_id, req_hmac_key) = from_hkdf(&token.0, &[NAMESPACE, b"passwordChangeToken"]);
- Self { token_id: PasswordChangeID(token_id), req_hmac_key }
+ Self { token_id: PasswordChangeID(token_id), req_hmac_key: HawkKey(req_hmac_key) }
}
pub fn derive_from_forgot_token(token: &PasswordChangeToken) -> Self {
let (token_id, req_hmac_key) = from_hkdf(&token.0, &[NAMESPACE, b"passwordForgotToken"]);
- Self { token_id: PasswordChangeID(token_id), req_hmac_key }
+ Self { token_id: PasswordChangeID(token_id), req_hmac_key: HawkKey(req_hmac_key) }
}
}
@@ -330,13 +334,13 @@ impl AccountResetToken {
pub(crate) struct AccountResetReq {
pub token_id: AccountResetID,
- pub req_hmac_key: SecretBytes<32>,
+ pub req_hmac_key: HawkKey,
}
impl AccountResetReq {
pub fn derive_from(token: &AccountResetToken) -> Self {
let (token_id, req_hmac_key) = from_hkdf(&token.0, &[NAMESPACE, b"accountResetToken"]);
- Self { token_id: AccountResetID(token_id), req_hmac_key }
+ Self { token_id: AccountResetID(token_id), req_hmac_key: HawkKey(req_hmac_key) }
}
}