mirror of
https://github.com/OMGeeky/yup-oauth2.git
synced 2026-01-05 19:00:29 +01:00
Merge pull request #170 from FEC-bendingspoons/master
Add authorized user authenticator
This commit is contained in:
@@ -3,6 +3,7 @@ use crate::application_default_credentials::{
|
||||
ApplicationDefaultCredentialsFlow, ApplicationDefaultCredentialsFlowOpts,
|
||||
};
|
||||
use crate::authenticator_delegate::{DeviceFlowDelegate, InstalledFlowDelegate};
|
||||
use crate::authorized_user::{AuthorizedUserFlow, AuthorizedUserSecret};
|
||||
use crate::device::DeviceFlow;
|
||||
use crate::error::Error;
|
||||
use crate::installed::{InstalledFlow, InstalledFlowReturnMethod};
|
||||
@@ -360,6 +361,40 @@ where
|
||||
InstanceMetadata(AuthenticatorBuilder<C, ApplicationDefaultCredentialsFlowOpts>),
|
||||
}
|
||||
|
||||
/// Create an authenticator that uses an authorized user credentials.
|
||||
/// ```
|
||||
/// # async fn foo() {
|
||||
/// # use yup_oauth2::authenticator::AuthorizedUserAuthenticator;
|
||||
/// # let secret = yup_oauth2::read_authorized_user_secret("/tmp/foo").await.unwrap();
|
||||
/// let authenticator = yup_oauth2::AuthorizedUserAuthenticator::builder(secret)
|
||||
/// .build()
|
||||
/// .await
|
||||
/// .expect("failed to create authenticator");
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct AuthorizedUserAuthenticator;
|
||||
impl AuthorizedUserAuthenticator {
|
||||
/// Use the builder pattern to create an Authenticator that uses an authorized user.
|
||||
pub fn builder(
|
||||
authorized_user_secret: AuthorizedUserSecret,
|
||||
) -> AuthenticatorBuilder<DefaultHyperClient, AuthorizedUserFlow> {
|
||||
Self::with_client(authorized_user_secret, DefaultHyperClient)
|
||||
}
|
||||
|
||||
/// Construct a new Authenticator that uses the installed flow and the provided http client.
|
||||
pub fn with_client<C>(
|
||||
authorized_user_secret: AuthorizedUserSecret,
|
||||
client: C,
|
||||
) -> AuthenticatorBuilder<C, AuthorizedUserFlow> {
|
||||
AuthenticatorBuilder::new(
|
||||
AuthorizedUserFlow {
|
||||
secret: authorized_user_secret,
|
||||
},
|
||||
client,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// ## Methods available when building any Authenticator.
|
||||
/// ```
|
||||
/// # #[cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))]
|
||||
@@ -603,8 +638,25 @@ impl<C> AuthenticatorBuilder<C, ApplicationDefaultCredentialsFlowOpts> {
|
||||
}
|
||||
}
|
||||
|
||||
/// ## Methods available when building an authorized user flow Authenticator.
|
||||
impl<C> AuthenticatorBuilder<C, AuthorizedUserFlow> {
|
||||
/// Create the authenticator.
|
||||
pub async fn build(self) -> io::Result<Authenticator<C::Connector>>
|
||||
where
|
||||
C: HyperClientBuilder,
|
||||
{
|
||||
Self::common_build(
|
||||
self.hyper_client_builder,
|
||||
self.storage_type,
|
||||
AuthFlow::AuthorizedUserFlow(self.auth_flow),
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
mod private {
|
||||
use crate::application_default_credentials::ApplicationDefaultCredentialsFlow;
|
||||
use crate::authorized_user::AuthorizedUserFlow;
|
||||
use crate::device::DeviceFlow;
|
||||
use crate::error::Error;
|
||||
use crate::installed::InstalledFlow;
|
||||
@@ -618,6 +670,7 @@ mod private {
|
||||
#[cfg(feature = "service_account")]
|
||||
ServiceAccountFlow(ServiceAccountFlow),
|
||||
ApplicationDefaultCredentialsFlow(ApplicationDefaultCredentialsFlow),
|
||||
AuthorizedUserFlow(AuthorizedUserFlow),
|
||||
}
|
||||
|
||||
impl AuthFlow {
|
||||
@@ -628,6 +681,7 @@ mod private {
|
||||
#[cfg(feature = "service_account")]
|
||||
AuthFlow::ServiceAccountFlow(_) => None,
|
||||
AuthFlow::ApplicationDefaultCredentialsFlow(_) => None,
|
||||
AuthFlow::AuthorizedUserFlow(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -652,6 +706,9 @@ mod private {
|
||||
AuthFlow::ApplicationDefaultCredentialsFlow(service_account_flow) => {
|
||||
service_account_flow.token(hyper_client, scopes).await
|
||||
}
|
||||
AuthFlow::AuthorizedUserFlow(authorized_user_flow) => {
|
||||
authorized_user_flow.token(hyper_client, scopes).await
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
69
src/authorized_user.rs
Normal file
69
src/authorized_user.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
//! This module provides a token source (`GetToken`) that obtains tokens using user credentials
|
||||
//! for use by software (i.e., non-human actors) to get access to Google services.
|
||||
//!
|
||||
//! Resources:
|
||||
//! - [gcloud auth application-default login](https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login)
|
||||
//!
|
||||
use crate::error::Error;
|
||||
use crate::types::TokenInfo;
|
||||
use hyper::header;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::form_urlencoded;
|
||||
|
||||
const TOKEN_URI: &'static str = "https://accounts.google.com/o/oauth2/token";
|
||||
|
||||
/// JSON schema of authorized user secret. You can obtain it by
|
||||
/// running on the client: `gcloud auth application-default login`.
|
||||
///
|
||||
/// You can use `helpers::read_authorized_user_secret()` to read a JSON file
|
||||
/// into a `AuthorizedUserSecret`.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct AuthorizedUserSecret {
|
||||
/// client_id
|
||||
pub client_id: String,
|
||||
/// client_secret
|
||||
pub client_secret: String,
|
||||
/// refresh_token
|
||||
pub refresh_token: String,
|
||||
#[serde(rename = "type")]
|
||||
/// key_type
|
||||
pub key_type: String,
|
||||
}
|
||||
|
||||
/// AuthorizedUserFlow can fetch oauth tokens using an authorized user secret.
|
||||
pub struct AuthorizedUserFlow {
|
||||
pub(crate) secret: AuthorizedUserSecret,
|
||||
}
|
||||
|
||||
impl AuthorizedUserFlow {
|
||||
/// Send a request for a new Bearer token to the OAuth provider.
|
||||
pub(crate) async fn token<C, T>(
|
||||
&self,
|
||||
hyper_client: &hyper::Client<C>,
|
||||
_scopes: &[T],
|
||||
) -> Result<TokenInfo, Error>
|
||||
where
|
||||
T: AsRef<str>,
|
||||
C: hyper::client::connect::Connect + Clone + Send + Sync + 'static,
|
||||
{
|
||||
let req = form_urlencoded::Serializer::new(String::new())
|
||||
.extend_pairs(&[
|
||||
("client_id", self.secret.client_id.as_str()),
|
||||
("client_secret", self.secret.client_secret.as_str()),
|
||||
("refresh_token", self.secret.refresh_token.as_str()),
|
||||
("grant_type", "refresh_token"),
|
||||
])
|
||||
.finish();
|
||||
|
||||
let request = hyper::Request::post(TOKEN_URI)
|
||||
.header(header::CONTENT_TYPE, "application/x-www-form-urlencoded")
|
||||
.body(hyper::Body::from(req))
|
||||
.unwrap();
|
||||
|
||||
log::debug!("requesting token from authorized user: {:?}", request);
|
||||
let (head, body) = hyper_client.request(request).await?.into_parts();
|
||||
let body = hyper::body::to_bytes(body).await?;
|
||||
log::debug!("received response; head: {:?}, body: {:?}", head, body);
|
||||
TokenInfo::from_json(&body)
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,11 @@
|
||||
// Copyright (c) 2016 Google Inc (lewinb@google.com).
|
||||
//
|
||||
// Refer to the project root for licensing information.
|
||||
use crate::authorized_user::AuthorizedUserSecret;
|
||||
use crate::types::{ApplicationSecret, ConsoleApplicationSecret};
|
||||
|
||||
#[cfg(feature = "service_account")]
|
||||
use crate::service_account::ServiceAccountKey;
|
||||
use crate::types::{ApplicationSecret, ConsoleApplicationSecret};
|
||||
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
@@ -57,6 +59,22 @@ pub fn parse_service_account_key<S: AsRef<[u8]>>(key: S) -> io::Result<ServiceAc
|
||||
})
|
||||
}
|
||||
|
||||
/// Read an authorized user secret from a JSON file. You can obtain it by running on the client:
|
||||
/// `gcloud auth application-default login`.
|
||||
/// The file should be on Windows in: `%APPDATA%/gcloud/application_default_credentials.json`
|
||||
/// for other systems: `$HOME/.config/gcloud/application_default_credentials.json`.
|
||||
pub async fn read_authorized_user_secret<P: AsRef<Path>>(
|
||||
path: P,
|
||||
) -> io::Result<AuthorizedUserSecret> {
|
||||
let key = tokio::fs::read(path).await?;
|
||||
serde_json::from_slice(&key).map_err(|e| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!("Bad authorized user secret: {}", e),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn join<T>(pieces: &[T], separator: &str) -> String
|
||||
where
|
||||
T: AsRef<str>,
|
||||
|
||||
11
src/lib.rs
11
src/lib.rs
@@ -75,6 +75,7 @@
|
||||
mod application_default_credentials;
|
||||
pub mod authenticator;
|
||||
pub mod authenticator_delegate;
|
||||
mod authorized_user;
|
||||
mod device;
|
||||
pub mod error;
|
||||
mod helper;
|
||||
@@ -90,13 +91,13 @@ pub mod storage;
|
||||
|
||||
mod types;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use crate::authenticator::{
|
||||
ApplicationDefaultCredentialsAuthenticator, DeviceFlowAuthenticator,
|
||||
InstalledFlowAuthenticator
|
||||
};
|
||||
#[cfg(feature = "service_account")]
|
||||
pub use crate::authenticator::ServiceAccountAuthenticator;
|
||||
#[doc(inline)]
|
||||
pub use crate::authenticator::{
|
||||
ApplicationDefaultCredentialsAuthenticator, AuthorizedUserAuthenticator,
|
||||
DeviceFlowAuthenticator, InstalledFlowAuthenticator,
|
||||
};
|
||||
|
||||
pub use crate::helper::*;
|
||||
pub use crate::installed::InstalledFlowReturnMethod;
|
||||
|
||||
Reference in New Issue
Block a user