rustauth_oauth/oauth2/
provider.rs1use std::future::Future;
2use std::pin::Pin;
3
4use serde_json::Value;
5use url::Url;
6
7use super::authorization_url::AuthorizationUrlRequest;
8use super::error::OAuthError;
9use super::tokens::{OAuth2Tokens, OAuth2UserInfo, ProviderOptions};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct OAuthProviderMetadata {
14 id: String,
15 name: String,
16}
17
18impl OAuthProviderMetadata {
19 pub fn new(id: impl Into<String>, name: impl Into<String>) -> Self {
20 Self {
21 id: id.into(),
22 name: name.into(),
23 }
24 }
25
26 pub fn id(&self) -> &str {
27 &self.id
28 }
29
30 pub fn name(&self) -> &str {
31 &self.name
32 }
33}
34
35pub type SocialProviderFuture<'a, T> =
36 Pin<Box<dyn Future<Output = Result<T, OAuthError>> + Send + 'a>>;
37
38#[derive(Debug, Clone, Default, PartialEq, Eq)]
39pub struct SocialAuthorizationUrlRequest {
40 pub state: String,
41 pub redirect_uri: String,
42 pub code_verifier: Option<String>,
43 pub scopes: Vec<String>,
44 pub login_hint: Option<String>,
45}
46
47impl SocialAuthorizationUrlRequest {
48 pub fn into_authorization_url_request(
49 self,
50 id: impl Into<String>,
51 options: ProviderOptions,
52 authorization_endpoint: impl Into<String>,
53 scopes: Vec<String>,
54 ) -> AuthorizationUrlRequest {
55 AuthorizationUrlRequest {
56 id: id.into(),
57 options,
58 authorization_endpoint: authorization_endpoint.into(),
59 redirect_uri: self.redirect_uri,
60 state: self.state,
61 code_verifier: self.code_verifier,
62 scopes,
63 login_hint: self.login_hint,
64 ..AuthorizationUrlRequest::default()
65 }
66 }
67}
68
69#[derive(Debug, Clone, Default, PartialEq, Eq)]
70pub struct SocialAuthorizationCodeRequest {
71 pub code: String,
72 pub code_verifier: Option<String>,
73 pub redirect_uri: String,
74 pub device_id: Option<String>,
75}
76
77#[derive(Debug, Clone, Default, PartialEq)]
78pub struct SocialIdTokenRequest {
79 pub token: String,
80 pub nonce: Option<String>,
81 pub access_token: Option<String>,
82 pub refresh_token: Option<String>,
83 pub scopes: Vec<String>,
84 pub provider_user: Option<Value>,
85}
86
87pub trait SocialOAuthProvider: Send + Sync + 'static {
88 fn id(&self) -> &str;
89 fn name(&self) -> &str;
90 fn provider_options(&self) -> ProviderOptions;
91
92 fn create_authorization_url(
93 &self,
94 input: SocialAuthorizationUrlRequest,
95 ) -> Result<Url, OAuthError>;
96
97 fn validate_authorization_code(
98 &self,
99 input: SocialAuthorizationCodeRequest,
100 ) -> SocialProviderFuture<'_, OAuth2Tokens>;
101
102 fn get_user_info(
103 &self,
104 tokens: OAuth2Tokens,
105 provider_user: Option<Value>,
106 ) -> SocialProviderFuture<'_, Option<OAuth2UserInfo>>;
107
108 fn verify_id_token(&self, _input: SocialIdTokenRequest) -> SocialProviderFuture<'_, bool> {
109 Box::pin(async { Ok(false) })
110 }
111
112 fn refresh_access_token(
113 &self,
114 _refresh_token: String,
115 ) -> SocialProviderFuture<'_, OAuth2Tokens> {
116 Box::pin(async move {
117 Err(OAuthError::InvalidResponse(
118 "provider does not support refresh tokens".to_owned(),
119 ))
120 })
121 }
122
123 fn revoke_token(&self, _token: String) -> SocialProviderFuture<'_, ()> {
124 Box::pin(async move {
125 Err(OAuthError::InvalidResponse(
126 "provider does not support token revocation".to_owned(),
127 ))
128 })
129 }
130}