mirror of
https://github.com/OMGeeky/yup-oauth2.git
synced 2025-12-31 08:30:05 +01:00
refactor(delegate): Split AuthenticatorDelegate to have FlowDelegate
This commit is contained in:
@@ -134,7 +134,9 @@ pub trait AuthenticatorDelegate: Clone {
|
||||
let _ = error_description;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FlowDelegate: Clone {
|
||||
/// Called as long as we are waiting for the user to authorize us.
|
||||
/// Can be used to print progress information, or decide to time-out.
|
||||
///
|
||||
@@ -150,7 +152,6 @@ pub trait AuthenticatorDelegate: Clone {
|
||||
fn redirect_uri(&self) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
/// The server has returned a `user_code` which must be shown to the user,
|
||||
/// along with the `verification_url`.
|
||||
/// # Notes
|
||||
|
||||
@@ -13,7 +13,7 @@ use serde_json as json;
|
||||
use tokio_timer;
|
||||
use url::form_urlencoded;
|
||||
|
||||
use crate::authenticator_delegate::{AuthenticatorDelegate, PollError, PollInformation};
|
||||
use crate::authenticator_delegate::{FlowDelegate, PollError, PollInformation};
|
||||
use crate::types::{ApplicationSecret, Flow, FlowType, GetToken, JsonError, RequestError, Token};
|
||||
|
||||
pub const GOOGLE_DEVICE_CODE_URL: &'static str = "https://accounts.google.com/o/oauth2/device/code";
|
||||
@@ -22,25 +22,25 @@ pub const GOOGLE_DEVICE_CODE_URL: &'static str = "https://accounts.google.com/o/
|
||||
/// It operates in two steps:
|
||||
/// * obtain a code to show to the user
|
||||
/// * (repeatedly) poll for the user to authenticate your application
|
||||
pub struct DeviceFlow<AD, C> {
|
||||
pub struct DeviceFlow<FD, C> {
|
||||
client: hyper::Client<C, hyper::Body>,
|
||||
application_secret: ApplicationSecret,
|
||||
/// Usually GOOGLE_DEVICE_CODE_URL
|
||||
device_code_url: String,
|
||||
ad: AD,
|
||||
fd: FD,
|
||||
wait: Duration,
|
||||
}
|
||||
|
||||
impl<AD, C> Flow for DeviceFlow<AD, C> {
|
||||
impl<FD, C> Flow for DeviceFlow<FD, C> {
|
||||
fn type_id() -> FlowType {
|
||||
FlowType::Device(String::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
AD: AuthenticatorDelegate + Clone + Send + 'static,
|
||||
FD: FlowDelegate + Clone + Send + 'static,
|
||||
C: hyper::client::connect::Connect + Sync + 'static,
|
||||
> GetToken for DeviceFlow<AD, C>
|
||||
> GetToken for DeviceFlow<FD, C>
|
||||
{
|
||||
fn token<'b, I, T>(
|
||||
&mut self,
|
||||
@@ -57,19 +57,19 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
impl<AD, C> DeviceFlow<AD, C>
|
||||
impl<FD, C> DeviceFlow<FD, C>
|
||||
where
|
||||
C: hyper::client::connect::Connect + Sync + 'static,
|
||||
C::Transport: 'static,
|
||||
C::Future: 'static,
|
||||
AD: AuthenticatorDelegate + Clone + Send + 'static,
|
||||
FD: FlowDelegate + Clone + Send + 'static,
|
||||
{
|
||||
pub fn new<S: 'static + AsRef<str>>(
|
||||
client: hyper::Client<C, hyper::Body>,
|
||||
secret: ApplicationSecret,
|
||||
ad: AD,
|
||||
fd: FD,
|
||||
device_code_url: Option<S>,
|
||||
) -> DeviceFlow<AD, C> {
|
||||
) -> DeviceFlow<FD, C> {
|
||||
DeviceFlow {
|
||||
client: client,
|
||||
application_secret: secret,
|
||||
@@ -77,7 +77,7 @@ where
|
||||
.as_ref()
|
||||
.map(|s| s.as_ref().to_string())
|
||||
.unwrap_or(GOOGLE_DEVICE_CODE_URL.to_string()),
|
||||
ad: ad,
|
||||
fd: fd,
|
||||
wait: Duration::from_secs(120),
|
||||
}
|
||||
}
|
||||
@@ -87,11 +87,13 @@ where
|
||||
self.wait = wait;
|
||||
}
|
||||
|
||||
/// Essentially what `GetToken::token` does: Retrieve a token for the given scopes without
|
||||
/// caching.
|
||||
pub fn retrieve_device_token<'a>(
|
||||
&mut self,
|
||||
scopes: Vec<String>,
|
||||
) -> Box<dyn Future<Item = Token, Error = Box<dyn Error + Send>> + Send> {
|
||||
let mut ad = self.ad.clone();
|
||||
let mut fd = self.fd.clone();
|
||||
let application_secret = self.application_secret.clone();
|
||||
let client = self.client.clone();
|
||||
let wait = self.wait;
|
||||
@@ -102,14 +104,13 @@ where
|
||||
scopes,
|
||||
)
|
||||
.and_then(move |(pollinf, device_code)| {
|
||||
ad.present_user_code(&pollinf);
|
||||
fd.present_user_code(&pollinf);
|
||||
Ok((pollinf, device_code))
|
||||
});
|
||||
Box::new(request_code.and_then(move |(pollinf, device_code)| {
|
||||
future::loop_fn(0, move |i| {
|
||||
// Make a copy of everything every time, because the loop function needs to be
|
||||
// repeatable, i.e. we can't move anything out.
|
||||
//
|
||||
let pt = Self::poll_token(
|
||||
application_secret.clone(),
|
||||
client.clone(),
|
||||
|
||||
@@ -16,7 +16,7 @@ use serde_json::error;
|
||||
use url::form_urlencoded;
|
||||
use url::percent_encoding::{percent_encode, QUERY_ENCODE_SET};
|
||||
|
||||
use crate::authenticator_delegate::AuthenticatorDelegate;
|
||||
use crate::authenticator_delegate::FlowDelegate;
|
||||
use crate::types::{ApplicationSecret, GetToken, Token};
|
||||
|
||||
const OOB_REDIRECT_URI: &'static str = "urn:ietf:wg:oauth:2.0:oob";
|
||||
@@ -62,9 +62,9 @@ where
|
||||
}
|
||||
|
||||
impl<
|
||||
AD: AuthenticatorDelegate + 'static + Send + Clone,
|
||||
FD: FlowDelegate + 'static + Send + Clone,
|
||||
C: hyper::client::connect::Connect + 'static,
|
||||
> GetToken for InstalledFlow<AD, C>
|
||||
> GetToken for InstalledFlow<FD, C>
|
||||
{
|
||||
fn token<'b, I, T>(
|
||||
&mut self,
|
||||
@@ -81,10 +81,10 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InstalledFlow<AD: AuthenticatorDelegate, C: hyper::client::connect::Connect + 'static> {
|
||||
pub struct InstalledFlow<FD: FlowDelegate, C: hyper::client::connect::Connect + 'static> {
|
||||
method: InstalledFlowReturnMethod,
|
||||
client: hyper::client::Client<C, hyper::Body>,
|
||||
ad: AD,
|
||||
fd: FD,
|
||||
appsecret: ApplicationSecret,
|
||||
}
|
||||
|
||||
@@ -101,22 +101,22 @@ pub enum InstalledFlowReturnMethod {
|
||||
|
||||
impl<
|
||||
'c,
|
||||
AD: 'static + AuthenticatorDelegate + Clone + Send,
|
||||
FD: 'static + FlowDelegate + Clone + Send,
|
||||
C: 'c + hyper::client::connect::Connect,
|
||||
> InstalledFlow<AD, C>
|
||||
> InstalledFlow<FD, C>
|
||||
{
|
||||
/// Starts a new Installed App auth flow.
|
||||
/// If HTTPRedirect is chosen as method and the server can't be started, the flow falls
|
||||
/// back to Interactive.
|
||||
pub fn new(
|
||||
client: hyper::client::Client<C, hyper::Body>,
|
||||
ad: AD,
|
||||
fd: FD,
|
||||
secret: ApplicationSecret,
|
||||
method: InstalledFlowReturnMethod,
|
||||
) -> InstalledFlow<AD, C> {
|
||||
) -> InstalledFlow<FD, C> {
|
||||
InstalledFlow {
|
||||
method: method,
|
||||
ad: ad,
|
||||
fd: fd,
|
||||
appsecret: secret,
|
||||
client: client,
|
||||
}
|
||||
@@ -127,12 +127,12 @@ impl<
|
||||
/// . Obtain a token and refresh token using that code.
|
||||
/// . Return that token
|
||||
///
|
||||
/// It's recommended not to use the DefaultAuthenticatorDelegate, but a specialized one.
|
||||
/// It's recommended not to use the DefaultFlowDelegate, but a specialized one.
|
||||
pub fn obtain_token<'a>(
|
||||
&mut self,
|
||||
scopes: Vec<String>, // Note: I haven't found a better way to give a list of strings here, due to ownership issues with futures.
|
||||
) -> impl 'a + Future<Item = Token, Error = Box<dyn 'a + Error + Send>> + Send {
|
||||
let rduri = self.ad.redirect_uri();
|
||||
let rduri = self.fd.redirect_uri();
|
||||
// Start server on localhost to accept auth code.
|
||||
let server = if let InstalledFlowReturnMethod::HTTPRedirect(port) = self.method {
|
||||
match InstalledFlowServer::new(port) {
|
||||
@@ -149,7 +149,7 @@ impl<
|
||||
};
|
||||
let client = self.client.clone();
|
||||
let (appsecclone, appsecclone2) = (self.appsecret.clone(), self.appsecret.clone());
|
||||
let auth_delegate = self.ad.clone();
|
||||
let auth_delegate = self.fd.clone();
|
||||
server
|
||||
.into_future()
|
||||
// First: Obtain authorization code from user.
|
||||
@@ -218,7 +218,7 @@ impl<
|
||||
|
||||
fn ask_authorization_code<'a, S, T>(
|
||||
server: Option<InstalledFlowServer>,
|
||||
mut auth_delegate: AD,
|
||||
mut auth_delegate: FD,
|
||||
appsecret: &ApplicationSecret,
|
||||
scopes: S,
|
||||
) -> Box<dyn Future<Item = String, Error = Box<dyn Error + Send>> + Send>
|
||||
|
||||
Reference in New Issue
Block a user