multiple ways to sign
This commit is contained in:
parent
23e5e2c777
commit
9a2fe46105
@ -5,6 +5,6 @@ authors = ["Bryan Stitt <bryan@stitthappens.com>"]
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.61"
|
anyhow = "1.0.62"
|
||||||
bb8-redis = "0.11.0"
|
bb8-redis = "0.11.0"
|
||||||
tracing = "0.1.36"
|
tracing = "0.1.36"
|
||||||
|
@ -16,12 +16,12 @@ entities = { path = "../entities" }
|
|||||||
migration = { path = "../migration" }
|
migration = { path = "../migration" }
|
||||||
redis-rate-limit = { path = "../redis-rate-limit" }
|
redis-rate-limit = { path = "../redis-rate-limit" }
|
||||||
|
|
||||||
anyhow = { version = "1.0.61", features = ["backtrace"] }
|
anyhow = { version = "1.0.62", features = ["backtrace"] }
|
||||||
arc-swap = "1.5.1"
|
arc-swap = "1.5.1"
|
||||||
argh = "0.1.8"
|
argh = "0.1.8"
|
||||||
axum = { version = "0.5.15", features = ["headers", "serde_json", "tokio-tungstenite", "ws"] }
|
axum = { version = "0.5.15", features = ["headers", "serde_json", "tokio-tungstenite", "ws"] }
|
||||||
axum-client-ip = "0.2.0"
|
axum-client-ip = "0.2.0"
|
||||||
axum-macros = "*"
|
axum-macros = "0.2.3"
|
||||||
counter = "0.5.6"
|
counter = "0.5.6"
|
||||||
dashmap = "5.3.4"
|
dashmap = "5.3.4"
|
||||||
derive_more = "0.99.17"
|
derive_more = "0.99.17"
|
||||||
@ -39,7 +39,7 @@ num = "0.4.0"
|
|||||||
parking_lot = { version = "0.12.1", features = ["arc_lock"] }
|
parking_lot = { version = "0.12.1", features = ["arc_lock"] }
|
||||||
petgraph = "0.6.2"
|
petgraph = "0.6.2"
|
||||||
proctitle = "0.1.1"
|
proctitle = "0.1.1"
|
||||||
prometheus-client = "0.17.0"
|
prometheus-client = "0.18.0"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
# TODO: regex has several "perf" features that we might want to use
|
# TODO: regex has several "perf" features that we might want to use
|
||||||
regex = "1.6.0"
|
regex = "1.6.0"
|
||||||
@ -51,7 +51,7 @@ sea-orm = { version = "0.9.1", features = ["macros"] }
|
|||||||
serde = { version = "1.0.143", features = [] }
|
serde = { version = "1.0.143", features = [] }
|
||||||
serde_json = { version = "1.0.83", default-features = false, features = ["alloc", "raw_value"] }
|
serde_json = { version = "1.0.83", default-features = false, features = ["alloc", "raw_value"] }
|
||||||
# TODO: make sure this time version matches siwe. PR to put this in their prelude
|
# TODO: make sure this time version matches siwe. PR to put this in their prelude
|
||||||
time = "0.3.11"
|
time = "0.3.13"
|
||||||
tokio = { version = "1.20.1", features = ["full", "tracing"] }
|
tokio = { version = "1.20.1", features = ["full", "tracing"] }
|
||||||
# TODO: make sure this uuid version matches sea-orm. PR to put this in their prelude
|
# TODO: make sure this uuid version matches sea-orm. PR to put this in their prelude
|
||||||
tokio-stream = { version = "0.1.9", features = ["sync"] }
|
tokio-stream = { version = "0.1.9", features = ["sync"] }
|
||||||
|
@ -34,7 +34,9 @@ async fn handle_anyhow_error(err: anyhow::Error) -> (StatusCode, String) {
|
|||||||
|
|
||||||
/// http and websocket frontend for customers
|
/// http and websocket frontend for customers
|
||||||
pub async fn serve(port: u16, proxy_app: Arc<Web3ProxyApp>) -> anyhow::Result<()> {
|
pub async fn serve(port: u16, proxy_app: Arc<Web3ProxyApp>) -> anyhow::Result<()> {
|
||||||
// create a tracing span for each request
|
// create a tracing span for each request with a random request id and the method
|
||||||
|
// GET: websocket or static pages
|
||||||
|
// POST: http rpc or login
|
||||||
let request_tracing_layer =
|
let request_tracing_layer =
|
||||||
TraceLayer::new_for_http().make_span_with(|request: &Request<Body>| {
|
TraceLayer::new_for_http().make_span_with(|request: &Request<Body>| {
|
||||||
// We get the request id from the extensions
|
// We get the request id from the extensions
|
||||||
@ -70,6 +72,7 @@ pub async fn serve(port: u16, proxy_app: Arc<Web3ProxyApp>) -> anyhow::Result<()
|
|||||||
.route("/health", get(http::health))
|
.route("/health", get(http::health))
|
||||||
.route("/status", get(http::status))
|
.route("/status", get(http::status))
|
||||||
.route("/login/:user_address", get(users::get_login))
|
.route("/login/:user_address", get(users::get_login))
|
||||||
|
.route("/login/:user_address/:message_eip", get(users::get_login))
|
||||||
.route("/users", post(users::create_user))
|
.route("/users", post(users::create_user))
|
||||||
// .route(
|
// .route(
|
||||||
// "/foo",
|
// "/foo",
|
||||||
|
@ -21,6 +21,7 @@ use axum_client_ip::ClientIp;
|
|||||||
use axum_macros::debug_handler;
|
use axum_macros::debug_handler;
|
||||||
use entities::{user, user_keys};
|
use entities::{user, user_keys};
|
||||||
use ethers::{prelude::Address, types::Bytes};
|
use ethers::{prelude::Address, types::Bytes};
|
||||||
|
use hashbrown::HashMap;
|
||||||
use redis_rate_limit::redis::AsyncCommands;
|
use redis_rate_limit::redis::AsyncCommands;
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
use sea_orm::ActiveModelTrait;
|
use sea_orm::ActiveModelTrait;
|
||||||
@ -38,7 +39,7 @@ pub async fn get_login(
|
|||||||
ClientIp(ip): ClientIp,
|
ClientIp(ip): ClientIp,
|
||||||
// TODO: what does axum's error handling look like if the path fails to parse?
|
// TODO: what does axum's error handling look like if the path fails to parse?
|
||||||
// TODO: allow ENS names here?
|
// TODO: allow ENS names here?
|
||||||
Path(user_address): Path<Address>,
|
Path(mut params): Path<HashMap<String, String>>,
|
||||||
) -> FrontendResult {
|
) -> FrontendResult {
|
||||||
// TODO: refactor this to use the try operator
|
// TODO: refactor this to use the try operator
|
||||||
let _ip = match app.rate_limit_by_ip(ip).await {
|
let _ip = match app.rate_limit_by_ip(ip).await {
|
||||||
@ -65,7 +66,8 @@ pub async fn get_login(
|
|||||||
|
|
||||||
let expiration_time = issued_at.add(Duration::new(expire_seconds as i64, 0));
|
let expiration_time = issued_at.add(Duration::new(expire_seconds as i64, 0));
|
||||||
|
|
||||||
// TODO: get request_id out of the trace? do we need that when we have a none?
|
// TODO: proper errors. the first unwrap should be impossible, but the second will happen with bad input
|
||||||
|
let user_address: Address = params.remove("user_address").unwrap().parse().unwrap();
|
||||||
|
|
||||||
// TODO: get most of these from the app config
|
// TODO: get most of these from the app config
|
||||||
let message = Message {
|
let message = Message {
|
||||||
@ -98,7 +100,20 @@ pub async fn get_login(
|
|||||||
.set_ex(session_key, message.to_string(), expire_seconds)
|
.set_ex(session_key, message.to_string(), expire_seconds)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(message.to_string().into_response())
|
// there are multiple ways to sign messages and not all wallets support them
|
||||||
|
let message_eip = params
|
||||||
|
.remove("message_eip")
|
||||||
|
.unwrap_or_else(|| "eip4361".to_string());
|
||||||
|
|
||||||
|
let message: String = match message_eip.as_str() {
|
||||||
|
"eip4361" => message.to_string(),
|
||||||
|
// https://github.com/spruceid/siwe/issues/98
|
||||||
|
"eip191_string" => Bytes::from(message.eip191_string().unwrap()).to_string(),
|
||||||
|
"eip191_hash" => Bytes::from(&message.eip191_hash().unwrap()).to_string(),
|
||||||
|
_ => todo!("return a proper error"),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(message.into_response())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
|
Loading…
Reference in New Issue
Block a user