Add idnot logic
This commit is contained in:
parent
e7a685056c
commit
febd8c963d
79
src/idnot.rs
Normal file
79
src/idnot.rs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
use reqwest::{Client, Url};
|
||||||
|
use jwt_simple::prelude::*;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
use crate::Config;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct IdNotVariables {
|
||||||
|
pub idnot_client_id: String,
|
||||||
|
pub idnot_client_secret: String,
|
||||||
|
pub idnot_redirect_uri: String,
|
||||||
|
pub idnot_base_url: String,
|
||||||
|
pub idnot_connexion_url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct IdNotToken {
|
||||||
|
pub access_token: String,
|
||||||
|
pub expires_in: String,
|
||||||
|
pub id_token: String,
|
||||||
|
pub token_type: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct IdNotJwtPayload {
|
||||||
|
pub sub: String,
|
||||||
|
pub profile_idn: String,
|
||||||
|
pub entity_idn: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_id_not_token(
|
||||||
|
code: &str,
|
||||||
|
vars: &IdNotVariables,
|
||||||
|
// ) -> Result<IdNotJwtPayload, Box<dyn Error>> {
|
||||||
|
) -> Result<(), anyhow::Error> {
|
||||||
|
// Build the full URL
|
||||||
|
let url = Url::parse(&format!("{}{}", vars.idnot_base_url, vars.idnot_connexion_url))?;
|
||||||
|
|
||||||
|
let params = [
|
||||||
|
("client_id", vars.idnot_client_id.as_str()),
|
||||||
|
("client_secret", vars.idnot_client_secret.as_str()),
|
||||||
|
("redirect_uri", vars.idnot_redirect_uri.as_str()),
|
||||||
|
("code", &code),
|
||||||
|
("grant_type", "authorization_code"),
|
||||||
|
];
|
||||||
|
|
||||||
|
let client = Client::new();
|
||||||
|
let req = client
|
||||||
|
.post(url.as_str())
|
||||||
|
.query(¶ms)
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
log::debug!("{:#?}", req);
|
||||||
|
|
||||||
|
// let resp = client.execute(req).await?;
|
||||||
|
|
||||||
|
// log::debug!("{:#?}", resp);
|
||||||
|
|
||||||
|
// If status != 200, print the body as error and bail
|
||||||
|
// if !resp.status().is_success() {
|
||||||
|
// let err_text = resp.text().await.unwrap_or_else(|_| "<no body>".into());
|
||||||
|
// log::error!("Error response from {}: {}", url, err_text);
|
||||||
|
// return Err(anyhow::Error::msg("Non-200 response"));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Parse JSON into our token struct
|
||||||
|
// let decoded_token: IdNotToken = resp.json().await?;
|
||||||
|
|
||||||
|
// log::debug!("{:?}", decoded_token);
|
||||||
|
|
||||||
|
// let token_data: IdNotJwtPayload = // &decoded_token.id_token)
|
||||||
|
// .map_err(|e| {
|
||||||
|
// eprintln!("JWT decode error: {}", e);
|
||||||
|
// "Failed to decode id_token"
|
||||||
|
// })?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
115
src/main.rs
115
src/main.rs
@ -16,6 +16,7 @@ use bitcoincore_rpc::{
|
|||||||
};
|
};
|
||||||
use commit::{lock_members, MEMBERLIST};
|
use commit::{lock_members, MEMBERLIST};
|
||||||
use futures_util::{future, pin_mut, stream::TryStreamExt, FutureExt, StreamExt};
|
use futures_util::{future, pin_mut, stream::TryStreamExt, FutureExt, StreamExt};
|
||||||
|
use idnot::{get_id_not_token, IdNotVariables};
|
||||||
use log::{debug, error, warn};
|
use log::{debug, error, warn};
|
||||||
use message::{broadcast_message, process_message, BroadcastType, MessageCache, MESSAGECACHE};
|
use message::{broadcast_message, process_message, BroadcastType, MessageCache, MESSAGECACHE};
|
||||||
use scan::{check_transaction_alone, compute_partial_tweak_to_transaction};
|
use scan::{check_transaction_alone, compute_partial_tweak_to_transaction};
|
||||||
@ -46,8 +47,8 @@ use sdk_common::{
|
|||||||
MutexExt,
|
MutexExt,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde_json::Value;
|
use serde_json::{json, Value};
|
||||||
use tokio::net::{TcpListener, TcpStream};
|
use tokio::{io::{AsyncReadExt, AsyncWriteExt}, net::{TcpListener, TcpStream}};
|
||||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedSender};
|
use tokio::sync::mpsc::{unbounded_channel, UnboundedSender};
|
||||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||||
use tokio_tungstenite::tungstenite::Message;
|
use tokio_tungstenite::tungstenite::Message;
|
||||||
@ -62,6 +63,8 @@ mod electrumclient;
|
|||||||
mod faucet;
|
mod faucet;
|
||||||
mod message;
|
mod message;
|
||||||
mod scan;
|
mod scan;
|
||||||
|
mod commit;
|
||||||
|
mod idnot;
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -165,11 +168,79 @@ fn handle_new_tx_request(new_tx_msg: &NewTxMessage) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_connection(
|
async fn handle_http_connection(mut raw_stream: TcpStream, addr: SocketAddr, vars: IdNotVariables) {
|
||||||
raw_stream: TcpStream,
|
debug!("Incoming HTTP connection from: {}", addr);
|
||||||
addr: SocketAddr,
|
|
||||||
our_sp_address: SilentPaymentAddress,
|
// 1) Read up to 4KiB for the request headers
|
||||||
) {
|
let mut buf = vec![0u8; 4096];
|
||||||
|
let n = match raw_stream.read(&mut buf).await {
|
||||||
|
Ok(0) => return, // client closed connection
|
||||||
|
Ok(n) => n,
|
||||||
|
Err(err) => {
|
||||||
|
debug!("Failed to read from socket: {}", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 2) Convert to &str
|
||||||
|
let req = match std::str::from_utf8(&buf[..n]) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(err) => {
|
||||||
|
debug!("Invalid UTF-8 request: {}", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 3) Parse request-line: "POST /api/v1/idnot/user?code=XYZ HTTP/1.1"
|
||||||
|
let mut lines = req.split("\r\n");
|
||||||
|
let request_line = match lines.next() {
|
||||||
|
Some(l) => l,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
let mut parts = request_line.split_whitespace();
|
||||||
|
let method = parts.next().unwrap_or("");
|
||||||
|
let uri = parts.next().unwrap_or("");
|
||||||
|
|
||||||
|
// 4) Only handle POST /api/v1/idnot/user
|
||||||
|
if method == "POST" && uri.starts_with("/api/v1/idnot/user/") {
|
||||||
|
let code_opt = uri
|
||||||
|
.split('/')
|
||||||
|
.last()
|
||||||
|
.filter(|&code| !code.is_empty());
|
||||||
|
|
||||||
|
if let Some(code) = code_opt {
|
||||||
|
if let Ok(()) = get_id_not_token(code, &vars).await {
|
||||||
|
let response =
|
||||||
|
"HTTP/1.1 200 OK\r\n\
|
||||||
|
Content-Type: application/json\r\n\
|
||||||
|
Content-Length: 0\r\n\r\n";
|
||||||
|
let _ = raw_stream.write_all(response.as_bytes()).await;
|
||||||
|
} else {
|
||||||
|
log::error!("Failed to get token");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Missing code → 400 Bad Request
|
||||||
|
let body = json!({ "error": "code is required" }).to_string();
|
||||||
|
let response = format!(
|
||||||
|
"HTTP/1.1 400 Bad Request\r\n\
|
||||||
|
Content-Type: application/json\r\n\
|
||||||
|
Content-Length: {}\r\n\r\n\
|
||||||
|
{}",
|
||||||
|
body.len(),
|
||||||
|
body
|
||||||
|
);
|
||||||
|
let _ = raw_stream.write_all(response.as_bytes()).await;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5) Fallback: 404 Not Found
|
||||||
|
let response = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
|
||||||
|
let _ = raw_stream.write_all(response.as_bytes()).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_ws_connection(raw_stream: TcpStream, addr: SocketAddr, our_sp_address: SilentPaymentAddress) {
|
||||||
debug!("Incoming TCP connection from: {}", addr);
|
debug!("Incoming TCP connection from: {}", addr);
|
||||||
|
|
||||||
let peers = PEERMAP.get().expect("Peer Map not initialized");
|
let peers = PEERMAP.get().expect("Peer Map not initialized");
|
||||||
@ -474,15 +545,39 @@ async fn main() -> Result<()> {
|
|||||||
// Subscribe to Bitcoin Core
|
// Subscribe to Bitcoin Core
|
||||||
tokio::spawn(handle_zmq(config.zmq_url, config.electrum_url));
|
tokio::spawn(handle_zmq(config.zmq_url, config.electrum_url));
|
||||||
|
|
||||||
|
// Create the TcpListener for http request
|
||||||
|
let try_socket = TcpListener::bind(config.http_url).await;
|
||||||
|
let http_listener = try_socket.expect("Failed to bind");
|
||||||
|
|
||||||
|
if config.idnot_client_id.is_some() && config.idnot_client_secret.is_some() && config.idnot_redirect_uri.is_some() {
|
||||||
|
let id_not_vars = IdNotVariables {
|
||||||
|
idnot_base_url: "https://qual-connexion.idnot.fr".to_owned(),
|
||||||
|
idnot_client_id: config.idnot_client_id.unwrap(),
|
||||||
|
idnot_client_secret: config.idnot_client_secret.unwrap(),
|
||||||
|
idnot_connexion_url: "/IdPOAuth2/token/idnot_idp_v1".to_owned(),
|
||||||
|
idnot_redirect_uri: config.idnot_redirect_uri.unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
log::debug!("{:?}", id_not_vars);
|
||||||
|
|
||||||
|
// Spawn a task to handle HTTP connections
|
||||||
|
tokio::spawn(async move {
|
||||||
|
while let Ok((stream, addr)) = http_listener.accept().await {
|
||||||
|
tokio::spawn(handle_http_connection(stream, addr, id_not_vars.clone()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Create the event loop and TCP listener we'll accept connections on.
|
// Create the event loop and TCP listener we'll accept connections on.
|
||||||
let try_socket = TcpListener::bind(config.ws_url).await;
|
let try_socket = TcpListener::bind(config.ws_url).await;
|
||||||
let listener = try_socket.expect("Failed to bind");
|
let ws_listener = try_socket.expect("Failed to bind");
|
||||||
|
|
||||||
tokio::spawn(MessageCache::clean_up());
|
tokio::spawn(MessageCache::clean_up());
|
||||||
|
|
||||||
// Let's spawn the handling of each connection in a separate task.
|
// Let's spawn the handling of each connection in a separate task.
|
||||||
while let Ok((stream, addr)) = listener.accept().await {
|
while let Ok((stream, addr)) = ws_listener.accept().await {
|
||||||
tokio::spawn(handle_connection(stream, addr, our_sp_address));
|
tokio::spawn(handle_ws_connection(stream, addr, our_sp_address));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user