From 9b31070edbac3ba9e42dc08c81a48ec3fee8a728 Mon Sep 17 00:00:00 2001 From: Lewin Bormann Date: Sat, 16 Apr 2016 20:54:11 +0200 Subject: [PATCH] fix(installed): Genericize token/auth URI This means that in theory other providers besides Google could be used. --- src/helper.rs | 4 ++++ src/installed.rs | 35 ++++++++++++++++++++--------------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/helper.rs b/src/helper.rs index ed7a59d0b..5cb71a8c8 100644 --- a/src/helper.rs +++ b/src/helper.rs @@ -207,6 +207,8 @@ impl Authenticator let mut flow = InstalledFlow::new(self.client.borrow_mut(), installed_type); flow.obtain_token(&mut self.delegate, + &self.secret.auth_uri, + &self.secret.token_uri, &self.secret.client_id, &self.secret.client_secret, scopes.iter()) @@ -366,6 +368,8 @@ impl GetToken for Authenticator match match self.flow_type { FlowType::Device => self.retrieve_device_token(&scopes), + FlowType::InstalledInteractive => self.do_installed_flow(&scopes), + FlowType::InstalledRedirect(_) => self.do_installed_flow(&scopes), } { Ok(token) => { diff --git a/src/installed.rs b/src/installed.rs index 7e95fd077..49da82ffb 100644 --- a/src/installed.rs +++ b/src/installed.rs @@ -1,8 +1,7 @@ -/* - * Copyright (c) 2016 Google Inc (lewinb@google.com). - * - * Refer to the project root for licensing information. - */ +// Copyright (c) 2016 Google Inc (lewinb@google.com). +// +// Refer to the project root for licensing information. +// extern crate serde_json; extern crate url; @@ -28,7 +27,8 @@ const OOB_REDIRECT_URI: &'static str = "urn:ietf:wg:oauth:2.0:oob"; /// Assembles a URL to request an authorization token (with user interaction). /// Note that the redirect_uri here has to be either None or some variation of /// http://localhost:{port}, or the authorization won't work (error "redirect_uri_mismatch") -fn build_authentication_request_url<'a, T, I>(client_id: &str, +fn build_authentication_request_url<'a, T, I>(auth_uri: &str, + client_id: &str, scopes: I, redirect_uri: Option) -> String @@ -44,8 +44,8 @@ fn build_authentication_request_url<'a, T, I>(client_id: &str, // Remove last space scopes_string.pop(); - url.push_str("https://accounts.google.com/o/oauth2/v2/auth?"); - vec![format!("scope={}", scopes_string), + url.push_str(auth_uri); + vec![format!("?scope={}", scopes_string), format!("&redirect_uri={}", redirect_uri.unwrap_or(OOB_REDIRECT_URI.to_string())), format!("&response_type=code"), @@ -128,6 +128,8 @@ impl InstalledFlow where C: BorrowMut /// It's recommended not to use the DefaultAuthenticatorDelegate, but a specialized one. pub fn obtain_token<'a, AD: AuthenticatorDelegate, S, T>(&mut self, auth_delegate: &mut AD, + auth_uri: &str, + token_uri: &str, client_id: &str, client_secret: &str, scopes: S) @@ -136,8 +138,8 @@ impl InstalledFlow where C: BorrowMut S: Iterator { use std::error::Error; - let authcode = try!(self.get_authorization_code(auth_delegate, client_id, scopes)); - let tokens = try!(self.request_token(client_secret, client_id, &authcode)); + let authcode = try!(self.get_authorization_code(auth_delegate, auth_uri, client_id, scopes)); + let tokens = try!(self.request_token(token_uri, client_secret, client_id, &authcode)); // Successful response if tokens.access_token.is_some() { @@ -166,6 +168,7 @@ impl InstalledFlow where C: BorrowMut /// TODO(dermesser): Add timeout configurability! fn get_authorization_code<'a, AD: AuthenticatorDelegate, S, T>(&mut self, auth_delegate: &mut AD, + auth_uri: &str, client_id: &str, scopes: S) -> Result> @@ -174,7 +177,7 @@ impl InstalledFlow where C: BorrowMut { let result: Result> = match self.server { None => { - let url = build_authentication_request_url(client_id, scopes, None); + let url = build_authentication_request_url(auth_uri, client_id, scopes, None); match auth_delegate.present_user_url(&url, true /* need_code */) { None => { Result::Err(Box::new(io::Error::new(io::ErrorKind::UnexpectedEof, @@ -190,7 +193,7 @@ impl InstalledFlow where C: BorrowMut Some(_) => { // The redirect URI must be this very localhost URL, otherwise Google refuses // authorization. - let url = build_authentication_request_url(client_id, + let url = build_authentication_request_url(auth_uri, client_id, scopes, Some(format!("http://localhost:{}", self.port @@ -209,6 +212,7 @@ impl InstalledFlow where C: BorrowMut /// Sends the authorization code to the provider in order to obtain access and refresh tokens. fn request_token(&mut self, + token_uri: &str, client_secret: &str, client_id: &str, authcode: &str) @@ -232,7 +236,7 @@ impl InstalledFlow where C: BorrowMut let result: Result = self.client .borrow_mut() - .post("https://www.googleapis.com/oauth2/v4/token") + .post(token_uri) .body(&body) .header(header::ContentType("application/x-www-form-urlencoded".parse().unwrap())) .send(); @@ -332,10 +336,11 @@ mod tests { #[test] fn test_request_url_builder() { assert_eq!("https://accounts.google.\ - com/o/oauth2/v2/auth?scope=email%20profile&redirect_uri=urn:ietf:wg:oauth:2.\ + com/o/oauth2/auth?scope=email%20profile&redirect_uri=urn:ietf:wg:oauth:2.\ 0:oob&response_type=code&client_id=812741506391-h38jh0j4fv0ce1krdkiq0hfvt6n5a\ mrf.apps.googleusercontent.com", - build_authentication_request_url("812741506391-h38jh0j4fv0ce1krdkiq0hfvt6n5am\ + build_authentication_request_url("https://accounts.google.com/o/oauth2/auth", + "812741506391-h38jh0j4fv0ce1krdkiq0hfvt6n5am\ rf.apps.googleusercontent.com", vec![&"email".to_string(), &"profile".to_string()],