azure_core/
auth.rs

1//! Azure authentication and authorization.
2
3use serde::{Deserialize, Serialize};
4use std::{borrow::Cow, fmt::Debug};
5use time::OffsetDateTime;
6
7pub static DEFAULT_SCOPE_SUFFIX: &str = "/.default";
8
9#[derive(Clone, Deserialize, Serialize, Eq)]
10pub struct Secret(Cow<'static, str>);
11
12impl Secret {
13    pub fn new<T>(access_token: T) -> Self
14    where
15        T: Into<Cow<'static, str>>,
16    {
17        Self(access_token.into())
18    }
19
20    pub fn secret(&self) -> &str {
21        &self.0
22    }
23}
24
25// NOTE: this is a constant time compare, however LLVM may (and probably will)
26// optimize this in unexpected ways.
27impl PartialEq for Secret {
28    fn eq(&self, other: &Self) -> bool {
29        let a = self.secret();
30        let b = other.secret();
31
32        if a.len() != b.len() {
33            return false;
34        }
35
36        a.bytes()
37            .zip(b.bytes())
38            .fold(0, |acc, (a, b)| acc | (a ^ b))
39            == 0
40    }
41}
42
43impl From<String> for Secret {
44    fn from(access_token: String) -> Self {
45        Self::new(access_token)
46    }
47}
48
49impl From<&'static str> for Secret {
50    fn from(access_token: &'static str) -> Self {
51        Self::new(access_token)
52    }
53}
54
55impl Debug for Secret {
56    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57        f.debug_tuple("Secret").field(&"<REDACTED>").finish()
58    }
59}
60
61/// Represents an Azure service bearer access token with expiry information.
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct AccessToken {
64    /// Get the access token value.
65    pub token: Secret,
66    /// Gets the time when the provided token expires.
67    pub expires_on: OffsetDateTime,
68}
69
70impl AccessToken {
71    /// Create a new `AccessToken`.
72    pub fn new<T>(token: T, expires_on: OffsetDateTime) -> Self
73    where
74        T: Into<Secret>,
75    {
76        Self {
77            token: token.into(),
78            expires_on,
79        }
80    }
81}
82
83/// Represents a credential capable of providing an OAuth token.
84#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
85#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
86pub trait TokenCredential: Send + Sync + Debug {
87    /// Gets a `AccessToken` for the specified resource
88    async fn get_token(&self, scopes: &[&str]) -> crate::Result<AccessToken>;
89
90    /// Clear the credential's cache.
91    async fn clear_cache(&self) -> crate::Result<()>;
92}