ws-auth 0.0.3

A library to help build authentication services and client libraries for web services.
Documentation
use chrono::{DateTime, Utc};
use uuid::Uuid;

#[derive(Debug, Serialize, Deserialize)]
pub enum GrantType {
    #[serde(rename = "refresh_token")]
    RefreshToken,

    #[serde(rename = "authorization_code")]
    AuthorizationCode,
}

#[derive(Debug, Serialize, Deserialize)]
pub enum ErrorCode {
    #[serde(rename = "invalid_request")]
    InvalidRequest,

    #[serde(rename = "invalid_grant")]
    InvalidGrant,

    #[serde(rename = "unauthorized_client")]
    UnauthorizedClient,

    #[serde(rename = "invalid_client")]
    InvalidClient,

    #[serde(rename = "unsupported_grant_type")]
    UnsupportedGrantType,

    #[serde(rename = "invalid_resource")]
    InvalidResource,

    #[serde(rename = "interaction_required")]
    InteractionRequired,

    #[serde(rename = "temporarily_unavailable")]
    TemporarilyUnavailable,

    #[serde(rename = "consent_required")]
    ConsentRequired,

    #[serde(rename = "invalid_scope")]
    InvalidScope,
}

// https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow
#[derive(Debug, Serialize, Deserialize)]
pub struct TokenRequest {
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub client_id: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub client_secret: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub client_assertion_type: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub client_assertion: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub scope: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub code: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub redirect_uri: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub grant_type: Option<GrantType>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub code_verifier: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TokenErrorResponse {
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub error: Option<ErrorCode>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub error_description: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub error_codes: Option<Vec<u64>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    timestamp: Option<DateTime<Utc>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    trace_id: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    correlation_id: Option<String>,
}

impl TokenErrorResponse {
    pub fn new() -> TokenErrorResponse {
        let trace_id = Uuid::new_v4();
        let correlation_id = Uuid::new_v4();

        return TokenErrorResponse {
            error: Option::None,
            error_description: Option::None,
            error_codes: Option::None,
            timestamp: Some(Utc::now()),
            trace_id: Some(trace_id.to_string()),
            correlation_id: Some(correlation_id.to_string()),
        };
    }

    pub fn new_with_tracking(trace_id: String, correlation_id: String) -> TokenErrorResponse {
        return TokenErrorResponse {
            error: Option::None,
            error_description: Option::None,
            error_codes: Option::None,
            timestamp: Some(Utc::now()),
            trace_id: Some(trace_id.to_owned()),
            correlation_id: Some(correlation_id.to_owned()),
        };
    }
}