From fb0c3ff506a70431112c46f4c4d79f6a9559dd58 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sun, 1 Mar 2015 09:54:15 +0100 Subject: [PATCH] feat(auth): Authenticator support GetToken trait This will allow its usage in generics, without having to provide the 4 additional template types it usees. --- Cargo.toml | 2 +- examples/auth.rs | 1 + src/helper.rs | 128 ++++++++++++++++++++++++++--------------------- src/lib.rs | 4 +- 4 files changed, 75 insertions(+), 60 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5f33d5803..308fd5b71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "yup-oauth2" -version = "0.2.0" +version = "0.2.1" authors = ["Sebastian Thiel "] repository = "https://github.com/Byron/yup-oauth2" description = "A partial oauth2 implementation, providing the 'device' authorization flow" diff --git a/examples/auth.rs b/examples/auth.rs index 50f808f55..84c712cc7 100644 --- a/examples/auth.rs +++ b/examples/auth.rs @@ -6,6 +6,7 @@ extern crate chrono; extern crate getopts; extern crate open; +use oauth2::GetToken; use chrono::{Local}; use getopts::{HasArg,Options,Occur,Fail}; use std::env; diff --git a/src/helper.rs b/src/helper.rs index 8df69bac3..6327da915 100644 --- a/src/helper.rs +++ b/src/helper.rs @@ -80,6 +80,13 @@ pub struct Authenticator { _m: PhantomData } +/// A provider for authorization tokens, yielding tokens valid for a given scope. +pub trait GetToken { + fn token<'b, I, T>(&mut self, scopes: I) -> Option + where T: Str + Ord, + I: IntoIterator; +} + impl Authenticator where D: AuthenticatorDelegate, S: TokenStorage, @@ -113,11 +120,74 @@ impl Authenticator } } + fn retrieve_device_token(&mut self, scopes: &Vec<&str>) -> Option { + let mut flow = DeviceFlow::new(self.client.borrow_mut()); + + // PHASE 1: REQUEST CODE + loop { + let res = flow.request_code(&self.secret.client_id, + &self.secret.client_secret, scopes.iter()); + match res { + RequestResult::Error(err) => { + match self.delegate.connection_error(err) { + Retry::Abort => return None, + Retry::After(d) => sleep(d), + } + }, + RequestResult::InvalidClient + |RequestResult::InvalidScope(_) => { + self.delegate.request_failure(res); + return None + } + RequestResult::ProceedWithPolling(pi) => { + self.delegate.present_user_code(pi); + break + } + } + } + + // PHASE 1: POLL TOKEN + loop { + match flow.poll_token() { + PollResult::Error(err) => { + match self.delegate.connection_error(err) { + Retry::Abort => return None, + Retry::After(d) => sleep(d), + } + }, + PollResult::Expired(t) => { + self.delegate.expired(t); + return None + }, + PollResult::AccessDenied => { + self.delegate.denied(); + return None + }, + PollResult::AuthorizationPending(pi) => { + match self.delegate.pending(&pi) { + Retry::Abort => return None, + Retry::After(d) => sleep(min(d, pi.interval)), + } + }, + PollResult::AccessGranted(token) => { + return Some(token) + }, + } + } + } +} + +impl GetToken for Authenticator + where D: AuthenticatorDelegate, + S: TokenStorage, + NC: hyper::net::NetworkConnector, + C: BorrowMut> { + /// Blocks until a token was retrieved from storage, from the server, or until the delegate /// decided to abort the attempt, or the user decided not to authorize the application. /// In any failure case, the returned token will be None, otherwise it is guaranteed to be /// valid for the given scopes. - pub fn token<'b, I, T>(&mut self, scopes: I) -> Option + fn token<'b, I, T>(&mut self, scopes: I) -> Option where T: Str + Ord, I: IntoIterator { let (scope_key, scopes) = { @@ -175,62 +245,6 @@ impl Authenticator }, } } - - fn retrieve_device_token(&mut self, scopes: &Vec<&str>) -> Option { - let mut flow = DeviceFlow::new(self.client.borrow_mut()); - - // PHASE 1: REQUEST CODE - loop { - let res = flow.request_code(&self.secret.client_id, - &self.secret.client_secret, scopes.iter()); - match res { - RequestResult::Error(err) => { - match self.delegate.connection_error(err) { - Retry::Abort => return None, - Retry::After(d) => sleep(d), - } - }, - RequestResult::InvalidClient - |RequestResult::InvalidScope(_) => { - self.delegate.request_failure(res); - return None - } - RequestResult::ProceedWithPolling(pi) => { - self.delegate.present_user_code(pi); - break - } - } - } - - // PHASE 1: POLL TOKEN - loop { - match flow.poll_token() { - PollResult::Error(err) => { - match self.delegate.connection_error(err) { - Retry::Abort => return None, - Retry::After(d) => sleep(d), - } - }, - PollResult::Expired(t) => { - self.delegate.expired(t); - return None - }, - PollResult::AccessDenied => { - self.delegate.denied(); - return None - }, - PollResult::AuthorizationPending(pi) => { - match self.delegate.pending(&pi) { - Retry::Abort => return None, - Retry::After(d) => sleep(min(d, pi.interval)), - } - }, - PollResult::AccessGranted(token) => { - return Some(token) - }, - } - } - } } diff --git a/src/lib.rs b/src/lib.rs index bdc715eac..92eb24fc7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,7 @@ //! extern crate "yup-oauth2" as oauth2; //! extern crate "rustc-serialize" as rustc_serialize; //! -//! use oauth2::{Authenticator, DefaultAuthenticatorDelegate, PollInformation, ConsoleApplicationSecret, MemoryStorage}; +//! use oauth2::{Authenticator, DefaultAuthenticatorDelegate, PollInformation, ConsoleApplicationSecret, MemoryStorage, GetToken}; //! use rustc_serialize::json; //! use std::default::Default; //! # const SECRET: &'static str = "{\"installed\":{\"auth_uri\":\"https://accounts.google.com/o/oauth2/auth\",\"client_secret\":\"UqkDJd5RFwnHoiG5x5Rub8SI\",\"token_uri\":\"https://accounts.google.com/o/oauth2/token\",\"client_email\":\"\",\"redirect_uris\":[\"urn:ietf:wg:oauth:2.0:oob\",\"oob\"],\"client_x509_cert_url\":\"\",\"client_id\":\"14070749909-vgip2f1okm7bkvajhi9jugan6126io9v.apps.googleusercontent.com\",\"auth_provider_x509_cert_url\":\"https://www.googleapis.com/oauth2/v1/certs\"}}"; @@ -83,4 +83,4 @@ pub use device::{DeviceFlow, PollInformation, PollResult}; pub use refresh::{RefreshFlow, RefreshResult}; pub use common::{Token, FlowType, ApplicationSecret, ConsoleApplicationSecret}; pub use helper::{TokenStorage, NullStorage, MemoryStorage, Authenticator, - AuthenticatorDelegate, Retry, DefaultAuthenticatorDelegate}; + AuthenticatorDelegate, Retry, DefaultAuthenticatorDelegate, GetToken};