|
| 1 | +use std::sync::Arc; |
1 | 2 | use std::time::Duration; |
2 | 3 |
|
| 4 | +use oauth2::basic::{ |
| 5 | + BasicClient, BasicErrorResponse, BasicRevocationErrorResponse, BasicTokenIntrospectionResponse, |
| 6 | + BasicTokenResponse, |
| 7 | +}; |
| 8 | +use oauth2::{AuthUrl, EndpointNotSet, EndpointSet, RedirectUrl, StandardRevocableToken, TokenUrl}; |
3 | 9 | use reqwest::header::{CONTENT_TYPE, HeaderValue, USER_AGENT}; |
4 | 10 | use reqwest::{Client, Method, Response}; |
5 | 11 | use url::Url; |
6 | 12 |
|
7 | 13 | use super::auth::CoinbaseAuth; |
8 | 14 | use super::auth::jwt::Jwt; |
9 | | -use super::constant::{API_ROOT_URL, API_SANDBOX_URL, CB_VERSION, USER_AGENT_NAME}; |
| 15 | +use super::constant::{ |
| 16 | + API_ROOT_URL, API_SANDBOX_URL, CB_VERSION, OAUTH_ACCESS_TOKEN_URL, OAUTH_AUTHORIZE_URL, |
| 17 | + USER_AGENT_NAME, |
| 18 | +}; |
10 | 19 | use super::error::Error; |
| 20 | +use super::oauth::{CoinbaseAppOAuth2Callback, CoinbaseOAuth2Token}; |
| 21 | + |
| 22 | +#[derive(Debug, Clone)] |
| 23 | +enum Authenticator { |
| 24 | + None, |
| 25 | + Jwt(Jwt), |
| 26 | + OAuth2 { |
| 27 | + client: oauth2::Client< |
| 28 | + BasicErrorResponse, |
| 29 | + BasicTokenResponse, |
| 30 | + BasicTokenIntrospectionResponse, |
| 31 | + StandardRevocableToken, |
| 32 | + BasicRevocationErrorResponse, |
| 33 | + EndpointSet, |
| 34 | + EndpointNotSet, |
| 35 | + EndpointNotSet, |
| 36 | + EndpointNotSet, |
| 37 | + EndpointSet, |
| 38 | + >, |
| 39 | + token: Arc<Mutex<Option<CoinbaseOAuth2Token>>> |
| 40 | + }, |
| 41 | +} |
11 | 42 |
|
12 | 43 | #[derive(Debug, Clone)] |
13 | 44 | struct HttpClientAgent { |
@@ -87,31 +118,65 @@ impl HttpClientAgent { |
87 | 118 |
|
88 | 119 | #[derive(Debug, Clone)] |
89 | 120 | pub struct SecureHttpClientAgent { |
90 | | - /// JWT generator, disabled in sandbox mode. |
91 | | - jwt: Option<Jwt>, |
| 121 | + /// Authenticator |
| 122 | + authenticator: Authenticator, |
| 123 | + /// OAuth2 callback |
| 124 | + oauth2_callback: Option<Arc<dyn CoinbaseAppOAuth2Callback>>, |
92 | 125 | /// Base client that is responsible for making the requests. |
93 | 126 | base: HttpClientAgent, |
94 | 127 | } |
95 | 128 |
|
96 | 129 | impl SecureHttpClientAgent { |
97 | | - pub(super) fn new(auth: CoinbaseAuth, sandbox: bool, timeout: Duration) -> Result<Self, Error> { |
98 | | - let jwt: Option<Jwt> = match auth { |
99 | | - CoinbaseAuth::None => None, |
| 130 | + pub(super) fn new( |
| 131 | + auth: CoinbaseAuth, |
| 132 | + sandbox: bool, |
| 133 | + timeout: Duration, |
| 134 | + oauth2_callback: Option<Arc<dyn CoinbaseAppOAuth2Callback>>, |
| 135 | + ) -> Result<Self, Error> { |
| 136 | + let authenticator: Authenticator = match auth { |
| 137 | + CoinbaseAuth::None => Authenticator::None, |
100 | 138 | CoinbaseAuth::ApiKeys { |
101 | 139 | api_key, |
102 | 140 | secret_key, |
103 | 141 | } => { |
104 | 142 | // Do not generate JWT in sandbox mode. |
105 | 143 | if sandbox { |
106 | | - None |
| 144 | + Authenticator::None |
107 | 145 | } else { |
108 | | - Some(Jwt::new(api_key, secret_key)?) |
| 146 | + Authenticator::Jwt(Jwt::new(api_key, secret_key)?) |
109 | 147 | } |
110 | 148 | } |
| 149 | + CoinbaseAuth::OAuth { |
| 150 | + client_id, |
| 151 | + client_secret, |
| 152 | + redirect_url, |
| 153 | + token, |
| 154 | + } => { |
| 155 | + let auth_url: Url = Url::parse(OAUTH_AUTHORIZE_URL)?; |
| 156 | + let auth_url: AuthUrl = AuthUrl::from_url(auth_url); |
| 157 | + |
| 158 | + let token_url: Url = Url::parse(OAUTH_ACCESS_TOKEN_URL)?; |
| 159 | + let token_url: TokenUrl = TokenUrl::from_url(token_url); |
| 160 | + |
| 161 | + let redirect_url: RedirectUrl = RedirectUrl::from_url(redirect_url); |
| 162 | + |
| 163 | + let client = BasicClient::new(client_id) |
| 164 | + .set_client_secret(client_secret) |
| 165 | + .set_auth_uri(auth_url) |
| 166 | + .set_token_uri(token_url) |
| 167 | + .set_redirect_uri(redirect_url); |
| 168 | + |
| 169 | + //client.exchange_refresh_token() |
| 170 | + |
| 171 | + //client.exchange_code().request_async() |
| 172 | + |
| 173 | + Authenticator::OAuth2 { client, token: Arc::new(Mutex::new(token)) } |
| 174 | + } |
111 | 175 | }; |
112 | 176 |
|
113 | 177 | Ok(Self { |
114 | | - jwt, |
| 178 | + authenticator, |
| 179 | + oauth2_callback, |
115 | 180 | base: HttpClientAgent::new(sandbox, timeout)?, |
116 | 181 | }) |
117 | 182 | } |
|
0 commit comments