mirror of
https://github.com/aljazceru/pubky-core.git
synced 2026-01-28 18:34:27 +01:00
feat(pubky): add PubkyClient::authorize()
This commit is contained in:
190
Cargo.lock
generated
190
Cargo.lock
generated
@@ -144,6 +144,7 @@ dependencies = [
|
||||
"pubky",
|
||||
"pubky-common",
|
||||
"rpassword",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
@@ -1011,6 +1012,24 @@ dependencies = [
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.27.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"http",
|
||||
"hyper",
|
||||
"hyper-util",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
"tower-service",
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-util"
|
||||
version = "0.1.6"
|
||||
@@ -1216,13 +1235,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.11"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||
checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"wasi",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1250,16 +1270,6 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.1"
|
||||
@@ -1569,6 +1579,54 @@ dependencies = [
|
||||
"psl-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quinn"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"pin-project-lite",
|
||||
"quinn-proto",
|
||||
"quinn-udp",
|
||||
"rustc-hash",
|
||||
"rustls",
|
||||
"socket2",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quinn-proto"
|
||||
version = "0.11.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba92fb39ec7ad06ca2582c0ca834dfeadcaf06ddfc8e635c80aa7e1c05315fdd"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"rand",
|
||||
"ring",
|
||||
"rustc-hash",
|
||||
"rustls",
|
||||
"slab",
|
||||
"thiserror",
|
||||
"tinyvec",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quinn-udp"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"once_cell",
|
||||
"socket2",
|
||||
"tracing",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.36"
|
||||
@@ -1688,6 +1746,7 @@ dependencies = [
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"hyper",
|
||||
"hyper-rustls",
|
||||
"hyper-util",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
@@ -1696,19 +1755,40 @@ dependencies = [
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"quinn",
|
||||
"rustls",
|
||||
"rustls-pemfile",
|
||||
"rustls-pki-types",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"sync_wrapper 1.0.1",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"webpki-roots",
|
||||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"getrandom",
|
||||
"libc",
|
||||
"spin",
|
||||
"untrusted",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rpassword"
|
||||
version = "7.3.1"
|
||||
@@ -1736,6 +1816,12 @@ version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
@@ -1745,6 +1831,47 @@ dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pemfile"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pki-types"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0"
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.102.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.17"
|
||||
@@ -2107,34 +2234,44 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.38.0"
|
||||
version = "1.40.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
|
||||
checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"parking_lot",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.3.0"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
|
||||
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
|
||||
dependencies = [
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.11"
|
||||
@@ -2349,6 +2486,12 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.2"
|
||||
@@ -2469,6 +2612,15 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.26.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd"
|
||||
dependencies = [
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
||||
@@ -9,4 +9,5 @@ clap = { version = "4.5.16", features = ["derive"] }
|
||||
pubky = { version = "0.1.0", path = "../../../pubky" }
|
||||
pubky-common = { version = "0.1.0", path = "../../../pubky-common" }
|
||||
rpassword = "7.3.1"
|
||||
tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread"] }
|
||||
url = "2.5.2"
|
||||
|
||||
@@ -1,40 +1,79 @@
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use pubky::PubkyClient;
|
||||
use pubky_common::{auth::AuthToken, capabilities::Capability, crypto::PublicKey};
|
||||
use std::path::PathBuf;
|
||||
use url::Url;
|
||||
|
||||
/// local testnet HOMESERVER
|
||||
const HOMESERVER: &str = "8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo";
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
struct Cli {
|
||||
/// Path to a recovery_file of the Pubky you want to sign in with
|
||||
recovery_file: PathBuf,
|
||||
|
||||
/// Pubky Auth url
|
||||
url: Url,
|
||||
|
||||
/// Path to a recovery_file of the Pubky you want to sign in with
|
||||
// #[arg(short, long, value_name = "FILE")]
|
||||
recovery_file: PathBuf,
|
||||
// /// Mutable data public key.
|
||||
// public_key: String,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
let url = cli.url;
|
||||
dbg!(url);
|
||||
|
||||
let mut required_capabilities = vec![];
|
||||
let mut relay = "".to_string();
|
||||
let client_secret: [u8; 32];
|
||||
|
||||
for (name, value) in url.query_pairs() {
|
||||
if name == "relay" {
|
||||
relay = value.to_string();
|
||||
}
|
||||
if name == "secret" {
|
||||
// client_secret = value.to_string();
|
||||
}
|
||||
if name == "capabilities" {
|
||||
println!("\nRequired Capabilities:");
|
||||
|
||||
for cap_str in value.split(',') {
|
||||
if let Ok(cap) = Capability::try_from(cap_str) {
|
||||
println!(" {} : {:?}", cap.resource, cap.abilities);
|
||||
required_capabilities.push(cap)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let recovery_file = std::fs::read(&cli.recovery_file)?;
|
||||
println!("Successfully opened recovery file");
|
||||
// println!("\nSuccessfully opened recovery file");
|
||||
|
||||
// // println!("Enter Pubky Auth URL to start the consent form:");
|
||||
// // let pubky_auth_url = rl.readline("> ")?;
|
||||
// // dbg!(pubky_auth_url);
|
||||
// === Consent form ===
|
||||
|
||||
println!("Enter your recovery_file's passphrase to confirm:");
|
||||
println!("\nEnter your recovery_file's passphrase to confirm:");
|
||||
let passphrase = rpassword::read_password()?;
|
||||
|
||||
let keypair = pubky_common::recovery_file::decrypt_recovery_file(&recovery_file, &passphrase)?;
|
||||
|
||||
println!("Successfully decrypted recovery file...");
|
||||
|
||||
let client = PubkyClient::testnet();
|
||||
|
||||
// For the purposes of this demo, we need to make sure
|
||||
// the user has an account on the local homeserver.
|
||||
if client.signin(&keypair).await.is_err() {
|
||||
client
|
||||
.signup(&keypair, &PublicKey::try_from(HOMESERVER).unwrap())
|
||||
.await?;
|
||||
};
|
||||
|
||||
client
|
||||
.authorize(&keypair, required_capabilities, [0; 32], &relay)
|
||||
.await?;
|
||||
|
||||
println!("Sending AuthToken to the client...");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -69,6 +69,13 @@ impl PubkyClient {
|
||||
PubkyClientBuilder::default()
|
||||
}
|
||||
|
||||
pub fn testnet() -> Self {
|
||||
Self::test(&Testnet {
|
||||
bootstrap: vec!["localhost:6881".to_string()],
|
||||
nodes: vec![],
|
||||
})
|
||||
}
|
||||
|
||||
pub fn test(testnet: &Testnet) -> Self {
|
||||
let pkarr = PkarrClient::builder()
|
||||
.dht_settings(DhtSettings {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use reqwest::{Method, StatusCode};
|
||||
|
||||
use pkarr::{Keypair, PublicKey};
|
||||
use pubky_common::{auth::AuthToken, capabilities::Capability, session::Session};
|
||||
use pubky_common::{auth::AuthToken, capabilities::Capability, crypto::encrypt, session::Session};
|
||||
use url::Url;
|
||||
|
||||
use crate::{error::Result, PubkyClient};
|
||||
|
||||
@@ -20,13 +21,13 @@ impl PubkyClient {
|
||||
let homeserver = homeserver.to_string();
|
||||
|
||||
let Endpoint {
|
||||
public_key: audience,
|
||||
public_key: server,
|
||||
mut url,
|
||||
} = self.resolve_endpoint(&homeserver).await?;
|
||||
|
||||
url.set_path("/signup");
|
||||
|
||||
let body = AuthToken::sign(keypair, &audience, vec![Capability::root()]).serialize();
|
||||
let body = AuthToken::sign(keypair, &server, vec![Capability::root()]).serialize();
|
||||
|
||||
let response = self
|
||||
.request(Method::POST, url.clone())
|
||||
@@ -83,13 +84,13 @@ impl PubkyClient {
|
||||
let pubky = keypair.public_key();
|
||||
|
||||
let Endpoint {
|
||||
public_key: audience,
|
||||
public_key: homeserver,
|
||||
mut url,
|
||||
} = self.resolve_pubky_homeserver(&pubky).await?;
|
||||
|
||||
url.set_path("/session");
|
||||
|
||||
let body = AuthToken::sign(keypair, &audience, vec![Capability::root()]).serialize();
|
||||
let body = AuthToken::sign(keypair, &homeserver, vec![Capability::root()]).serialize();
|
||||
|
||||
let response = self.request(Method::POST, url).body(body).send().await?;
|
||||
|
||||
@@ -97,6 +98,39 @@ impl PubkyClient {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn authorize(
|
||||
&self,
|
||||
keypair: &Keypair,
|
||||
capabilities: Vec<Capability>,
|
||||
client_secret: [u8; 32],
|
||||
relay: &str,
|
||||
) -> Result<()> {
|
||||
let pubky = keypair.public_key();
|
||||
let Endpoint {
|
||||
public_key: homeserver,
|
||||
..
|
||||
} = self.resolve_pubky_homeserver(&pubky).await?;
|
||||
|
||||
let token = AuthToken::sign(keypair, &homeserver, capabilities);
|
||||
|
||||
let encrypted_token = encrypt(&token.serialize(), &client_secret)?;
|
||||
|
||||
let mut callback = Url::parse(relay)?;
|
||||
let mut path_segments = callback.path_segments_mut().unwrap();
|
||||
path_segments.push("8Y69yafXgEMafLJKoJ_Ht5zPOVMWuZx_HfKY03U4MTI");
|
||||
|
||||
drop(path_segments);
|
||||
|
||||
dbg!(callback.to_string());
|
||||
|
||||
self.request(Method::POST, callback)
|
||||
.body(encrypted_token)
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user