Add OAuth module with token management functionality

This commit is contained in:
Palash Tyagi 2024-11-02 03:06:12 +00:00
parent 3c5d4aa941
commit 8bda1da6fe
2 changed files with 111 additions and 0 deletions

1
src/lib.rs Normal file
View File

@ -0,0 +1 @@
pub mod oauth;

110
src/oauth.rs Normal file
View File

@ -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<String>,
expires_at: Option<SystemTime>, // 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(&params).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<HashMap<String, String>, 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();
// }