commit 2aa72eb2401408ef05b24be39465476ce611a9d4
parent f21089900e86274c8a89a15a6ff79dfb9c433ca2
Author: Daniel GarcĂa <dani-garcia@users.noreply.github.com>
Date: Wed, 15 Mar 2023 22:03:15 +0100
Merge pull request #3329 from jjlin/knowndevices-header
Add support for `/api/devices/knowndevice` with HTTP header params
Diffstat:
1 file changed, 56 insertions(+), 1 deletion(-)
diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs
@@ -12,6 +12,11 @@ use crate::{
mail, CONFIG,
};
+use rocket::{
+ http::Status,
+ request::{FromRequest, Outcome, Request},
+};
+
pub fn routes() -> Vec<rocket::Route> {
routes![
register,
@@ -39,6 +44,7 @@ pub fn routes() -> Vec<rocket::Route> {
api_key,
rotate_api_key,
get_known_device,
+ get_known_device_from_path,
put_avatar,
]
}
@@ -872,8 +878,9 @@ async fn rotate_api_key(data: JsonUpcase<SecretVerificationRequest>, headers: He
_api_key(data, true, headers, conn).await
}
+// This variant is deprecated: https://github.com/bitwarden/server/pull/2682
#[get("/devices/knowndevice/<email>/<uuid>")]
-async fn get_known_device(email: String, uuid: String, mut conn: DbConn) -> JsonResult {
+async fn get_known_device_from_path(email: String, uuid: String, mut conn: DbConn) -> JsonResult {
// This endpoint doesn't have auth header
let mut result = false;
if let Some(user) = User::find_by_mail(&email, &mut conn).await {
@@ -881,3 +888,51 @@ async fn get_known_device(email: String, uuid: String, mut conn: DbConn) -> Json
}
Ok(Json(json!(result)))
}
+
+#[get("/devices/knowndevice")]
+async fn get_known_device(device: KnownDevice, conn: DbConn) -> JsonResult {
+ get_known_device_from_path(device.email, device.uuid, conn).await
+}
+
+struct KnownDevice {
+ email: String,
+ uuid: String,
+}
+
+#[rocket::async_trait]
+impl<'r> FromRequest<'r> for KnownDevice {
+ type Error = &'static str;
+
+ async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
+ let email = if let Some(email_b64) = req.headers().get_one("X-Request-Email") {
+ let email_bytes = match data_encoding::BASE64URL.decode(email_b64.as_bytes()) {
+ Ok(bytes) => bytes,
+ Err(_) => {
+ return Outcome::Failure((
+ Status::BadRequest,
+ "X-Request-Email value failed to decode as base64url",
+ ));
+ }
+ };
+ match String::from_utf8(email_bytes) {
+ Ok(email) => email,
+ Err(_) => {
+ return Outcome::Failure((Status::BadRequest, "X-Request-Email value failed to decode as UTF-8"));
+ }
+ }
+ } else {
+ return Outcome::Failure((Status::BadRequest, "X-Request-Email value is required"));
+ };
+
+ let uuid = if let Some(uuid) = req.headers().get_one("X-Device-Identifier") {
+ uuid.to_string()
+ } else {
+ return Outcome::Failure((Status::BadRequest, "X-Device-Identifier value is required"));
+ };
+
+ Outcome::Success(KnownDevice {
+ email,
+ uuid,
+ })
+ }
+}