mirror of
https://github.com/OMGeeky/yup-oauth2.git
synced 2026-01-06 19:29:39 +01:00
Rust 2018 edition modifications.
This commit is contained in:
@@ -8,6 +8,7 @@ description = "An oauth2 implementation, providing the 'device', 'service accoun
|
||||
documentation = "https://docs.rs/yup-oauth2/"
|
||||
keywords = ["google", "oauth", "v2"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.9"
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
extern crate yup_oauth2 as oauth2;
|
||||
extern crate yup_hyper_mock as mock;
|
||||
extern crate hyper;
|
||||
extern crate chrono;
|
||||
extern crate getopts;
|
||||
extern crate open;
|
||||
|
||||
use oauth2::GetToken;
|
||||
use yup_oauth2::{self as oauth2, GetToken};
|
||||
use yup_hyper_mock as mock;
|
||||
use chrono::{Local};
|
||||
use getopts::{HasArg,Options,Occur,Fail};
|
||||
use std::env;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "drive_example"
|
||||
version = "0.1.0"
|
||||
authors = ["Lewin Bormann <lbo@spheniscida.de>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
yup-oauth2 = "^ 1.0"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "service_account"
|
||||
version = "0.1.0"
|
||||
authors = ["Lewin Bormann <lewin@lewin-bormann.info>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.2"
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
//! Copyright (c) 2016 Google, Inc. (Lewin Bormann <lbo@spheniscida.de>)
|
||||
//!
|
||||
extern crate base64;
|
||||
extern crate yup_oauth2 as oauth;
|
||||
extern crate google_pubsub1 as pubsub;
|
||||
extern crate hyper;
|
||||
extern crate hyper_native_tls;
|
||||
|
||||
@@ -34,9 +32,10 @@ use std::env;
|
||||
use std::time;
|
||||
use std::thread;
|
||||
|
||||
use yup_oauth2 as oauth;
|
||||
use hyper::net::HttpsConnector;
|
||||
use hyper_native_tls::NativeTlsClient;
|
||||
use pubsub::{Topic, Subscription};
|
||||
use google_pubsub1::{self as pubsub, Topic, Subscription};
|
||||
|
||||
// The prefixes are important!
|
||||
const SUBSCRIPTION_NAME: &'static str = "projects/sanguine-rhythm-105020/subscriptions/rust_authd_sub_1";
|
||||
@@ -52,7 +51,7 @@ fn check_or_create_topic(methods: &PubsubMethods) -> Topic {
|
||||
|
||||
if result.is_err() {
|
||||
println!("Assuming topic doesn't exist; creating topic");
|
||||
let topic = pubsub::Topic { name: Some(TOPIC_NAME.to_string()) };
|
||||
let topic = pubsub::Topic { name: Some(TOPIC_NAME.to_string()), labels: None };
|
||||
let result = methods.topics_create(topic, TOPIC_NAME).doit().unwrap();
|
||||
result.1
|
||||
} else {
|
||||
@@ -73,6 +72,7 @@ fn check_or_create_subscription(methods: &PubsubMethods) -> Subscription {
|
||||
message_retention_duration: None,
|
||||
retain_acked_messages: None,
|
||||
name: Some(SUBSCRIPTION_NAME.to_string()),
|
||||
labels: None,
|
||||
};
|
||||
let (_resp, sub) = methods.subscriptions_create(sub, SUBSCRIPTION_NAME).doit().unwrap();
|
||||
|
||||
@@ -170,7 +170,7 @@ fn main() {
|
||||
let client = hyper::Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
|
||||
let mut access = oauth::ServiceAccountAccess::new(client_secret, client);
|
||||
|
||||
use oauth::GetToken;
|
||||
use yup_oauth2::GetToken;
|
||||
println!("{:?}",
|
||||
access.token(&vec!["https://www.googleapis.com/auth/pubsub"]).unwrap());
|
||||
|
||||
|
||||
@@ -6,14 +6,14 @@ use std::error::Error;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::iter::IntoIterator;
|
||||
use std::thread::sleep;
|
||||
|
||||
use authenticator_delegate::{AuthenticatorDelegate, PollError, PollInformation};
|
||||
use device::{GOOGLE_DEVICE_CODE_URL, DeviceFlow};
|
||||
use installed::{InstalledFlow, InstalledFlowReturnMethod};
|
||||
use refresh::{RefreshResult, RefreshFlow};
|
||||
use std::time::Duration;
|
||||
use storage::TokenStorage;
|
||||
use types::{RequestError, StringError, Token, FlowType, ApplicationSecret};
|
||||
|
||||
use crate::authenticator_delegate::{AuthenticatorDelegate, PollError, PollInformation};
|
||||
use crate::device::{GOOGLE_DEVICE_CODE_URL, DeviceFlow};
|
||||
use crate::installed::{InstalledFlow, InstalledFlowReturnMethod};
|
||||
use crate::refresh::{RefreshResult, RefreshFlow};
|
||||
use crate::storage::TokenStorage;
|
||||
use crate::types::{RequestError, StringError, Token, FlowType, ApplicationSecret};
|
||||
|
||||
use hyper;
|
||||
|
||||
@@ -326,8 +326,8 @@ mod tests {
|
||||
use super::super::device::tests::MockGoogleAuth;
|
||||
use super::super::types::tests::SECRET;
|
||||
use super::super::types::ConsoleApplicationSecret;
|
||||
use authenticator_delegate::DefaultAuthenticatorDelegate;
|
||||
use storage::MemoryStorage;
|
||||
use crate::authenticator_delegate::DefaultAuthenticatorDelegate;
|
||||
use crate::storage::MemoryStorage;
|
||||
use std::default::Default;
|
||||
use hyper;
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ use std::fmt;
|
||||
use std::io;
|
||||
use std::error::Error;
|
||||
|
||||
use authenticator::Retry;
|
||||
use types::RequestError;
|
||||
use crate::authenticator::Retry;
|
||||
use crate::types::RequestError;
|
||||
|
||||
use chrono::{DateTime, Local, Utc};
|
||||
use std::time::Duration;
|
||||
@@ -63,7 +63,7 @@ pub trait AuthenticatorDelegate {
|
||||
/// Called whenever there is an HttpError, usually if there are network problems.
|
||||
///
|
||||
/// Return retry information.
|
||||
fn connection_error(&mut self, &hyper::Error) -> Retry {
|
||||
fn connection_error(&mut self, _: &hyper::Error) -> Retry {
|
||||
Retry::Abort
|
||||
}
|
||||
|
||||
@@ -78,12 +78,12 @@ pub trait AuthenticatorDelegate {
|
||||
}
|
||||
|
||||
/// The server denied the attempt to obtain a request code
|
||||
fn request_failure(&mut self, RequestError) {}
|
||||
fn request_failure(&mut self, _: RequestError) {}
|
||||
|
||||
/// Called if the request code is expired. You will have to start over in this case.
|
||||
/// This will be the last call the delegate receives.
|
||||
/// Given `DateTime` is the expiration date
|
||||
fn expired(&mut self, &DateTime<Utc>) {}
|
||||
fn expired(&mut self, _: &DateTime<Utc>) {}
|
||||
|
||||
/// Called if the user denied access. You would have to start over.
|
||||
/// This will be the last call the delegate receives.
|
||||
@@ -108,7 +108,7 @@ pub trait AuthenticatorDelegate {
|
||||
/// # Notes
|
||||
/// * Only used in `DeviceFlow`. Return value will only be used if it
|
||||
/// is larger than the interval desired by the server.
|
||||
fn pending(&mut self, &PollInformation) -> Retry {
|
||||
fn pending(&mut self, _: &PollInformation) -> Retry {
|
||||
Retry::After(Duration::from_secs(5))
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ use std::borrow::BorrowMut;
|
||||
use std::io::Read;
|
||||
use std::i64;
|
||||
|
||||
use types::{ApplicationSecret, Token, FlowType, Flow, RequestError, JsonError};
|
||||
use authenticator_delegate::{PollError, PollInformation};
|
||||
use crate::types::{ApplicationSecret, Token, FlowType, Flow, RequestError, JsonError};
|
||||
use crate::authenticator_delegate::{PollError, PollInformation};
|
||||
|
||||
pub const GOOGLE_DEVICE_CODE_URL: &'static str = "https://accounts.google.com/o/oauth2/device/code";
|
||||
|
||||
@@ -294,7 +294,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn working_flow() {
|
||||
use helper::parse_application_secret;
|
||||
use crate::helper::parse_application_secret;
|
||||
|
||||
let appsecret = parse_application_secret(&TEST_APP_SECRET.to_string()).unwrap();
|
||||
let mut flow = DeviceFlow::new(
|
||||
|
||||
@@ -13,16 +13,16 @@ use std::io::{self, Read};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use service_account::ServiceAccountKey;
|
||||
use types::{ConsoleApplicationSecret, ApplicationSecret};
|
||||
use crate::service_account::ServiceAccountKey;
|
||||
use crate::types::{ConsoleApplicationSecret, ApplicationSecret};
|
||||
|
||||
/// Read an application secret from a file.
|
||||
pub fn read_application_secret(path: &Path) -> io::Result<ApplicationSecret> {
|
||||
use std::io::Read;
|
||||
|
||||
let mut secret = String::new();
|
||||
let mut file = try!(fs::OpenOptions::new().read(true).open(path));
|
||||
try!(file.read_to_string(&mut secret));
|
||||
let mut file = fs::OpenOptions::new().read(true).open(path)?;
|
||||
file.read_to_string(&mut secret)?;
|
||||
|
||||
parse_application_secret(&secret)
|
||||
}
|
||||
@@ -52,8 +52,8 @@ pub fn parse_application_secret(secret: &String) -> io::Result<ApplicationSecret
|
||||
/// Cloud Console or the respective console of your service provider.
|
||||
pub fn service_account_key_from_file(path: &String) -> io::Result<ServiceAccountKey> {
|
||||
let mut key = String::new();
|
||||
let mut file = try!(fs::OpenOptions::new().read(true).open(path));
|
||||
try!(file.read_to_string(&mut key));
|
||||
let mut file = fs::OpenOptions::new().read(true).open(path)?;
|
||||
file.read_to_string(&mut key)?;
|
||||
|
||||
match serde_json::from_str(&key) {
|
||||
Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, format!("{}", e))),
|
||||
|
||||
@@ -19,8 +19,8 @@ use serde_json::error;
|
||||
use url::form_urlencoded;
|
||||
use url::percent_encoding::{percent_encode, QUERY_ENCODE_SET};
|
||||
|
||||
use types::{ApplicationSecret, Token};
|
||||
use authenticator_delegate::AuthenticatorDelegate;
|
||||
use crate::types::{ApplicationSecret, Token};
|
||||
use crate::authenticator_delegate::AuthenticatorDelegate;
|
||||
|
||||
const OOB_REDIRECT_URI: &'static str = "urn:ietf:wg:oauth:2.0:oob";
|
||||
|
||||
@@ -134,8 +134,8 @@ impl<C> InstalledFlow<C>
|
||||
where T: AsRef<str> + 'a,
|
||||
S: Iterator<Item = &'a T>
|
||||
{
|
||||
let authcode = try!(self.get_authorization_code(auth_delegate, &appsecret, scopes));
|
||||
let tokens = try!(self.request_token(&appsecret, &authcode));
|
||||
let authcode = self.get_authorization_code(auth_delegate, &appsecret, scopes)?;
|
||||
let tokens = self.request_token(&appsecret, &authcode)?;
|
||||
|
||||
// Successful response
|
||||
if tokens.access_token.is_some() {
|
||||
|
||||
27
src/lib.rs
27
src/lib.rs
@@ -38,13 +38,7 @@
|
||||
//! #[macro_use]
|
||||
//! extern crate serde_derive;
|
||||
//!
|
||||
//! extern crate hyper;
|
||||
//! extern crate hyper_native_tls;
|
||||
//! extern crate yup_oauth2 as oauth2;
|
||||
//! extern crate serde;
|
||||
//! extern crate serde_json;
|
||||
//!
|
||||
//! use oauth2::{Authenticator, DefaultAuthenticatorDelegate, PollInformation, ConsoleApplicationSecret, MemoryStorage, GetToken};
|
||||
//! use yup_oauth2::{Authenticator, DefaultAuthenticatorDelegate, PollInformation, ConsoleApplicationSecret, MemoryStorage, GetToken};
|
||||
//! use serde_json as json;
|
||||
//! use std::default::Default;
|
||||
//! use hyper::{Client, net::HttpsConnector};
|
||||
@@ -78,7 +72,6 @@ extern crate base64;
|
||||
extern crate chrono;
|
||||
extern crate hyper;
|
||||
extern crate hyper_native_tls;
|
||||
extern crate openssl;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate log;
|
||||
@@ -97,14 +90,14 @@ mod service_account;
|
||||
mod storage;
|
||||
mod types;
|
||||
|
||||
pub use device::{GOOGLE_DEVICE_CODE_URL, DeviceFlow};
|
||||
pub use refresh::{RefreshFlow, RefreshResult};
|
||||
pub use types::{Token, FlowType, ApplicationSecret, ConsoleApplicationSecret, Scheme, TokenType};
|
||||
pub use installed::{InstalledFlow, InstalledFlowReturnMethod};
|
||||
pub use storage::{TokenStorage, NullStorage, MemoryStorage, DiskTokenStorage};
|
||||
pub use authenticator::{Authenticator, Retry, GetToken};
|
||||
pub use authenticator_delegate::{AuthenticatorDelegate, DefaultAuthenticatorDelegate, PollError,
|
||||
pub use crate::device::{GOOGLE_DEVICE_CODE_URL, DeviceFlow};
|
||||
pub use crate::refresh::{RefreshFlow, RefreshResult};
|
||||
pub use crate::types::{Token, FlowType, ApplicationSecret, ConsoleApplicationSecret, Scheme, TokenType};
|
||||
pub use crate::installed::{InstalledFlow, InstalledFlowReturnMethod};
|
||||
pub use crate::storage::{TokenStorage, NullStorage, MemoryStorage, DiskTokenStorage};
|
||||
pub use crate::authenticator::{Authenticator, Retry, GetToken};
|
||||
pub use crate::authenticator_delegate::{AuthenticatorDelegate, DefaultAuthenticatorDelegate, PollError,
|
||||
PollInformation};
|
||||
pub use helper::*;
|
||||
pub use service_account::*;
|
||||
pub use crate::helper::*;
|
||||
pub use crate::service_account::*;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use types::{ApplicationSecret, FlowType, JsonError};
|
||||
use crate::types::{ApplicationSecret, FlowType, JsonError};
|
||||
|
||||
use chrono::Utc;
|
||||
use hyper;
|
||||
@@ -125,8 +125,8 @@ mod tests {
|
||||
use super::*;
|
||||
use super::super::FlowType;
|
||||
use yup_hyper_mock::{MockStream, SequentialConnector};
|
||||
use helper::parse_application_secret;
|
||||
use device::GOOGLE_DEVICE_CODE_URL;
|
||||
use crate::helper::parse_application_secret;
|
||||
use crate::device::GOOGLE_DEVICE_CODE_URL;
|
||||
|
||||
struct MockGoogleRefresh(SequentialConnector);
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ use std::io::Read;
|
||||
use std::result;
|
||||
use std::str;
|
||||
|
||||
use authenticator::GetToken;
|
||||
use storage::{hash_scopes, MemoryStorage, TokenStorage};
|
||||
use types::{StringError, Token};
|
||||
use crate::authenticator::GetToken;
|
||||
use crate::storage::{hash_scopes, MemoryStorage, TokenStorage};
|
||||
use crate::types::{StringError, Token};
|
||||
|
||||
use hyper::header;
|
||||
use url::form_urlencoded;
|
||||
@@ -45,7 +45,7 @@ fn encode_base64<T: AsRef<[u8]>>(s: T) -> String {
|
||||
|
||||
fn decode_rsa_key(pem_pkcs8: &str) -> Result<PKey<Private>, Box<error::Error>> {
|
||||
let private = pem_pkcs8.to_string().replace("\\n", "\n").into_bytes();
|
||||
Ok(try!(PKey::private_key_from_pem(&private)))
|
||||
Ok(PKey::private_key_from_pem(&private)?)
|
||||
}
|
||||
|
||||
/// JSON schema of secret service account key. You can obtain the key from
|
||||
@@ -103,11 +103,11 @@ impl JWT {
|
||||
|
||||
fn sign(&self, private_key: &str) -> Result<String, Box<error::Error>> {
|
||||
let mut jwt_head = self.encode_claims();
|
||||
let key = try!(decode_rsa_key(private_key));
|
||||
let mut signer = try!(Signer::new(MessageDigest::sha256(), &key));
|
||||
try!(signer.set_rsa_padding(Padding::PKCS1));
|
||||
try!(signer.update(jwt_head.as_bytes()));
|
||||
let signature = try!(signer.sign_to_vec());
|
||||
let key = decode_rsa_key(private_key)?;
|
||||
let mut signer = Signer::new(MessageDigest::sha256(), &key)?;
|
||||
signer.set_rsa_padding(Padding::PKCS1)?;
|
||||
signer.update(jwt_head.as_bytes())?;
|
||||
let signature = signer.sign_to_vec()?;
|
||||
let signature_b64 = encode_base64(signature);
|
||||
|
||||
jwt_head.push_str(".");
|
||||
@@ -205,8 +205,8 @@ impl<'a, C> ServiceAccountAccess<C>
|
||||
fn request_token(&mut self, scopes: &Vec<&str>) -> result::Result<Token, Box<error::Error>> {
|
||||
let mut claims = init_claims_from_key(&self.key, scopes);
|
||||
claims.sub = self.sub.clone();
|
||||
let signed = try!(JWT::new(claims)
|
||||
.sign(self.key.private_key.as_ref().unwrap()));
|
||||
let signed = JWT::new(claims)
|
||||
.sign(self.key.private_key.as_ref().unwrap())?;
|
||||
|
||||
let body = form_urlencoded::Serializer::new(String::new())
|
||||
.extend_pairs(vec![("grant_type".to_string(), GRANT_TYPE.to_string()),
|
||||
@@ -214,14 +214,14 @@ impl<'a, C> ServiceAccountAccess<C>
|
||||
.finish();
|
||||
|
||||
let mut response = String::new();
|
||||
let mut result = try!(self.client
|
||||
let mut result = self.client
|
||||
.borrow_mut()
|
||||
.post(self.key.token_uri.as_ref().unwrap())
|
||||
.body(&body)
|
||||
.header(header::ContentType("application/x-www-form-urlencoded".parse().unwrap()))
|
||||
.send());
|
||||
.send()?;
|
||||
|
||||
try!(result.read_to_string(&mut response));
|
||||
result.read_to_string(&mut response)?;
|
||||
|
||||
let token: Result<TokenResponse, serde_json::error::Error> =
|
||||
serde_json::from_str(&response);
|
||||
@@ -248,13 +248,13 @@ impl<C: BorrowMut<hyper::Client>> GetToken for ServiceAccountAccess<C> {
|
||||
{
|
||||
let (hash, scps) = hash_scopes(scopes);
|
||||
|
||||
if let Some(token) = try!(self.cache.get(hash, &scps)) {
|
||||
if let Some(token) = self.cache.get(hash, &scps)? {
|
||||
if !token.expired() {
|
||||
return Ok(token);
|
||||
}
|
||||
}
|
||||
|
||||
let token = try!(self.request_token(&scps));
|
||||
let token = self.request_token(&scps)?;
|
||||
let _ = self.cache.set(hash, &scps, Some(token.clone()));
|
||||
|
||||
Ok(token)
|
||||
@@ -268,11 +268,11 @@ impl<C: BorrowMut<hyper::Client>> GetToken for ServiceAccountAccess<C> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use helper::service_account_key_from_file;
|
||||
use crate::helper::service_account_key_from_file;
|
||||
use hyper;
|
||||
use hyper::net::HttpsConnector;
|
||||
use hyper_native_tls::NativeTlsClient;
|
||||
use authenticator::GetToken;
|
||||
use crate::authenticator::GetToken;
|
||||
|
||||
// This is a valid but deactivated key.
|
||||
const TEST_PRIVATE_KEY_PATH: &'static str = "examples/Sanguine-69411a0c0eea.json";
|
||||
|
||||
@@ -14,7 +14,7 @@ use std::hash::{Hash, Hasher};
|
||||
use std::io::{Read, Write};
|
||||
use std::io;
|
||||
|
||||
use types::Token;
|
||||
use crate::types::Token;
|
||||
|
||||
/// Implements a specialized storage to set and retrieve `Token` instances.
|
||||
/// The `scope_hash` represents the signature of the scopes for which the given token
|
||||
@@ -149,7 +149,7 @@ impl DiskTokenStorage {
|
||||
}
|
||||
|
||||
fn load_from_file(&mut self) -> Result<(), io::Error> {
|
||||
let mut f = try!(fs::OpenOptions::new().read(true).open(&self.location));
|
||||
let mut f = fs::OpenOptions::new().read(true).open(&self.location)?;
|
||||
let mut contents = String::new();
|
||||
|
||||
match f.read_to_string(&mut contents) {
|
||||
@@ -187,11 +187,11 @@ impl DiskTokenStorage {
|
||||
Result::Ok(s) => serialized = s,
|
||||
}
|
||||
|
||||
let mut f = try!(fs::OpenOptions::new()
|
||||
let mut f = fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.open(&self.location));
|
||||
.open(&self.location)?;
|
||||
f.write(serialized.as_ref()).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,9 +50,9 @@ impl fmt::Display for RequestError {
|
||||
RequestError::InvalidClient => "Invalid Client".fmt(f),
|
||||
RequestError::InvalidScope(ref scope) => writeln!(f, "Invalid Scope: '{}'", scope),
|
||||
RequestError::NegativeServerResponse(ref error, ref desc) => {
|
||||
try!(error.fmt(f));
|
||||
error.fmt(f)?;
|
||||
if let &Some(ref desc) = desc {
|
||||
try!(write!(f, ": {}", desc));
|
||||
write!(f, ": {}", desc)?;
|
||||
}
|
||||
"\n".fmt(f)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user