1use std::fmt::Display;
2use url::{ParseError, Url};
3
4lazy_static! {
5 pub static ref AZURE_PUBLIC_CLOUD_INSTANCE: Url = {
6 Url::parse(AzureCloudInstance::AzurePublic.as_ref())
7 .expect("Unable to create Azure Public Cloud Instance Url")
8 };
9 pub static ref AZURE_CHINA_CLOUD_INSTANCE: Url = {
10 Url::parse(AzureCloudInstance::AzureChina.as_ref())
11 .expect("Unable to create Azure China Cloud Instance Url")
12 };
13 pub static ref AZURE_GERMANY_CLOUD_INSTANCE: Url = {
14 Url::parse(AzureCloudInstance::AzureGermany.as_ref())
15 .expect("Unable to create Azure Germany Cloud Instance Url")
16 };
17 pub static ref AZURE_US_GOVERNMENT: Url = {
18 Url::parse(AzureCloudInstance::AzureUsGovernment.as_ref())
19 .expect("Unable to create Azure Us Government Cloud Instance Url")
20 };
21}
22
23#[derive(
26 Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize,
27)]
28pub enum AzureCloudInstance {
29 #[default]
31 AzurePublic,
32 AzureChina,
34 AzureGermany,
36 AzureUsGovernment,
38}
39
40impl AzureCloudInstance {
41 pub fn get_open_id_configuration_url(&self, authority: Authority) -> String {
42 format!("{}/v2.0/{}", self.as_ref(), authority.as_ref())
43 }
44}
45
46impl AsRef<str> for AzureCloudInstance {
47 fn as_ref(&self) -> &str {
48 match self {
49 AzureCloudInstance::AzurePublic => "https://login.microsoftonline.com",
50 AzureCloudInstance::AzureChina => "https://login.chinacloudapi.cn",
51 AzureCloudInstance::AzureGermany => "https://login.microsoftonline.de",
52 AzureCloudInstance::AzureUsGovernment => "https://login.microsoftonline.us",
53 }
54 }
55}
56
57impl From<&AzureCloudInstance> for Url {
58 fn from(value: &AzureCloudInstance) -> Self {
59 match value {
60 AzureCloudInstance::AzurePublic => AZURE_PUBLIC_CLOUD_INSTANCE.clone(),
61 AzureCloudInstance::AzureChina => AZURE_CHINA_CLOUD_INSTANCE.clone(),
62 AzureCloudInstance::AzureGermany => AZURE_GERMANY_CLOUD_INSTANCE.clone(),
63 AzureCloudInstance::AzureUsGovernment => AZURE_US_GOVERNMENT.clone(),
64 }
65 }
66}
67
68impl From<AzureCloudInstance> for Url {
69 fn from(value: AzureCloudInstance) -> Self {
70 match value {
71 AzureCloudInstance::AzurePublic => AZURE_PUBLIC_CLOUD_INSTANCE.clone(),
72 AzureCloudInstance::AzureChina => AZURE_CHINA_CLOUD_INSTANCE.clone(),
73 AzureCloudInstance::AzureGermany => AZURE_GERMANY_CLOUD_INSTANCE.clone(),
74 AzureCloudInstance::AzureUsGovernment => AZURE_US_GOVERNMENT.clone(),
75 }
76 }
77}
78
79impl AzureCloudInstance {
80 pub fn auth_uri(&self, authority: &Authority) -> Result<Url, ParseError> {
81 Url::parse(&format!(
82 "{}/{}/oauth2/v2.0/authorize",
83 self.as_ref(),
84 authority.as_ref()
85 ))
86 }
87
88 pub fn token_uri(&self, authority: &Authority) -> Result<Url, ParseError> {
89 Url::parse(&format!(
90 "{}/{}/oauth2/v2.0/token",
91 self.as_ref(),
92 authority.as_ref()
93 ))
94 }
95
96 pub fn admin_consent_uri(&self, authority: &Authority) -> Result<Url, ParseError> {
97 Url::parse(&format!(
98 "{}/{}/adminconsent",
99 self.as_ref(),
100 authority.as_ref()
101 ))
102 }
103
104 pub fn device_code_uri(&self, authority: &Authority) -> Result<Url, ParseError> {
105 Url::parse(&format!(
106 "{}/{}/oauth2/v2.0/devicecode",
107 self.as_ref(),
108 authority.as_ref()
109 ))
110 }
111
112 pub fn openid_configuration_uri(&self, authority: &Authority) -> Result<Url, ParseError> {
113 Url::parse(&format!(
114 "{}/{}/v2.0/.well-known/openid-configuration",
115 self.as_ref(),
116 authority.as_ref()
117 ))
118 }
119
120 pub fn issuer(&self, authority: &Authority) -> Result<Url, ParseError> {
121 Url::parse(&format!("{}/{}/v2.0", self.as_ref(), authority.as_ref()))
122 }
123
124 }
141
142#[derive(Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
148pub enum AadAuthorityAudience {
149 AzureAdMyOrg(String),
159
160 #[default]
163 AzureAdAndPersonalMicrosoftAccount,
164
165 AzureAdMultipleOrgs,
168
169 PersonalMicrosoftAccount,
172}
173
174impl AadAuthorityAudience {
175 pub fn as_str(&self) -> &str {
176 match self {
177 AadAuthorityAudience::AzureAdMyOrg(tenant) => tenant.as_str(),
178 AadAuthorityAudience::AzureAdAndPersonalMicrosoftAccount => "common",
179 AadAuthorityAudience::AzureAdMultipleOrgs => "organizations",
180 AadAuthorityAudience::PersonalMicrosoftAccount => "consumers",
181 }
182 }
183}
184
185impl AsRef<str> for AadAuthorityAudience {
186 fn as_ref(&self) -> &str {
187 self.as_str()
188 }
189}
190
191impl Display for AadAuthorityAudience {
192 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
193 write!(f, "{}", self.as_str())
194 }
195}
196
197impl From<&str> for AadAuthorityAudience {
198 fn from(value: &str) -> Self {
199 match value.as_bytes() {
200 b"common" => AadAuthorityAudience::AzureAdAndPersonalMicrosoftAccount,
201 b"organizations" => AadAuthorityAudience::AzureAdMultipleOrgs,
202 b"consumers" => AadAuthorityAudience::PersonalMicrosoftAccount,
203 _ => AadAuthorityAudience::AzureAdMyOrg(value.to_string()),
204 }
205 }
206}
207
208#[derive(Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
211pub enum Authority {
212 #[default]
220 AzureActiveDirectory,
221 AzureDirectoryFederatedServices,
222 Common,
231 Organizations,
233 Consumers,
235 TenantId(String),
243}
244
245impl Authority {
246 pub fn tenant_id(&self) -> Option<&String> {
247 match self {
248 Authority::TenantId(tenant_id) => Some(tenant_id),
249 _ => None,
250 }
251 }
252
253 pub fn as_str(&self) -> &str {
254 match self {
255 Authority::AzureActiveDirectory | Authority::Common => "common",
256 Authority::AzureDirectoryFederatedServices => "adfs",
257 Authority::Organizations => "organizations",
258 Authority::Consumers => "consumers",
259 Authority::TenantId(tenant_id) => tenant_id.as_str(),
260 }
261 }
262}
263
264impl From<&AadAuthorityAudience> for Authority {
265 fn from(value: &AadAuthorityAudience) -> Self {
266 match value {
267 AadAuthorityAudience::AzureAdAndPersonalMicrosoftAccount => Authority::Common,
268 AadAuthorityAudience::AzureAdMyOrg(tenant_id) => Authority::TenantId(tenant_id.clone()),
269 AadAuthorityAudience::AzureAdMultipleOrgs => Authority::Organizations,
270 AadAuthorityAudience::PersonalMicrosoftAccount => Authority::Consumers,
271 }
272 }
273}
274
275impl From<AadAuthorityAudience> for Authority {
276 fn from(value: AadAuthorityAudience) -> Self {
277 match value {
278 AadAuthorityAudience::AzureAdAndPersonalMicrosoftAccount => Authority::Common,
279 AadAuthorityAudience::AzureAdMyOrg(tenant_id) => Authority::TenantId(tenant_id),
280 AadAuthorityAudience::AzureAdMultipleOrgs => Authority::Organizations,
281 AadAuthorityAudience::PersonalMicrosoftAccount => Authority::Consumers,
282 }
283 }
284}
285
286impl AsRef<str> for Authority {
287 fn as_ref(&self) -> &str {
288 self.as_str()
289 }
290}
291
292impl Display for Authority {
293 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
294 write!(f, "{}", self.as_str())
295 }
296}
297
298impl From<&str> for Authority {
299 fn from(value: &str) -> Self {
300 match value.as_bytes() {
301 b"aad" => Authority::AzureActiveDirectory,
302 b"common" => Authority::Common,
303 b"adfs" => Authority::AzureDirectoryFederatedServices,
304 b"organizations" => Authority::Organizations,
305 b"consumers" => Authority::Consumers,
306 _ => Authority::TenantId(value.to_owned()),
307 }
308 }
309}