Initial oauth impl

This commit is contained in:
lewis
2025-12-11 20:05:59 +02:00
parent 0944ecf5bf
commit 17a7f1dc2b
115 changed files with 12007 additions and 1663 deletions
+32 -64
View File
@@ -20,31 +20,22 @@ pub async fn upload_blob(
headers: axum::http::HeaderMap,
body: Bytes,
) -> Response {
let auth_header = headers.get("Authorization");
if auth_header.is_none() {
return (
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationRequired"})),
)
.into_response();
}
let token = auth_header
.unwrap()
.to_str()
.unwrap_or("")
.replace("Bearer ", "");
let session = sqlx::query!(
"SELECT s.did, k.key_bytes FROM sessions s JOIN users u ON s.did = u.did JOIN user_keys k ON u.id = k.user_id WHERE s.access_jwt = $1",
token
)
.fetch_optional(&state.db)
.await
.unwrap_or(None);
let (did, key_bytes) = match session {
Some(row) => (row.did, row.key_bytes),
let token = match crate::auth::extract_bearer_token_from_header(
headers.get("Authorization").and_then(|h| h.to_str().ok())
) {
Some(t) => t,
None => {
return (
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationRequired"})),
)
.into_response();
}
};
let auth_user = match crate::auth::validate_bearer_token(&state.db, &token).await {
Ok(user) => user,
Err(_) => {
return (
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationFailed"})),
@@ -52,14 +43,7 @@ pub async fn upload_blob(
.into_response();
}
};
if let Err(_) = crate::auth::verify_token(&token, &key_bytes) {
return (
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationFailed", "message": "Invalid token signature"})),
)
.into_response();
}
let did = auth_user.did;
let mime_type = headers
.get("content-type")
@@ -182,32 +166,22 @@ pub async fn list_missing_blobs(
headers: axum::http::HeaderMap,
Query(params): Query<ListMissingBlobsParams>,
) -> Response {
let auth_header = headers.get("Authorization");
if auth_header.is_none() {
return (
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationRequired"})),
)
.into_response();
}
let token = auth_header
.unwrap()
.to_str()
.unwrap_or("")
.replace("Bearer ", "");
let session = sqlx::query!(
"SELECT s.did, k.key_bytes FROM sessions s JOIN users u ON s.did = u.did JOIN user_keys k ON u.id = k.user_id WHERE s.access_jwt = $1",
token
)
.fetch_optional(&state.db)
.await
.unwrap_or(None);
let (did, key_bytes) = match session {
Some(row) => (row.did, row.key_bytes),
let token = match crate::auth::extract_bearer_token_from_header(
headers.get("Authorization").and_then(|h| h.to_str().ok())
) {
Some(t) => t,
None => {
return (
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationRequired"})),
)
.into_response();
}
};
let auth_user = match crate::auth::validate_bearer_token(&state.db, &token).await {
Ok(user) => user,
Err(_) => {
return (
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationFailed"})),
@@ -216,13 +190,7 @@ pub async fn list_missing_blobs(
}
};
if let Err(_) = crate::auth::verify_token(&token, &key_bytes) {
return (
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationFailed", "message": "Invalid token signature"})),
)
.into_response();
}
let did = auth_user.did;
let user_query = sqlx::query!("SELECT id FROM users WHERE did = $1", did)
.fetch_optional(&state.db)
+16 -31
View File
@@ -73,31 +73,22 @@ pub async fn apply_writes(
headers: axum::http::HeaderMap,
Json(input): Json<ApplyWritesInput>,
) -> Response {
let auth_header = headers.get("Authorization");
if auth_header.is_none() {
return (
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationRequired"})),
)
.into_response();
}
let token = auth_header
.unwrap()
.to_str()
.unwrap_or("")
.replace("Bearer ", "");
let session = sqlx::query!(
"SELECT s.did, k.key_bytes FROM sessions s JOIN users u ON s.did = u.did JOIN user_keys k ON u.id = k.user_id WHERE s.access_jwt = $1",
token
)
.fetch_optional(&state.db)
.await
.unwrap_or(None);
let (did, key_bytes) = match session {
Some(row) => (row.did, row.key_bytes),
let token = match crate::auth::extract_bearer_token_from_header(
headers.get("Authorization").and_then(|h| h.to_str().ok())
) {
Some(t) => t,
None => {
return (
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationRequired"})),
)
.into_response();
}
};
let auth_user = match crate::auth::validate_bearer_token(&state.db, &token).await {
Ok(user) => user,
Err(_) => {
return (
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationFailed"})),
@@ -106,13 +97,7 @@ pub async fn apply_writes(
}
};
if let Err(_) = crate::auth::verify_token(&token, &key_bytes) {
return (
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationFailed", "message": "Invalid token signature"})),
)
.into_response();
}
let did = auth_user.did;
if input.repo != did {
return (
+15 -33
View File
@@ -23,45 +23,27 @@ pub async fn prepare_repo_write(
headers: &HeaderMap,
repo_did: &str,
) -> Result<(String, Uuid, Cid), Response> {
let auth_header = headers.get("Authorization").ok_or_else(|| {
let token = crate::auth::extract_bearer_token_from_header(
headers.get("Authorization").and_then(|h| h.to_str().ok())
).ok_or_else(|| {
(
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationRequired"})),
)
.into_response()
})?;
let token = auth_header
.to_str()
.unwrap_or("")
.replace("Bearer ", "");
let session = sqlx::query!(
"SELECT s.did, k.key_bytes FROM sessions s JOIN users u ON s.did = u.did JOIN user_keys k ON u.id = k.user_id WHERE s.access_jwt = $1",
token
)
.fetch_optional(&state.db)
.await
.map_err(|e| {
error!("DB error fetching session: {}", e);
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response()
})?
.ok_or_else(|| {
(
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationFailed"})),
)
.into_response()
})?;
let auth_user = crate::auth::validate_bearer_token(&state.db, &token)
.await
.map_err(|_| {
(
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationFailed"})),
)
.into_response()
})?;
crate::auth::verify_token(&token, &session.key_bytes).map_err(|_| {
(
StatusCode::UNAUTHORIZED,
Json(json!({"error": "AuthenticationFailed", "message": "Invalid token signature"})),
)
.into_response()
})?;
if repo_did != session.did {
if repo_did != auth_user.did {
return Err((
StatusCode::FORBIDDEN,
Json(json!({"error": "InvalidRepo", "message": "Repo does not match authenticated user"})),
@@ -69,7 +51,7 @@ pub async fn prepare_repo_write(
.into_response());
}
let user_id = sqlx::query_scalar!("SELECT id FROM users WHERE did = $1", session.did)
let user_id = sqlx::query_scalar!("SELECT id FROM users WHERE did = $1", auth_user.did)
.fetch_optional(&state.db)
.await
.map_err(|e| {
@@ -108,7 +90,7 @@ pub async fn prepare_repo_write(
.into_response()
})?;
Ok((session.did, user_id, current_root_cid))
Ok((auth_user.did, user_id, current_root_cid))
}
#[derive(Deserialize)]