diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..f3982a9 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +pub mod oauth; diff --git a/src/oauth.rs b/src/oauth.rs new file mode 100644 index 0000000..00639c2 --- /dev/null +++ b/src/oauth.rs @@ -0,0 +1,110 @@ +use reqwest::blocking::Client; +use reqwest::Error; +use serde_json::Value; +use std::collections::HashMap; +use std::env; +use std::time::{Duration, SystemTime}; + +pub const OAUTH_TOKEN_URL: &str = "https://authe.jpmchase.com/as/token.oauth2"; + +struct OAuthClient { + client_id: String, + client_secret: String, + token_url: String, + access_token: Option, + expires_at: Option, // Stores the token's expiration time +} + +impl OAuthClient { + fn new(client_id: String, client_secret: String) -> Self { + OAuthClient { + client_id, + client_secret, + token_url: OAUTH_TOKEN_URL.to_string(), + access_token: None, + expires_at: None, // Initially None until a token is fetched + } + } + + fn fetch_token(&mut self) -> Result<(), Error> { + let client = Client::new(); + + // Set up the form parameters for the request + let mut params = HashMap::new(); + params.insert("grant_type", "client_credentials"); + params.insert("client_id", &self.client_id); + params.insert("client_secret", &self.client_secret); + + // Make the POST request to retrieve the token + let response = client.post(&self.token_url).form(¶ms).send()?; + + // Check if the request was successful + if response.status().is_success() { + // Parse the JSON response to get the access token and expiration time + let json: Value = response.json()?; + if let Some(token) = json["access_token"].as_str() { + self.access_token = Some(token.to_string()); + println!("Access token retrieved: {}", token); + + // Set the expiration time + if let Some(expires_in) = json["expires_in"].as_u64() { + self.expires_at = Some(SystemTime::now() + Duration::from_secs(expires_in)); + } else { + self.expires_at = Some(SystemTime::now() + Duration::from_secs(3600)); + // Default to 1 hour if `expires_in` is missing + } + } else { + eprintln!("Failed to retrieve access token from response."); + } + } else { + eprintln!("Token request failed with status: {}", response.status()); + } + + Ok(()) + } + + // Method to check if the token has expired + fn is_token_expired(&self) -> bool { + match self.expires_at { + Some(expiration) => SystemTime::now() >= expiration, + None => true, // If there's no expiration set, assume it's expired + } + } + + // Method to get headers with authorization, renewing the token if expired + fn get_headers(&mut self) -> Result, Error> { + // Check if the token is expired; if it is, fetch a new one + if self.is_token_expired() { + println!("Token has expired. Fetching a new token..."); + self.fetch_token()?; + } + + // Construct the headers + let mut headers = HashMap::new(); + if let Some(token) = &self.access_token { + headers.insert("Authorization".to_string(), format!("Bearer {}", token)); + } else { + eprintln!("No access token available."); + } + + Ok(headers) + } +} + +// fn retrive_oauth_headers() -> Result<(), Error> { +// // Retrieve client_id and client_secret from environment variables +// let client_id = env::var("DQ_CLIENT_ID").expect("CLIENT_ID not set in environment"); +// let client_secret = env::var("DQ_CLIENT_SECRET").expect("CLIENT_SECRET not set in environment"); +// println!("Client ID: {}", client_id); +// let mut oauth_client = OAuthClient::new(client_id, client_secret); +// println!("OAuth client created."); +// print!("Fetching token..."); +// // Fetch headers with authorization, automatically refreshing token if needed +// let headers = oauth_client.get_headers()?; +// println!("Headers: {:?}", headers); +// Ok(()) +// } + +// fn main() { +// retrive_oauth_headers().unwrap(); +// }