diff --git a/src/controllers/admin/admin_account_controller.rs b/src/controllers/admin/admin_account_controller.rs index 364c606..0ca82b6 100644 --- a/src/controllers/admin/admin_account_controller.rs +++ b/src/controllers/admin/admin_account_controller.rs @@ -154,4 +154,24 @@ pub fn challenge_auth_with_key(r: &mut HttpRequestHandler) -> RequestResult { admin_key_authentication_challenges_helper::set(key.id, auth_state)?; r.set_response(challenge_response) +} + +/// Authenticate a user with a security key +pub fn auth_with_key(r: &mut HttpRequestHandler) -> RequestResult { + let key = r.post_admin_auth_key("mail", "key_id")?; + let credentials = r.post_auth_public_key_credential("credential")?; + + let state = r.some_or_internal_error( + admin_key_authentication_challenges_helper::get(key.id)?, + "Associated authentication state not found!", + )?; + + // Perform authentication + let state = get_wan().authenticate_credential(credentials, state)?; + r.some_or_bad_request(state, "Invalid key!")?; + + // Generate access token + let token = admin_access_token_helper::create(key.admin_id)?; + + r.set_response(AdminAuthSuccess::new(token)) } \ No newline at end of file diff --git a/src/data/base_request_handler.rs b/src/data/base_request_handler.rs index 28048b7..c2c68c9 100644 --- a/src/data/base_request_handler.rs +++ b/src/data/base_request_handler.rs @@ -177,6 +177,17 @@ pub trait BaseRequestHandler { } } + /// Unwrap an option, returning an error if none is returned + fn some_or_bad_request(&mut self, opt: Option, msg: &str) -> Res { + match opt { + None => { + self.bad_request(msg.to_string())?; + unreachable!() + } + Some(e) => Ok(e) + } + } + /// Get a user ID, if available fn user_id_opt(&self) -> Option { @@ -558,6 +569,13 @@ pub trait BaseRequestHandler { Ok(serde_json::from_str(&str)?) } + /// Get the response to a key authentication included in the request + fn post_auth_public_key_credential(&mut self, name: &str) -> Res { + let str = self.post_string(name)?; + + Ok(serde_json::from_str(&str)?) + } + /// Get the ID of a user included in a POST request fn post_user_id(&mut self, name: &str) -> ResultBoxError { let user_id = UserID::new(self.post_u64(name)?); diff --git a/src/routes.rs b/src/routes.rs index 481992e..3e391e6 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -356,5 +356,6 @@ pub fn get_routes() -> Vec { Route::admin_post("/admin/accounts/challenge_register_key", Box::new(admin_account_controller::challenge_register_key)), Route::admin_post("/admin/accounts/register_key", Box::new(admin_account_controller::register_key)), Route::limited_admin_post_without_login("/admin/accounts/challenge_auth_with_key", Box::new(admin_account_controller::challenge_auth_with_key), LimitPolicy::ANY(10)), + Route::limited_admin_post_without_login("/admin/accounts/auth_with_key", Box::new(admin_account_controller::auth_with_key), LimitPolicy::ANY(10)), ] } \ No newline at end of file