Skip to main content

max / goingson

2.7 KB · 81 lines History Blame Raw
1 //! Microsoft/Outlook OAuth2 provider.
2 //!
3 //! Implements OAuth2 for Outlook/Microsoft 365 access via IMAP with XOAUTH2.
4 //! Uses default trait implementations for token exchange.
5 //!
6 //! See: https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow
7
8 use crate::oauth::provider::{OAuthProvider, OAuthProviderConfig};
9
10 /// Microsoft/Outlook OAuth2 provider.
11 ///
12 /// Uses PKCE for desktop apps (client secret is optional).
13 pub struct MicrosoftProvider {
14 client_id: String,
15 client_secret: Option<String>,
16 config: OAuthProviderConfig,
17 }
18
19 impl MicrosoftProvider {
20 /// Creates a new Microsoft OAuth provider.
21 ///
22 /// # Arguments
23 /// * `client_id` - Azure AD application (client) ID
24 /// * `client_secret` - Optional Azure AD client secret (desktop apps use PKCE instead)
25 pub fn new(client_id: impl Into<String>, client_secret: Option<String>) -> Self {
26 Self {
27 client_id: client_id.into(),
28 client_secret,
29 config: OAuthProviderConfig {
30 auth_url: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize".to_string(),
31 token_url: "https://login.microsoftonline.com/common/oauth2/v2.0/token".to_string(),
32 scopes: vec![
33 "https://outlook.office.com/IMAP.AccessAsUser.All".to_string(),
34 "https://outlook.office.com/SMTP.Send".to_string(),
35 "offline_access".to_string(),
36 "openid".to_string(),
37 "email".to_string(),
38 "profile".to_string(),
39 ],
40 uses_jmap: false,
41 jmap_session_url: None,
42 imap_server: Some("outlook.office365.com".to_string()),
43 imap_port: Some(993),
44 smtp_server: Some("smtp.office365.com".to_string()),
45 smtp_port: Some(587),
46 userinfo_url: Some("https://graph.microsoft.com/v1.0/me".to_string()),
47 email_json_path: vec!["mail", "userPrincipalName"], // Try mail first, then UPN
48 },
49 }
50 }
51 }
52
53 impl OAuthProvider for MicrosoftProvider {
54 fn id(&self) -> &'static str {
55 "microsoft"
56 }
57
58 fn display_name(&self) -> &'static str {
59 "Microsoft / Outlook"
60 }
61
62 fn config(&self) -> &OAuthProviderConfig {
63 &self.config
64 }
65
66 fn client_id(&self) -> &str {
67 &self.client_id
68 }
69
70 fn client_secret(&self) -> Option<&str> {
71 self.client_secret.as_deref()
72 }
73
74 fn customize_auth_url(&self, url: &mut String) {
75 // Microsoft-specific: response_mode for better security
76 url.push_str("&response_mode=query");
77 }
78
79 // Uses default exchange_code, refresh_token, get_user_email implementations
80 }
81