Files
yup-oauth2/examples/custom_storage.rs
Daniel Rodgers-Pryor 6e4503f55e Simplify with_storage interface
By only allowing a custom storage. To use one of the built-in storage mechanism, there is already a special-purpose `persist_tokens_to_disk` method available.
2021-03-25 21:20:21 +11:00

91 lines
2.7 KiB
Rust

//! Demonstrating how to create a custom token store
use anyhow::anyhow;
use async_trait::async_trait;
use std::sync::RwLock;
use yup_oauth2::storage::{TokenInfo, TokenStorage};
struct ExampleTokenStore {
store: RwLock<Vec<StoredToken>>,
}
struct StoredToken {
scopes: Vec<String>,
serialized_token: String,
}
/// Is this set of scopes covered by the other? Returns true if the other
/// set is a superset of this one. Use this when implementing TokenStorage.get()
fn scopes_covered_by(scopes: &[&str], possible_match_or_superset: &[&str]) -> bool {
scopes
.iter()
.all(|s| possible_match_or_superset.iter().any(|t| t == s))
}
/// Here we implement our own token storage. You could write the serialized token and scope data
/// to disk, an OS keychain, a database or whatever suits your use-case
#[async_trait]
impl TokenStorage for ExampleTokenStore {
async fn set(&self, scopes: &[&str], token: TokenInfo) -> anyhow::Result<()> {
let data = serde_json::to_string(&token).unwrap();
println!("Storing token for scopes {:?}", scopes);
let mut store = self
.store
.write()
.map_err(|_| anyhow!("Unable to lock store for writing"))?;
store.push(StoredToken {
scopes: scopes.iter().map(|str| str.to_string()).collect(),
serialized_token: data,
});
Ok(())
}
async fn get(&self, target_scopes: &[&str]) -> Option<TokenInfo> {
// Retrieve the token data
self.store.read().ok().and_then(|store| {
for stored_token in store.iter() {
if scopes_covered_by(
target_scopes,
&stored_token
.scopes
.iter()
.map(|s| &s[..])
.collect::<Vec<_>>()[..],
) {
return serde_json::from_str(&stored_token.serialized_token).ok();
}
}
None
})
}
}
#[tokio::main]
async fn main() {
// Put your client secret in the working directory!
let sec = yup_oauth2::read_application_secret("client_secret.json")
.await
.expect("client secret couldn't be read.");
let auth = yup_oauth2::InstalledFlowAuthenticator::builder(
sec,
yup_oauth2::InstalledFlowReturnMethod::HTTPRedirect,
)
.with_storage(Box::new(ExampleTokenStore {
store: RwLock::new(vec![]),
}))
.build()
.await
.expect("InstalledFlowAuthenticator failed to build");
let scopes = &["https://www.googleapis.com/auth/drive.file"];
match auth.token(scopes).await {
Err(e) => println!("error: {:?}", e),
Ok(t) => println!("The token is {:?}", t),
}
}