diff --git a/src/authenticator_delegate.rs b/src/authenticator_delegate.rs index 8272b9f..0fd2fca 100644 --- a/src/authenticator_delegate.rs +++ b/src/authenticator_delegate.rs @@ -112,6 +112,11 @@ pub trait AuthenticatorDelegate { Retry::After(Duration::from_secs(5)) } + /// Configure a custom redirect uri if needed. + fn redirect_uri(&self) -> Option { + None + } + /// The server has returned a `user_code` which must be shown to the user, /// along with the `verification_url`. /// # Notes @@ -126,7 +131,7 @@ pub trait AuthenticatorDelegate { pi.expires_at.with_timezone(&Local)); } - /// Only method currently used by the InstalledFlow. + /// This method is used by the InstalledFlow. /// We need the user to navigate to a URL using their browser and potentially paste back a code /// (or maybe not). Whether they have to enter a code depends on the InstalledFlowReturnMethod /// used. diff --git a/src/installed.rs b/src/installed.rs index 62db42e..87f1377 100644 --- a/src/installed.rs +++ b/src/installed.rs @@ -135,7 +135,7 @@ impl InstalledFlow S: Iterator { let authcode = self.get_authorization_code(auth_delegate, &appsecret, scopes)?; - let tokens = self.request_token(&appsecret, &authcode)?; + let tokens = self.request_token(&appsecret, &authcode, auth_delegate.redirect_uri())?; // Successful response if tokens.access_token.is_some() { @@ -175,7 +175,7 @@ impl InstalledFlow let url = build_authentication_request_url(&appsecret.auth_uri, &appsecret.client_id, scopes, - None); + auth_delegate.redirect_uri()); match auth_delegate.present_user_url(&url, true /* need_code */) { None => { Result::Err(Box::new(io::Error::new(io::ErrorKind::UnexpectedEof, @@ -194,9 +194,9 @@ impl InstalledFlow let url = build_authentication_request_url(&appsecret.auth_uri, &appsecret.client_id, scopes, - Some(format!("http://localhost:{}", - self.port - .unwrap_or(8080)))); + auth_delegate.redirect_uri().or_else(|| { + Some(format!("http://localhost:{}", self.port.unwrap_or(8080))) + })); auth_delegate.present_user_url(&url, false /* need_code */); match self.auth_code_rcv.as_ref().unwrap().recv() { @@ -212,14 +212,15 @@ impl InstalledFlow /// Sends the authorization code to the provider in order to obtain access and refresh tokens. fn request_token(&mut self, appsecret: &ApplicationSecret, - authcode: &str) + authcode: &str, + custom_redirect_uri: Option) -> Result> { - let redirect_uri; - - match self.port { - None => redirect_uri = OOB_REDIRECT_URI.to_string(), - Some(p) => redirect_uri = format!("http://localhost:{}", p), - } + let redirect_uri = custom_redirect_uri.unwrap_or_else(|| { + match self.port { + None => OOB_REDIRECT_URI.to_string(), + Some(p) => format!("http://localhost:{}", p), + } + }); let body = form_urlencoded::Serializer::new(String::new()) .extend_pairs(vec![("code".to_string(), authcode.to_string()),