#![cfg(not(doctest))]
use core::fmt;
use reqwest::{Client, Url};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::{collections::HashMap, fmt::Display};
pub struct AuthClient {
pub(crate) client: Client,
pub(crate) project_url: String,
pub(crate) api_key: String,
pub(crate) jwt_secret: String,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Session {
pub provider_token: Option<String>,
pub provider_refresh_token: Option<String>,
pub access_token: String,
pub token_type: String,
pub expires_in: i64,
pub expires_at: u64,
pub refresh_token: String,
pub user: User,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct User {
pub id: String,
pub aud: String,
pub role: String,
pub email: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub invited_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub confirmation_sent_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub email_confirmed_at: Option<String>,
pub phone: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub phone_confirmed_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub confirmed_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub recovery_sent_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_sign_in_at: Option<String>,
pub app_metadata: AppMetadata,
pub user_metadata: UserMetadata,
pub identities: Vec<Identity>,
pub created_at: String,
pub updated_at: String,
pub is_anonymous: bool,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Default)]
pub struct AppMetadata {
#[serde(skip_serializing_if = "Option::is_none")]
pub provider: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub providers: Option<Vec<String>>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Default)]
pub struct UserMetadata {
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub email_verified: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub phone_verified: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sub: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct IdTokenCredentials {
pub provider: Provider,
pub token: String,
pub access_token: Option<String>,
pub nonce: Option<String>,
pub gotrue_meta_security: Option<GotrueMetaSecurity>,
}
#[derive(Debug, Deserialize, Serialize, PartialEq, Default)]
pub struct LoginWithOAuthOptions {
pub query_params: Option<HashMap<String, String>>,
pub redirect_to: Option<String>,
pub scopes: Option<String>,
pub skip_brower_redirect: Option<bool>,
}
#[derive(Debug, PartialEq)]
pub struct OAuthResponse {
pub url: Url,
pub provider: Provider,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct GotrueMetaSecurity {
captcha_token: Option<String>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Identity {
pub identity_id: String,
pub id: String,
pub user_id: String,
pub identity_data: IdentityData,
pub provider: String,
pub last_sign_in_at: String,
pub created_at: String,
pub updated_at: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct IdentityData {
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
pub email_verified: bool,
pub phone_verified: bool,
pub sub: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum LoginOptions {
Email(String),
Phone(String),
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub(crate) struct LoginWithEmailAndPasswordPayload<'a> {
pub(crate) email: &'a str,
pub(crate) password: &'a str,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub(crate) struct LoginWithPhoneAndPasswordPayload<'a> {
pub(crate) phone: &'a str,
pub(crate) password: &'a str,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub(crate) struct SignUpWithEmailAndPasswordPayload<'a> {
pub(crate) email: &'a str,
pub(crate) password: &'a str,
pub(crate) options: Option<SignUpWithPasswordOptions>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub(crate) struct SignUpWithPhoneAndPasswordPayload<'a> {
pub(crate) phone: &'a str,
pub(crate) password: &'a str,
pub(crate) options: Option<SignUpWithPasswordOptions>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub(crate) struct LoginAnonymouslyPayload {
pub(crate) options: Option<SignUpWithPasswordOptions>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SignUpWithPasswordOptions {
pub email_redirect_to: Option<String>,
pub data: Option<Value>,
pub captcha_token: Option<String>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub(crate) struct RequestMagicLinkPayload<'a> {
pub(crate) email: &'a str,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UpdatedUser {
pub email: Option<String>,
pub password: Option<String>,
pub data: Option<serde_json::Value>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub(crate) struct SendSMSOtpPayload<'a> {
pub phone: &'a str,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct OTPResponse {
#[serde(skip_serializing_if = "Option::is_none")]
pub message_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum VerifyOtpParams {
Mobile(VerifyMobileOtpParams),
Email(VerifyEmailOtpParams),
TokenHash(VerifyTokenHashParams),
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct VerifyMobileOtpParams {
pub phone: String,
pub token: String,
#[serde(rename = "type")]
pub otp_type: OtpType,
#[serde(skip_serializing_if = "Option::is_none")]
pub options: Option<VerifyOtpOptions>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct VerifyEmailOtpParams {
pub token: String,
#[serde(rename = "type")]
pub otp_type: OtpType,
#[serde(skip_serializing_if = "Option::is_none")]
pub options: Option<VerifyOtpOptions>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct VerifyTokenHashParams {
pub token_hash: String,
#[serde(rename = "type")]
pub otp_type: OtpType,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum OtpType {
#[default]
Signup,
EmailChange,
Sms,
PhoneChange,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct VerifyOtpOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub redirect_to: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Default)]
pub(crate) struct LoginWithEmailOtpPayload<'a> {
pub email: &'a str,
pub options: Option<LoginEmailOtpParams>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Default)]
pub struct LoginWithEmailOtp {
pub email: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub options: Option<LoginEmailOtpParams>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct LoginEmailOtpParams {
pub captcha_token: Option<String>,
pub data: Option<serde_json::Value>,
pub email_redirect_to: Option<String>,
pub should_create_user: Option<bool>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct LoginMobileOtpParams {
pub captcha_token: Option<String>,
pub data: Option<serde_json::Value>,
pub channel: Option<Channel>,
pub should_create_user: Option<bool>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub(crate) struct RefreshSessionPayload<'a> {
pub refresh_token: &'a str,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub(crate) struct ResetPasswordForEmailPayload {
pub email: String,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ResendParams {
#[serde(rename = "type")]
pub otp_type: OtpType,
pub email: String,
pub options: Option<DesktopResendOptions>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct InviteParams {
pub email: String,
pub data: Option<Value>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct DesktopResendOptions {
pub email_redirect_to: Option<String>,
pub captcha_token: Option<String>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct MobileResendParams {
#[serde(rename = "type")]
pub otp_type: OtpType,
pub phone: String,
pub options: Option<MobileResendOptions>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct MobileResendOptions {
captcha_token: Option<String>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum Channel {
#[default]
Sms,
Whatsapp,
}
impl Display for Channel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match *self {
Channel::Sms => write!(f, "sms"),
Channel::Whatsapp => write!(f, "whatsapp"),
}
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct AuthServerHealth {
pub version: String,
pub name: String,
pub description: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AuthServerSettings {
pub external: External,
pub disable_signup: bool,
pub mailer_autoconfirm: bool,
pub phone_autoconfirm: bool,
pub sms_provider: String,
pub saml_enabled: bool,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct External {
pub anonymous_users: bool,
pub apple: bool,
pub azure: bool,
pub bitbucket: bool,
pub discord: bool,
pub facebook: bool,
pub figma: bool,
pub fly: bool,
pub github: bool,
pub gitlab: bool,
pub google: bool,
pub keycloak: bool,
pub kakao: bool,
pub linkedin: bool,
pub linkedin_oidc: bool,
pub notion: bool,
pub spotify: bool,
pub slack: bool,
pub slack_oidc: bool,
pub workos: bool,
pub twitch: bool,
pub twitter: bool,
pub email: bool,
pub phone: bool,
pub zoom: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Provider {
Apple,
Azure,
Bitbucket,
Discord,
Facebook,
Figma,
Fly,
Github,
Gitlab,
Google,
Kakao,
Keycloak,
Linkedin,
LinkedinOidc,
Notion,
Slack,
SlackOidc,
Spotify,
Twitch,
Twitter,
Workos,
Zoom,
}
impl Display for Provider {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
match *self {
Provider::Apple => write!(f, "apple"),
Provider::Azure => write!(f, "azure"),
Provider::Bitbucket => write!(f, "bitbucket"),
Provider::Discord => write!(f, "discord"),
Provider::Facebook => write!(f, "facebook"),
Provider::Figma => write!(f, "figma"),
Provider::Fly => write!(f, "fly"),
Provider::Github => write!(f, "github"),
Provider::Gitlab => write!(f, "gitlab"),
Provider::Google => write!(f, "google"),
Provider::Kakao => write!(f, "kakao"),
Provider::Keycloak => write!(f, "keycloak"),
Provider::Linkedin => write!(f, "linkedin"),
Provider::LinkedinOidc => write!(f, "linkedin_oidc"),
Provider::Notion => write!(f, "notion"),
Provider::Slack => write!(f, "slack"),
Provider::SlackOidc => write!(f, "slack_oidc"),
Provider::Spotify => write!(f, "spotify"),
Provider::Twitch => write!(f, "twitch"),
Provider::Twitter => write!(f, "twitter"),
Provider::Workos => write!(f, "workos"),
Provider::Zoom => write!(f, "zoom"),
}
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum LogoutScope {
#[default]
Global,
Local,
Others,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct LoginWithSSO {
#[serde(skip_serializing_if = "Option::is_none")]
pub provider_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub domain: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub options: Option<SSOLoginOptions>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct SSOLoginOptions {
#[serde(skip_serializing_if = "Option::is_none")]
captcha_token: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
redirect_to: Option<String>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct SSOSuccess {
pub url: String,
pub status: u16,
pub headers: Headers,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Headers {
pub date: String,
#[serde(rename = "content-type")]
pub content_type: String,
#[serde(rename = "transfer-encoding")]
pub transfer_encoding: String,
pub connection: String,
pub server: String,
pub vary: String,
#[serde(rename = "x-okta-request-id")]
pub x_okta_request_id: String,
#[serde(rename = "x-xss-protection")]
pub x_xss_protection: String,
pub p3p: String,
#[serde(rename = "set-cookie")]
pub set_cookie: Vec<String>,
#[serde(rename = "content-security-policy-report-only")]
pub content_security_policy_report_only: String,
#[serde(rename = "content-security-policy")]
pub content_security_policy: String,
#[serde(rename = "x-rate-limit-limit")]
pub x_rate_limit_limit: String,
#[serde(rename = "x-rate-limit-remaining")]
pub x_rate_limit_remaining: String,
#[serde(rename = "x-rate-limit-reset")]
pub x_rate_limit_reset: String,
#[serde(rename = "referrer-policy")]
pub referrer_policy: String,
#[serde(rename = "accept-ch")]
pub accept_ch: String,
#[serde(rename = "cache-control")]
pub cache_control: String,
pub pragma: String,
pub expires: String,
#[serde(rename = "x-frame-options")]
pub x_frame_options: String,
#[serde(rename = "x-content-type-options")]
pub x_content_type_options: String,
#[serde(rename = "x-ua-compatible")]
pub x_ua_compatible: String,
#[serde(rename = "content-language")]
pub content_language: String,
#[serde(rename = "strict-transport-security")]
pub strict_transport_security: String,
#[serde(rename = "x-robots-tag")]
pub x_robots_tag: String,
}
impl fmt::Debug for AuthClient {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("AuthClient")
.field("project_url", &self.project_url())
.field("api_key", &"[REDACTED]")
.field("jwt_secret", &"[REDACTED]")
.finish()
}
}
pub const AUTH_V1: &str = "/auth/v1";