use std::time::Duration;
use serde::{Deserialize, Serialize};
use crate::config::OAuthConfig;
use crate::error::{OAuthError, Result};
pub mod authorization_code;
pub mod client_credentials;
pub mod refresh_token;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum GrantType {
ClientCredentials,
AuthorizationCode,
RefreshToken,
}
#[derive(Debug, Clone, Deserialize)]
pub struct TokenRequest {
pub grant_type: GrantType,
#[serde(default)]
pub client_id: Option<String>,
#[serde(default)]
pub client_secret: Option<String>,
#[serde(default)]
pub scope: Option<String>,
#[serde(default)]
pub code: Option<String>,
#[serde(default)]
pub redirect_uri: Option<String>,
#[serde(default)]
pub code_verifier: Option<String>,
#[serde(default)]
pub refresh_token: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
pub struct TokenResponse {
pub access_token: String,
pub token_type: String,
pub expires_in: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub refresh_token: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scope: Option<String>,
}
impl TokenResponse {
pub fn bearer(
access_token: String,
ttl: Duration,
refresh_token: Option<String>,
scope: Option<String>,
) -> Self {
Self {
access_token,
token_type: "Bearer".into(),
expires_in: ttl.as_secs(),
refresh_token,
scope,
}
}
}
pub fn issue_token(config: &OAuthConfig, request: TokenRequest) -> Result<TokenResponse> {
match request.grant_type {
GrantType::ClientCredentials => client_credentials::issue_token(config, &request),
GrantType::AuthorizationCode => authorization_code::issue_token(config, &request),
GrantType::RefreshToken => refresh_token::issue_token(config, &request),
}
}