Skip to content

Commit

Permalink
Controller JWT auth (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelsproul authored Sep 27, 2023
1 parent 488ad24 commit eed1587
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 2 deletions.
5 changes: 4 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ pub struct Config {
/// Path to the JWT secret for the primary execution engine.
#[arg(long, value_name = "PATH")]
pub ee_jwt_secret: String,
/// Path to TOML file JWT secrets for the non-canonical CL clients.
/// Path to the JWT secret for the controlling consensus client.
#[arg(long, value_name = "PATH")]
pub controller_jwt_secret: PathBuf,
/// Path to TOML file of JWT secrets for the non-controlling consensus clients.
///
/// See docs for TOML file format.
#[arg(long, value_name = "PATH")]
Expand Down
8 changes: 8 additions & 0 deletions src/jwt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ fn verify_parsed_token(token: UnverifiedToken, secret: &Secret) -> Result<Verifi
token.verify_with_key(secret).map_err(convert_err)
}

pub fn jwt_secret_from_path(path: &Path) -> Result<Secret, String> {
std::fs::read_to_string(path)
.map_err(|e| e.to_string())
.and_then(|hex_secret| hex::decode(hex_secret).map_err(|e| e.to_string()))
.and_then(|byte_secret| Secret::new_from_slice(&byte_secret).map_err(|e| e.to_string()))
.map_err(|e| format!("Invalid JWT secret at path {}: {e}", path.display()))
}

impl KeyCollection {
pub fn verify(&self, token: &str) -> Result<VerifiedToken, String> {
let parsed_token = UnverifiedToken::parse_unverified(token).map_err(convert_err)?;
Expand Down
20 changes: 19 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
config::Config,
jwt::KeyCollection,
jwt::{jwt_secret_from_path, verify_single_token, KeyCollection, Secret},
multiplexer::Multiplexer,
transition_config::handle_transition_config,
types::{
Expand Down Expand Up @@ -59,9 +59,11 @@ async fn main() {
let body_limit_mb = config.body_limit_mb;
let listen_address = config.listen_address;
let listen_port = config.listen_port;
let controller_jwt_secret = jwt_secret_from_path(&config.controller_jwt_secret).unwrap();
let client_jwt_collection = KeyCollection::load(&config.client_jwt_secrets).unwrap();
let multiplexer = Multiplexer::<E>::new(config, executor, log).unwrap();
let app_state = Arc::new(AppState {
controller_jwt_secret,
client_jwt_collection,
multiplexer,
});
Expand All @@ -82,6 +84,7 @@ async fn main() {
}

struct AppState {
controller_jwt_secret: Secret,
client_jwt_collection: KeyCollection,
multiplexer: Multiplexer<E>,
}
Expand Down Expand Up @@ -169,9 +172,24 @@ async fn process_client_request(

async fn handle_controller_json_rpc(
State(state): State<Arc<AppState>>,
TypedHeader(jwt_token_str): TypedHeader<Authorization<Bearer>>,
maybe_request: Result<Json<Request>, JsonRejection>,
) -> Result<Json<Response>, Json<ErrorResponse>> {
let jwt_secret = &state.controller_jwt_secret;
let multiplexer = &state.multiplexer;

// Check JWT auth.
if let Err(e) = verify_single_token(jwt_token_str.token(), jwt_secret) {
tracing::warn!(
error = ?e,
"Controller JWT auth failed"
);
return Err(Json(ErrorResponse::parse_error_generic(
serde_json::json!(0),
e,
)));
}

let Json(request) = maybe_request
.map_err(|e| ErrorResponse::parse_error_generic(serde_json::json!(0), e.body_text()))?;

Expand Down

0 comments on commit eed1587

Please sign in to comment.