Skip to main content

genius_core_client/auth/
utils.rs

1use crate::types::error::{ErrorCode, HstpError};
2
3#[allow(dead_code)]
4#[derive(Debug)]
5pub struct TokenResponse {
6    pub access_token: String,
7}
8
9#[allow(dead_code)]
10pub async fn retrieve_auth_token_client_credentials(
11    client_id: String,
12    client_secret: String,
13    token_url: String,
14    audience: Option<String>,
15    scope: Option<String>,
16) -> Result<TokenResponse, HstpError> {
17    use base64::{
18        alphabet,
19        engine::{GeneralPurpose, GeneralPurposeConfig},
20        Engine,
21    };
22
23    // Create the authorization header
24    let encoded_client_id = urlencoding::encode(&client_id);
25    let encoded_client_secret = urlencoding::encode(&client_secret);
26    let header = format!("{}:{}", encoded_client_id, encoded_client_secret);
27    let header_ascii_bytes = header.as_bytes();
28
29    let encoded_header = GeneralPurpose::new(&alphabet::STANDARD, GeneralPurposeConfig::default())
30        .encode(header_ascii_bytes);
31
32    let mut headers = reqwest::header::HeaderMap::new();
33    headers.insert(
34        reqwest::header::AUTHORIZATION,
35        reqwest::header::HeaderValue::from_str(&format!("Basic {}", encoded_header))
36            .map_err(HstpError::from_error)?,
37    );
38    headers.insert(
39        reqwest::header::CONTENT_TYPE,
40        reqwest::header::HeaderValue::from_static("application/x-www-form-urlencoded"),
41    );
42
43    // Build the request body
44    let body = "grant_type=client_credentials".to_string();
45    let body = if let Some(audience) = &audience {
46        format!("{}&audience={}", body, audience)
47    } else {
48        body
49    };
50    let body = if let Some(scope) = &scope {
51        format!("{}&scope={}", body, scope)
52    } else {
53        body
54    };
55
56    // Send the request
57    let client = reqwest::Client::new();
58    let response = client
59        .post(token_url.to_string())
60        .headers(headers)
61        .body(body)
62        .send()
63        .await
64        .map_err(HstpError::from_error)?;
65
66    // Check the HTTP status code before parsing the response
67    if response.status().is_success() {
68        let response_body = response.text().await.map_err(HstpError::from_error)?;
69        let response_body: serde_json::Value = serde_json::from_str(&response_body)?;
70        let access_token = response_body["access_token"].as_str().ok_or_else(|| {
71            HstpError::new(
72                ErrorCode::None,
73                "Failed to retrieve access token".to_string(),
74                "".into(),
75            )
76        })?;
77
78        Ok(TokenResponse {
79            access_token: access_token.to_string(),
80        })
81    } else {
82        let status = response.status().to_string(); // Store status before moving response
83        let error_body = response.text().await.unwrap_or_else(|_| "".to_string());
84        Err(HstpError::new(
85            ErrorCode::UnhandledError,
86            format!("Error response from server: {}", error_body),
87            status,
88        ))
89    }
90}