Skip to content

Commit

Permalink
Introduce basic Auth
Browse files Browse the repository at this point in the history
  • Loading branch information
lucemans committed Nov 22, 2023
1 parent 7c6ffd5 commit 3f8983f
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 31 deletions.
44 changes: 29 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ axum = "0.6.20"
chrono = "0.4.31"
dotenvy = "0.15.7"
ethers = "2.0.10"
ethers-contract-derive = "2.0.11"
ethers-core = { version = "2.0.11", features = ["eip712"] }
hex = "0.4.3"
postgres = "0.19.7"
postgres-types = { version = "0.2.6", features = ["derive", "with-serde_json-1"] }
Expand All @@ -19,3 +21,9 @@ tokio-postgres = "0.7.10"
tower-http = { version = "0.4.3", features = ["cors"] }
tracing = "0.1.40"
tracing-subscriber = "0.3.18"

[features]
postgres = []
selfservice = []
eoa-auth = []
default = ["postgres", "selfservice", "eoa-auth"]
9 changes: 7 additions & 2 deletions src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@ use tracing::{debug, info};
/// Starts the HTTP Server
pub async fn serve(state: GlobalState) {
info!("Starting webserver");

let app = Router::new()
.route("/", get(root))
.route("/gateway", post(crate::gateway::endpoint::route))
.route("/update", post(crate::selfservice::endpoint::route))
.route("/gateway", post(crate::gateway::endpoint::route));

#[cfg(feature = "selfservice")]
let app = app.route("/update", post(crate::selfservice::endpoint::route));

let app = app
.route("/view/:name", get(crate::selfservice::view::route))
.with_state(Arc::new(state))
.layer(CorsLayer::very_permissive());
Expand Down
73 changes: 59 additions & 14 deletions src/selfservice/endpoint.rs
Original file line number Diff line number Diff line change
@@ -1,44 +1,89 @@
use std::{collections::HashMap, sync::Arc};

use axum::{
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
Json,
};
use ethers::providers::namehash;
use ethers::core::utils::rlp::Decodable;
use ethers::{core::k256::ecdsa, providers::namehash, types::Signature};
use ethers_contract_derive::{Eip712, EthAbiType};
use ethers_core::types::{transaction::eip712::Eip712, H160};
use std::{collections::HashMap, str::FromStr, sync::Arc};
use tracing::info;

use crate::state::GlobalState;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct UpdateNamePayload {
name: String,
records: HashMap<String, Option<String>>,
addresses: HashMap<String, Option<String>>,
payload: String,
// Arbitrary auth payload
auth: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct SignableUpdateNamePayload {
name: String,
records: HashMap<String, String>,
addresses: HashMap<String, String>,
time: u64,
}

fn convert_hashmap(a: HashMap<String, String>) -> HashMap<String, Option<String>> {
a.into_iter()
.map(|(k, v)| (k, Some(v)))
.collect::<HashMap<String, Option<String>>>()
}

pub async fn route(
State(state): State<Arc<GlobalState>>,
Json(payload): Json<UpdateNamePayload>,
) -> impl IntoResponse {
info!("Update name: {:?}", payload);

if payload.auth != "yes" {
return "auth error";
}
let auth = payload.auth;
let raw_payload = &payload.payload;
let payload: SignableUpdateNamePayload = serde_json::from_str(raw_payload).unwrap();

let hash = namehash(&payload.name);
let owner = state
.db
.get_addresses(&hash.to_fixed_bytes().to_vec(), &[&"60"])
.await
.get("60")
.unwrap()
.clone()
.unwrap();

let owner: H160 = owner.parse().unwrap();

#[cfg(feature = "eoa-auth")]
if verify_eoa_payload(&auth, &raw_payload, &owner).is_err() {
return (StatusCode::FORBIDDEN, "auth error");
}

state
.db
.upsert(&hash.to_fixed_bytes().to_vec(), &payload.records, &payload.addresses)
.upsert(
&hash.to_fixed_bytes().to_vec(),
&convert_hashmap(payload.records),
&convert_hashmap(payload.addresses),
)
.await;
(StatusCode::OK, "ok")
}

// handle(request_payload, state)
// .await
// .map_err(|x| x.into_response())
"ok"
pub fn verify_eoa_payload(auth: &str, message: &str, owner: &H160) -> Result<(), ()> {
let signature = ethers::types::Signature::from_str(&auth).unwrap();

let payload = signature.recover(message).unwrap();

info!("Recovered payload: {:?}", payload);
info!("Owner: {:?}", owner);

if payload.eq(owner) {
Ok(())
} else {
Err(())
}
}

0 comments on commit 3f8983f

Please sign in to comment.