Skip to content

Commit

Permalink
Allow Authorization header for Web Sockets
Browse files Browse the repository at this point in the history
Some clients (Thirdparty) might use the `Authorization` header instead
of a query param. We didn't supported this since all the official
clients do not seem to use this way of working. But Bitwarden does check
both ways.

This PR adds an extra check for this header which can be optional.

Fixes #3776
  • Loading branch information
BlackDex committed Aug 31, 2023
1 parent f162e85 commit aa9bc1f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 2 deletions.
12 changes: 10 additions & 2 deletions src/api/notifications.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use tokio_tungstenite::{
};

use crate::{
auth::ClientIp,
auth::{ClientIp, WsAccessTokenHeader},
db::{
models::{Cipher, Folder, Send as DbSend, User},
DbConn,
Expand Down Expand Up @@ -111,11 +111,19 @@ fn websockets_hub<'r>(
ws: rocket_ws::WebSocket,
data: WsAccessToken,
ip: ClientIp,
header_token: WsAccessTokenHeader,
) -> Result<rocket_ws::Stream!['r], Error> {
let addr = ip.ip;
info!("Accepting Rocket WS connection from {addr}");

let Some(token) = data.access_token else { err_code!("Invalid claim", 401) };
let token = if let Some(token) = data.access_token {
token
} else if let Some(token) = header_token.access_token {
token
} else {
err_code!("Invalid claim", 401)
};

let Ok(claims) = crate::auth::decode_login(&token) else { err_code!("Invalid token", 401) };

let (mut rx, guard) = {
Expand Down
23 changes: 23 additions & 0 deletions src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,3 +825,26 @@ impl<'r> FromRequest<'r> for ClientIp {
})
}
}

pub struct WsAccessTokenHeader {
pub access_token: Option<String>,
}

#[rocket::async_trait]
impl<'r> FromRequest<'r> for WsAccessTokenHeader {
type Error = ();

async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let headers = request.headers();

// Get access_token
let access_token = match headers.get_one("Authorization") {
Some(a) => a.rsplit("Bearer ").next().map(String::from),
None => None,
};

Outcome::Success(Self {
access_token,
})
}
}

0 comments on commit aa9bc1f

Please sign in to comment.