aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/mod.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-07 22:35:21 +0100
committertv <tv@krebsco.de>2026-11-07 22:35:21 +0100
commite696d2f40636a6613eddfb1a3afdf87aa7ffdedd (patch)
treeb2734381ef1d010d0efad209f116b12f625c0f40 /src/api/mod.rs
parent70ff0ec9e50bf506cc6d80b929a81e350289f6cc (diff)
auth: logging in by key
POST /auth/challenge and /auth/login/key: a node-signed challenge, valid five minutes and taken once, signed with one of the user's SSH keys (ssh-keygen -Y sign -n continuum-login), for a token. Auth plan M7 (key login, M2b).
Diffstat (limited to 'src/api/mod.rs')
-rw-r--r--src/api/mod.rs6
1 files changed, 5 insertions, 1 deletions
diff --git a/src/api/mod.rs b/src/api/mod.rs
index a12e219..2a523a4 100644
--- a/src/api/mod.rs
+++ b/src/api/mod.rs
@@ -40,7 +40,8 @@ use crate::document::store::StoreError;
use crate::state::AppState;
/// Builds the complete HTTP router. Everything except the API description (`/swagger-ui`,
-/// `/openapi.yaml`), `/health` and `/ready` is authenticated.
+/// `/openapi.yaml`), `/health`, `/ready` and logging in by key (`/auth/challenge`,
+/// `/auth/login/key`, which prove the user themselves) is authenticated.
pub(crate) fn router(state: AppState, auth_state: AuthState, debug_api: bool) -> Router {
let mut api: Router<AppState> = Router::new()
.route("/store", get(store::get_store_root))
@@ -117,6 +118,9 @@ pub(crate) fn router(state: AppState, auth_state: AuthState, debug_api: bool) ->
SwaggerUi::new("/swagger-ui").config(utoipa_swagger_ui::Config::from("../openapi.yaml")),
)
.route("/openapi.yaml", get(openapi_spec))
+ // Logging in by key: a challenge, and the token for it signed, without a password.
+ .route("/auth/challenge", axum::routing::post(login::challenge))
+ .route("/auth/login/key", axum::routing::post(login::login_key))
.route("/health", get(health::node_health))
.route("/ready", get(health::ready))
// Outermost, so authentication failures get the error body too.