Skip to content

Commit

Permalink
feat(auth): Authenticator support GetToken trait
Browse files Browse the repository at this point in the history
This will allow its usage in generics, without having to provide
the 4 additional template types it usees.
  • Loading branch information
Byron committed Mar 1, 2015
1 parent fda2d62 commit fb0c3ff
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 60 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]

name = "yup-oauth2"
version = "0.2.0"
version = "0.2.1"
authors = ["Sebastian Thiel <[email protected]>"]
repository = "https://github.com/Byron/yup-oauth2"
description = "A partial oauth2 implementation, providing the 'device' authorization flow"
Expand Down
1 change: 1 addition & 0 deletions examples/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
128 changes: 71 additions & 57 deletions src/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ pub struct Authenticator<D, S, C, NC> {
_m: PhantomData<NC>
}

/// 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<Token>
where T: Str + Ord,
I: IntoIterator<Item=&'b T>;
}

impl<D, S, C, NC> Authenticator<D, S, C, NC>
where D: AuthenticatorDelegate,
S: TokenStorage,
Expand Down Expand Up @@ -113,11 +120,74 @@ impl<D, S, C, NC> Authenticator<D, S, C, NC>
}
}

fn retrieve_device_token(&mut self, scopes: &Vec<&str>) -> Option<Token> {
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<D, S, C, NC> GetToken for Authenticator<D, S, C, NC>
where D: AuthenticatorDelegate,
S: TokenStorage,
NC: hyper::net::NetworkConnector,
C: BorrowMut<hyper::Client<NC>> {

/// 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<Token>
fn token<'b, I, T>(&mut self, scopes: I) -> Option<Token>
where T: Str + Ord,
I: IntoIterator<Item=&'b T> {
let (scope_key, scopes) = {
Expand Down Expand Up @@ -175,62 +245,6 @@ impl<D, S, C, NC> Authenticator<D, S, C, NC>
},
}
}

fn retrieve_device_token(&mut self, scopes: &Vec<&str>) -> Option<Token> {
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)
},
}
}
}
}


Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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\"}}";
Expand Down Expand Up @@ -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};

0 comments on commit fb0c3ff

Please sign in to comment.