support EIP1271 login
This commit is contained in:
parent
91cbce6ce8
commit
8f76d9320d
192
Cargo.lock
generated
192
Cargo.lock
generated
@ -570,12 +570,6 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base16ct"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce"
|
||||
|
||||
[[package]]
|
||||
name = "base16ct"
|
||||
version = "0.2.0"
|
||||
@ -1027,7 +1021,7 @@ dependencies = [
|
||||
"digest 0.10.7",
|
||||
"getrandom",
|
||||
"hmac",
|
||||
"k256 0.13.1",
|
||||
"k256",
|
||||
"lazy_static",
|
||||
"serde",
|
||||
"sha2 0.10.6",
|
||||
@ -1327,18 +1321,6 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.5.2"
|
||||
@ -1465,16 +1447,6 @@ dependencies = [
|
||||
"pem-rfc7468",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de"
|
||||
dependencies = [
|
||||
"const-oid 0.9.2",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.6"
|
||||
@ -1590,18 +1562,6 @@ version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30"
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.14.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c"
|
||||
dependencies = [
|
||||
"der 0.6.1",
|
||||
"elliptic-curve 0.12.3",
|
||||
"rfc6979 0.3.1",
|
||||
"signature 1.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.16.7"
|
||||
@ -1610,9 +1570,9 @@ checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428"
|
||||
dependencies = [
|
||||
"der 0.7.6",
|
||||
"digest 0.10.7",
|
||||
"elliptic-curve 0.13.5",
|
||||
"rfc6979 0.4.0",
|
||||
"signature 2.1.0",
|
||||
"elliptic-curve",
|
||||
"rfc6979",
|
||||
"signature",
|
||||
"spki 0.7.2",
|
||||
]
|
||||
|
||||
@ -1622,40 +1582,21 @@ version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3"
|
||||
dependencies = [
|
||||
"base16ct 0.1.1",
|
||||
"crypto-bigint 0.4.9",
|
||||
"der 0.6.1",
|
||||
"digest 0.10.7",
|
||||
"ff 0.12.1",
|
||||
"generic-array",
|
||||
"group 0.12.1",
|
||||
"rand_core",
|
||||
"sec1 0.3.0",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.13.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b"
|
||||
dependencies = [
|
||||
"base16ct 0.2.0",
|
||||
"base16ct",
|
||||
"crypto-bigint 0.5.2",
|
||||
"digest 0.10.7",
|
||||
"ff 0.13.0",
|
||||
"ff",
|
||||
"generic-array",
|
||||
"group 0.13.0",
|
||||
"group",
|
||||
"pkcs8 0.10.2",
|
||||
"rand_core",
|
||||
"sec1 0.7.2",
|
||||
"sec1",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
@ -1693,7 +1634,7 @@ dependencies = [
|
||||
"base64 0.13.1",
|
||||
"bytes",
|
||||
"hex",
|
||||
"k256 0.13.1",
|
||||
"k256",
|
||||
"log",
|
||||
"rand",
|
||||
"rlp",
|
||||
@ -1928,11 +1869,11 @@ dependencies = [
|
||||
"bytes",
|
||||
"cargo_metadata 0.15.4",
|
||||
"chrono",
|
||||
"elliptic-curve 0.13.5",
|
||||
"elliptic-curve",
|
||||
"ethabi",
|
||||
"generic-array",
|
||||
"hex",
|
||||
"k256 0.13.1",
|
||||
"k256",
|
||||
"num_enum 0.6.1",
|
||||
"once_cell",
|
||||
"open-fastrlp",
|
||||
@ -2036,7 +1977,7 @@ dependencies = [
|
||||
"async-trait",
|
||||
"coins-bip32",
|
||||
"coins-bip39",
|
||||
"elliptic-curve 0.13.5",
|
||||
"elliptic-curve",
|
||||
"eth-keystore",
|
||||
"ethers-core",
|
||||
"hex",
|
||||
@ -2145,16 +2086,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ff"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ff"
|
||||
version = "0.13.0"
|
||||
@ -2482,24 +2413,13 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "558b88954871f5e5b2af0e62e2e176c8bde7a6c2c4ed41b13d138d96da2e2cbd"
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7"
|
||||
dependencies = [
|
||||
"ff 0.12.1",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
|
||||
dependencies = [
|
||||
"ff 0.13.0",
|
||||
"ff",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
@ -3049,9 +2969,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "iri-string"
|
||||
version = "0.6.0"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d0586ad318a04c73acdbad33f67969519b5452c80770c4c72059a686da48a7e"
|
||||
checksum = "21859b667d66a4c1dacd9df0863b3efb65785474255face87f5bca39dd8407c0"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde",
|
||||
@ -3111,19 +3031,6 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "k256"
|
||||
version = "0.11.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"ecdsa 0.14.8",
|
||||
"elliptic-curve 0.12.3",
|
||||
"sha2 0.10.6",
|
||||
"sha3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "k256"
|
||||
version = "0.13.1"
|
||||
@ -3131,11 +3038,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"ecdsa 0.16.7",
|
||||
"elliptic-curve 0.13.5",
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
"once_cell",
|
||||
"sha2 0.10.6",
|
||||
"signature 2.1.0",
|
||||
"signature",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4169,16 +4076,6 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba"
|
||||
dependencies = [
|
||||
"der 0.6.1",
|
||||
"spki 0.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.10.2"
|
||||
@ -4720,17 +4617,6 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0"
|
||||
|
||||
[[package]]
|
||||
name = "rfc6979"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb"
|
||||
dependencies = [
|
||||
"crypto-bigint 0.4.9",
|
||||
"hmac",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rfc6979"
|
||||
version = "0.4.0"
|
||||
@ -5261,27 +5147,13 @@ version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||
|
||||
[[package]]
|
||||
name = "sec1"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928"
|
||||
dependencies = [
|
||||
"base16ct 0.1.1",
|
||||
"der 0.6.1",
|
||||
"generic-array",
|
||||
"pkcs8 0.9.0",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sec1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e"
|
||||
dependencies = [
|
||||
"base16ct 0.2.0",
|
||||
"base16ct",
|
||||
"der 0.7.6",
|
||||
"generic-array",
|
||||
"pkcs8 0.10.2",
|
||||
@ -5642,16 +5514,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signature"
|
||||
version = "1.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
|
||||
dependencies = [
|
||||
"digest 0.10.7",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signature"
|
||||
version = "2.1.0"
|
||||
@ -5677,13 +5539,13 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
|
||||
[[package]]
|
||||
name = "siwe"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e6d1f422a568af1e98db37c6d0427c7218459ccac39218fd15a51a34d3933af"
|
||||
source = "git+https://github.com/llamanodes/siwe-rs?rev=013be5204ff1c85778ce21619f4b677a003db8a1#013be5204ff1c85778ce21619f4b677a003db8a1"
|
||||
dependencies = [
|
||||
"ethers",
|
||||
"hex",
|
||||
"http",
|
||||
"iri-string",
|
||||
"k256 0.11.6",
|
||||
"k256",
|
||||
"rand",
|
||||
"serde",
|
||||
"sha3",
|
||||
@ -5802,16 +5664,6 @@ dependencies = [
|
||||
"der 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"der 0.6.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.7.2"
|
||||
|
@ -25,7 +25,7 @@ redis-rate-limiter = { path = "../redis-rate-limiter" }
|
||||
#ethers = { git = "https://github.com/llamanodes/ethers-rs/", rev = "eb68f5d60850008cd302762bd3a5a4bdcfecc713", default-features = false, features = ["rustls", "ws"] }
|
||||
influxdb2 = { git = "https://github.com/llamanodes/influxdb2", features = ["rustls"], rev = "2d125128696a29d7e0b9abc052c928937e7c0579" }
|
||||
influxdb2-structmap = { git = "https://github.com/llamanodes/influxdb2/", rev = "2d125128696a29d7e0b9abc052c928937e7c0579"}
|
||||
#siwe = { git = "https://github.com/llamanodes/siwe-rs", rev = "bef5449b5dd8beb4e9fc697f09cd6dd11ba8f6e6", features = ["ethers", "serde"] }
|
||||
siwe = { git = "https://github.com/llamanodes/siwe-rs", rev = "013be5204ff1c85778ce21619f4b677a003db8a1", features = ["ethers", "serde"] }
|
||||
|
||||
# TODO: regex has several "perf" features that we might want to use
|
||||
# TODO: make sure this uuid version matches sea-orm. PR to put this in their prelude
|
||||
@ -89,7 +89,6 @@ sentry-tracing = "0.31.5"
|
||||
serde = { version = "1.0.164" }
|
||||
serde_json = { version = "1.0.99", default-features = false, features = ["raw_value"] }
|
||||
serde_prometheus = "0.2.3"
|
||||
siwe = { version = "0.5.2", features = ["serde"] }
|
||||
strum = { version = "0.25.0", features = ["derive"] }
|
||||
time = { version = "0.3.22", features = ["serde-well-known"] }
|
||||
tokio = { version = "1.28.2", features = ["full", "tracing"] }
|
||||
|
@ -21,6 +21,7 @@ use reqwest::header::ToStrError;
|
||||
use rust_decimal::Error as DecimalError;
|
||||
use serde::Serialize;
|
||||
use serde_json::value::RawValue;
|
||||
use siwe::VerificationError;
|
||||
use std::sync::Arc;
|
||||
use std::{borrow::Cow, net::IpAddr};
|
||||
use tokio::{sync::AcquireError, task::JoinError, time::Instant};
|
||||
@ -54,8 +55,6 @@ pub enum Web3ProxyError {
|
||||
Contract(ContractError<EthersHttpProvider>),
|
||||
Database(DbErr),
|
||||
Decimal(DecimalError),
|
||||
#[display(fmt = "{:#?}, {:#?}", _0, _1)]
|
||||
EipVerificationFailed(Box<Web3ProxyError>, Box<Web3ProxyError>),
|
||||
EthersHttpClient(ethers::prelude::HttpClientError),
|
||||
EthersProvider(ethers::prelude::ProviderError),
|
||||
EthersWsClient(ethers::prelude::WsClientError),
|
||||
@ -133,6 +132,7 @@ pub enum Web3ProxyError {
|
||||
SemaphoreAcquireError(AcquireError),
|
||||
SendAppStatError(flume::SendError<crate::stats::AppStat>),
|
||||
SerdeJson(serde_json::Error),
|
||||
SiweVerification(VerificationError),
|
||||
/// simple way to return an error message to the user and an anyhow to our logs
|
||||
#[display(fmt = "{}, {}, {:?}", _0, _1, _2)]
|
||||
StatusCode(StatusCode, Cow<'static, str>, Option<anyhow::Error>),
|
||||
@ -148,7 +148,6 @@ pub enum Web3ProxyError {
|
||||
UserAgentNotAllowed(headers::UserAgent),
|
||||
UserIdZero,
|
||||
PaymentRequired,
|
||||
VerificationError(siwe::VerificationError),
|
||||
WatchRecvError(tokio::sync::watch::error::RecvError),
|
||||
WatchSendError,
|
||||
WebsocketOnly,
|
||||
@ -267,20 +266,12 @@ impl Web3ProxyError {
|
||||
},
|
||||
)
|
||||
}
|
||||
Self::EipVerificationFailed(err_1, err_191) => {
|
||||
trace!(
|
||||
"EipVerificationFailed err_1={:#?} err2={:#?}",
|
||||
err_1,
|
||||
err_191
|
||||
);
|
||||
Self::SiweVerification(err) => {
|
||||
trace!("Siwe Verification err={:#?}", err,);
|
||||
(
|
||||
StatusCode::UNAUTHORIZED,
|
||||
JsonRpcErrorData {
|
||||
message: format!(
|
||||
"both the primary and eip191 verification failed: {:#?}; {:#?}",
|
||||
err_1, err_191
|
||||
)
|
||||
.into(),
|
||||
message: format!("siwe verification error: {:#?}", err).into(),
|
||||
code: StatusCode::UNAUTHORIZED.as_u16().into(),
|
||||
data: None,
|
||||
},
|
||||
@ -960,17 +951,6 @@ impl Web3ProxyError {
|
||||
},
|
||||
)
|
||||
}
|
||||
Self::VerificationError(err) => {
|
||||
trace!("VerificationError err={:#?}", err);
|
||||
(
|
||||
StatusCode::BAD_REQUEST,
|
||||
JsonRpcErrorData {
|
||||
message: "verification error!".into(),
|
||||
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
||||
data: None,
|
||||
},
|
||||
)
|
||||
}
|
||||
Self::WatchRecvError(err) => {
|
||||
error!("WatchRecvError err={:#?}", err);
|
||||
(
|
||||
|
@ -252,6 +252,16 @@ pub async fn admin_login_get(
|
||||
.db_replica()
|
||||
.web3_context("login requires a replica database")?;
|
||||
|
||||
// delete ALL expired rows.
|
||||
let now = Utc::now();
|
||||
let delete_result = pending_login::Entity::delete_many()
|
||||
.filter(pending_login::Column::ExpiresAt.lte(now))
|
||||
.exec(&db_conn)
|
||||
.await?;
|
||||
|
||||
// TODO: emit a stat? if this is high something weird might be happening
|
||||
debug!("cleared expired pending_logins: {:?}", delete_result);
|
||||
|
||||
// Get the user that we want to imitate from the read-only database (their id ...)
|
||||
// TODO: Only get the id, not the whole user object ...
|
||||
let user = user::Entity::find()
|
||||
@ -404,39 +414,16 @@ pub async fn admin_login_post(
|
||||
.parse()
|
||||
.web3_context("parsing siwe message")?;
|
||||
|
||||
// default options are fine. the message includes timestamp and domain and nonce
|
||||
let verify_config = VerificationOpts::default();
|
||||
// mostly default options are fine. the message includes timestamp and domain and nonce
|
||||
let verify_config = VerificationOpts {
|
||||
rpc_provider: Some(app.internal_provider.clone()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let db_conn = app
|
||||
.db_conn()
|
||||
.web3_context("deleting expired pending logins requires a db")?;
|
||||
|
||||
if let Err(err_1) = our_msg
|
||||
our_msg
|
||||
.verify(&their_sig, &verify_config)
|
||||
.await
|
||||
.web3_context("verifying signature against our local message")
|
||||
{
|
||||
// verification method 1 failed. try eip191
|
||||
if let Err(err_191) = our_msg
|
||||
.verify_eip191(&their_sig)
|
||||
.web3_context("verifying eip191 signature against our local message")
|
||||
{
|
||||
// delete ALL expired rows.
|
||||
let now = Utc::now();
|
||||
let delete_result = pending_login::Entity::delete_many()
|
||||
.filter(pending_login::Column::ExpiresAt.lte(now))
|
||||
.exec(&db_conn)
|
||||
.await?;
|
||||
|
||||
// TODO: emit a stat? if this is high something weird might be happening
|
||||
debug!("cleared expired pending_logins: {:?}", delete_result);
|
||||
|
||||
return Err(Web3ProxyError::EipVerificationFailed(
|
||||
Box::new(err_1),
|
||||
Box::new(err_191),
|
||||
));
|
||||
}
|
||||
}
|
||||
.web3_context("verifying signature against our local message")?;
|
||||
|
||||
let imitating_user_id = user_pending_login
|
||||
.imitating_user
|
||||
@ -456,6 +443,10 @@ pub async fn admin_login_post(
|
||||
.await?
|
||||
.web3_context("admin address was not found!")?;
|
||||
|
||||
let db_conn = app
|
||||
.db_conn()
|
||||
.web3_context("deleting expired pending logins requires a db")?;
|
||||
|
||||
// Add a message that the admin has logged in
|
||||
// Note that the admin is trying to log in as this user
|
||||
let trail = admin_trail::ActiveModel {
|
||||
@ -500,9 +491,7 @@ pub async fn admin_login_post(
|
||||
// add bearer to the database
|
||||
|
||||
// expire in 2 days, because this is more critical (and shouldn't need to be done so long!)
|
||||
let expires_at = Utc::now()
|
||||
.checked_add_signed(chrono::Duration::days(2))
|
||||
.unwrap();
|
||||
let expires_at = Utc::now() + chrono::Duration::days(2);
|
||||
|
||||
// TODO: Here, the bearer token should include a message
|
||||
// TODO: Above, make sure that the calling address is an admin!
|
||||
|
@ -29,7 +29,7 @@ use std::ops::Add;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use time::{Duration, OffsetDateTime};
|
||||
use tracing::{trace, warn};
|
||||
use tracing::{error, trace, warn};
|
||||
use ulid::Ulid;
|
||||
|
||||
/// `GET /user/login/:user_address` or `GET /user/login/:user_address/:message_eip` -- Start the "Sign In with Ethereum" (siwe) login flow.
|
||||
@ -38,8 +38,7 @@ use ulid::Ulid;
|
||||
/// - eip191_bytes
|
||||
/// - eip191_hash
|
||||
/// - eip4361 (default)
|
||||
///
|
||||
/// Coming soon: eip1271
|
||||
/// - eip1271
|
||||
///
|
||||
/// This is the initial entrypoint for logging in. Take the response from this endpoint and give it to your user's wallet for singing. POST the response to `/user/login`.
|
||||
///
|
||||
@ -103,6 +102,13 @@ pub async fn user_login_get(
|
||||
|
||||
let db_conn = app.db_conn().web3_context("login requires a database")?;
|
||||
|
||||
// delete ALL expired rows.
|
||||
let now = Utc::now();
|
||||
let _ = pending_login::Entity::delete_many()
|
||||
.filter(pending_login::Column::ExpiresAt.lte(now))
|
||||
.exec(&db_conn)
|
||||
.await?;
|
||||
|
||||
// massage types to fit in the database. sea-orm does not make this very elegant
|
||||
let uuid = Uuid::from_u128(nonce.into());
|
||||
// we add 1 to expire_seconds just to be sure the database has the key for the full expiration_time
|
||||
@ -234,11 +240,8 @@ pub async fn user_login_post(
|
||||
.db_replica()
|
||||
.web3_context("Getting database connection")?;
|
||||
|
||||
// massage type for the db
|
||||
let login_nonce_uuid: Uuid = login_nonce.clone().into();
|
||||
|
||||
let user_pending_login = pending_login::Entity::find()
|
||||
.filter(pending_login::Column::Nonce.eq(login_nonce_uuid))
|
||||
.filter(pending_login::Column::Nonce.eq(Uuid::from(login_nonce.clone())))
|
||||
.one(db_replica.as_ref())
|
||||
.await
|
||||
.web3_context("database error while finding pending_login")?
|
||||
@ -249,40 +252,17 @@ pub async fn user_login_post(
|
||||
.parse()
|
||||
.web3_context("parsing siwe message")?;
|
||||
|
||||
// default options are fine. the message includes timestamp and domain and nonce
|
||||
let verify_config = VerificationOpts::default();
|
||||
// mostly default options are fine. the message includes timestamp and domain and nonce
|
||||
let verify_config = VerificationOpts {
|
||||
rpc_provider: Some(app.internal_provider.clone()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// Check with both verify and verify_eip191
|
||||
if let Err(err_1) = our_msg
|
||||
our_msg
|
||||
.verify(&their_sig, &verify_config)
|
||||
.await
|
||||
.web3_context("verifying signature against our local message")
|
||||
{
|
||||
// verification method 1 failed. try eip191
|
||||
if let Err(err_191) = our_msg
|
||||
.verify_eip191(&their_sig)
|
||||
.web3_context("verifying eip191 signature against our local message")
|
||||
{
|
||||
let db_conn = app
|
||||
.db_conn()
|
||||
.web3_context("deleting expired pending logins requires a db")?;
|
||||
|
||||
// delete ALL expired rows.
|
||||
let now = Utc::now();
|
||||
let delete_result = pending_login::Entity::delete_many()
|
||||
.filter(pending_login::Column::ExpiresAt.lte(now))
|
||||
.exec(&db_conn)
|
||||
.await?;
|
||||
|
||||
// TODO: emit a stat? if this is high something weird might be happening
|
||||
trace!("cleared expired pending_logins: {:?}", delete_result);
|
||||
|
||||
return Err(Web3ProxyError::EipVerificationFailed(
|
||||
Box::new(err_1),
|
||||
Box::new(err_191),
|
||||
));
|
||||
}
|
||||
}
|
||||
.web3_context("verifying signature against our local message")?;
|
||||
|
||||
// TODO: limit columns or load whole user?
|
||||
let caller = user::Entity::find()
|
||||
@ -356,11 +336,7 @@ pub async fn user_login_post(
|
||||
.one(&txn)
|
||||
.await?
|
||||
.ok_or(Web3ProxyError::BadRequest(
|
||||
format!(
|
||||
"The referral_link you provided does not exist {}",
|
||||
referral_code
|
||||
)
|
||||
.into(),
|
||||
"The referral_link you provided does not exist".into(),
|
||||
))?;
|
||||
|
||||
// Create a new item in the database,
|
||||
@ -430,7 +406,7 @@ pub async fn user_login_post(
|
||||
.delete(&db_conn)
|
||||
.await
|
||||
{
|
||||
warn!("Failed to delete nonce:{}: {}", login_nonce.0, err);
|
||||
error!("Failed to delete nonce:{}: {}", login_nonce, err);
|
||||
}
|
||||
|
||||
Ok(response)
|
||||
|
@ -1,6 +1,7 @@
|
||||
use axum::headers::authorization::Bearer;
|
||||
use migration::sea_orm::prelude::Uuid;
|
||||
use serde::Serialize;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
use ulid::Ulid;
|
||||
|
||||
@ -47,6 +48,12 @@ impl From<UserBearerToken> for Uuid {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for UserBearerToken {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Bearer> for UserBearerToken {
|
||||
type Error = ulid::DecodeError;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user