Updating the fxa-client example
Added flags to: - Request the session scope. - Control how log messages get printed to the console. Updated the code to re-authenticated using the existing data rather than throwing it away and starting from scratch. These changes make it possible to repro https://bugzilla.mozilla.org/show_bug.cgi?id=1887071 - run `cargo run -- --log -d devices` with fresh credentials. - Any command should do, but I used `devices` - The client should ask you to login and paste your credentials - You should see the device list printed out - In a browser session, change your FxA password - run `cargo run -- --log -d devices` again - The client should tell you there was an auth-problem and ask you to reauthenticate. - After you paste the reauthentication URL you should see an error printed out
This commit is contained in:
Родитель
e6ccfed09e
Коммит
6c6951cdfe
|
@ -1003,6 +1003,15 @@ dependencies = [
|
|||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "difference"
|
||||
version = "2.0.0"
|
||||
|
@ -1397,6 +1406,8 @@ dependencies = [
|
|||
"clap 4.2.2",
|
||||
"cli-support",
|
||||
"fxa-client",
|
||||
"log",
|
||||
"simple_logger",
|
||||
"sync15",
|
||||
"url",
|
||||
"viaduct-reqwest",
|
||||
|
@ -2740,6 +2751,12 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
|
@ -3144,6 +3161,12 @@ dependencies = [
|
|||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.16"
|
||||
|
@ -3788,18 +3811,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.164"
|
||||
version = "1.0.193"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
|
||||
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.164"
|
||||
version = "1.0.193"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
|
||||
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -3896,6 +3919,18 @@ version = "2.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3"
|
||||
|
||||
[[package]]
|
||||
name = "simple_logger"
|
||||
version = "4.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e7e46c8c90251d47d08b28b8a419ffb4aede0f87c2eea95e17d1d5bacbf3ef1"
|
||||
dependencies = [
|
||||
"colored",
|
||||
"log",
|
||||
"time",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.10"
|
||||
|
@ -4284,20 +4319,36 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.11"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217"
|
||||
checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa 1.0.9",
|
||||
"libc",
|
||||
"num-conv",
|
||||
"num_threads",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.4"
|
||||
name = "time-core"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinytemplate"
|
||||
|
|
|
@ -11,7 +11,7 @@ use autofill::db::{
|
|||
};
|
||||
use autofill::encryption::{create_autofill_key, EncryptorDecryptor};
|
||||
use autofill::error::Error;
|
||||
use cli_support::fxa_creds::{get_cli_fxa, get_default_fxa_config};
|
||||
use cli_support::fxa_creds::{get_cli_fxa, get_default_fxa_config, SYNC_SCOPE};
|
||||
use cli_support::prompt::{prompt_string, prompt_usize};
|
||||
use interrupt_support::NeverInterrupts; // XXX need a real interruptee!
|
||||
use std::sync::Arc;
|
||||
|
@ -357,7 +357,7 @@ fn run_sync(
|
|||
wait: u64,
|
||||
) -> Result<()> {
|
||||
// XXX - need to add interrupts
|
||||
let cli_fxa = get_cli_fxa(get_default_fxa_config(), &cred_file)?;
|
||||
let cli_fxa = get_cli_fxa(get_default_fxa_config(), &cred_file, &[SYNC_SCOPE])?;
|
||||
|
||||
if wipe_all {
|
||||
Sync15StorageClient::new(cli_fxa.client_init.clone())?.wipe_all_remote()?;
|
||||
|
|
|
@ -24,7 +24,8 @@ use crate::prompt::prompt_string;
|
|||
// working option.
|
||||
const CLIENT_ID: &str = "3c49430b43dfba77";
|
||||
const REDIRECT_URI: &str = "https://accounts.firefox.com/oauth/success/3c49430b43dfba77";
|
||||
const SYNC_SCOPE: &str = "https://identity.mozilla.com/apps/oldsync";
|
||||
pub const SYNC_SCOPE: &str = "https://identity.mozilla.com/apps/oldsync";
|
||||
pub const SESSION_SCOPE: &str = "https://identity.mozilla.com/tokens/session";
|
||||
|
||||
fn load_fxa_creds(path: &str) -> Result<FirefoxAccount> {
|
||||
let mut file = fs::File::open(path)?;
|
||||
|
@ -33,20 +34,25 @@ fn load_fxa_creds(path: &str) -> Result<FirefoxAccount> {
|
|||
Ok(FirefoxAccount::from_json(&s)?)
|
||||
}
|
||||
|
||||
fn load_or_create_fxa_creds(path: &str, cfg: FxaConfig) -> Result<FirefoxAccount> {
|
||||
fn load_or_create_fxa_creds(path: &str, cfg: FxaConfig, scopes: &[&str]) -> Result<FirefoxAccount> {
|
||||
load_fxa_creds(path).or_else(|e| {
|
||||
log::info!(
|
||||
"Failed to load existing FxA credentials from {:?} (error: {}), launching OAuth flow",
|
||||
path,
|
||||
e
|
||||
);
|
||||
create_fxa_creds(path, cfg)
|
||||
create_fxa_creds(path, cfg, scopes)
|
||||
})
|
||||
}
|
||||
|
||||
fn create_fxa_creds(path: &str, cfg: FxaConfig) -> Result<FirefoxAccount> {
|
||||
fn create_fxa_creds(path: &str, cfg: FxaConfig, scopes: &[&str]) -> Result<FirefoxAccount> {
|
||||
let acct = FirefoxAccount::new(cfg);
|
||||
let oauth_uri = acct.begin_oauth_flow(&[SYNC_SCOPE], "fxa_creds")?;
|
||||
handle_oauth_flow(path, &acct, scopes)?;
|
||||
Ok(acct)
|
||||
}
|
||||
|
||||
fn handle_oauth_flow(path: &str, acct: &FirefoxAccount, scopes: &[&str]) -> Result<()> {
|
||||
let oauth_uri = acct.begin_oauth_flow(scopes, "fxa_creds")?;
|
||||
|
||||
if webbrowser::open(oauth_uri.as_ref()).is_err() {
|
||||
log::warn!("Failed to open a web browser D:");
|
||||
|
@ -68,7 +74,7 @@ fn create_fxa_creds(path: &str, cfg: FxaConfig) -> Result<FirefoxAccount> {
|
|||
let mut file = fs::File::create(path)?;
|
||||
write!(file, "{}", acct.to_json()?)?;
|
||||
file.flush()?;
|
||||
Ok(acct)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Our public functions. It would be awesome if we could somehow integrate
|
||||
|
@ -81,9 +87,10 @@ pub fn get_default_fxa_config() -> FxaConfig {
|
|||
pub fn get_account_and_token(
|
||||
config: FxaConfig,
|
||||
cred_file: &str,
|
||||
scopes: &[&str],
|
||||
) -> Result<(FirefoxAccount, AccessTokenInfo)> {
|
||||
// TODO: we should probably set a persist callback on acct?
|
||||
let mut acct = load_or_create_fxa_creds(cred_file, config.clone())?;
|
||||
let acct = load_or_create_fxa_creds(cred_file, config.clone(), scopes)?;
|
||||
// `scope` could be a param, but I can't see it changing.
|
||||
match acct.get_access_token(SYNC_SCOPE, None) {
|
||||
Ok(t) => Ok((acct, t)),
|
||||
|
@ -91,8 +98,9 @@ pub fn get_account_and_token(
|
|||
match e {
|
||||
// We can retry an auth error.
|
||||
FxaError::Authentication => {
|
||||
println!("Saw an auth error using stored credentials - recreating them...");
|
||||
acct = create_fxa_creds(cred_file, config)?;
|
||||
println!("Saw an auth error using stored credentials - attempting to re-authenticate");
|
||||
println!("If fails, consider deleting {cred_file} to start from scratch");
|
||||
handle_oauth_flow(cred_file, &acct, scopes)?;
|
||||
let token = acct.get_access_token(SYNC_SCOPE, None)?;
|
||||
Ok((acct, token))
|
||||
}
|
||||
|
@ -102,8 +110,8 @@ pub fn get_account_and_token(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_cli_fxa(config: FxaConfig, cred_file: &str) -> Result<CliFxa> {
|
||||
let (account, token_info) = match get_account_and_token(config, cred_file) {
|
||||
pub fn get_cli_fxa(config: FxaConfig, cred_file: &str, scopes: &[&str]) -> Result<CliFxa> {
|
||||
let (account, token_info) = match get_account_and_token(config, cred_file, scopes) {
|
||||
Ok(v) => v,
|
||||
Err(e) => anyhow::bail!("Failed to use saved credentials. {}", e),
|
||||
};
|
||||
|
|
|
@ -8,6 +8,8 @@ publish = false
|
|||
|
||||
[dependencies]
|
||||
viaduct-reqwest = { path = "../../components/support/viaduct-reqwest" }
|
||||
log = "0.4"
|
||||
simple_logger = "4"
|
||||
clap = {version = "4.2", features = ["derive"]}
|
||||
cli-support = { path = "../cli-support" }
|
||||
fxa-client = { path = "../../components/fxa-client" }
|
||||
|
|
|
@ -8,7 +8,7 @@ mod send_tab;
|
|||
use std::fs;
|
||||
|
||||
use clap::{Parser, Subcommand, ValueEnum};
|
||||
use cli_support::fxa_creds::get_cli_fxa;
|
||||
use cli_support::fxa_creds;
|
||||
use fxa_client::{FirefoxAccount, FxaConfig, FxaServer};
|
||||
|
||||
static CREDENTIALS_PATH: &str = "credentials.json";
|
||||
|
@ -24,6 +24,22 @@ struct Cli {
|
|||
#[arg(value_enum, default_value_t = Server::Release)]
|
||||
server: Server,
|
||||
|
||||
/// Request a session scope
|
||||
#[clap(long, short, action)]
|
||||
session_scope: bool,
|
||||
|
||||
/// Print out log to the console. The default level is WARN
|
||||
#[clap(long, short, action)]
|
||||
log: bool,
|
||||
|
||||
/// Set the logging level to INFO
|
||||
#[clap(long, short, action)]
|
||||
info: bool,
|
||||
|
||||
/// Set the logging level to DEBUG
|
||||
#[clap(long, short, action)]
|
||||
debug: bool,
|
||||
|
||||
#[command(subcommand)]
|
||||
command: Command,
|
||||
}
|
||||
|
@ -52,9 +68,24 @@ enum Command {
|
|||
fn main() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
viaduct_reqwest::use_reqwest_backend();
|
||||
if cli.log {
|
||||
if cli.debug {
|
||||
simple_logger::init_with_level(log::Level::Debug).unwrap();
|
||||
} else if cli.info {
|
||||
simple_logger::init_with_level(log::Level::Info).unwrap();
|
||||
} else {
|
||||
simple_logger::init_with_level(log::Level::Warn).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
let scopes: &[&str] = if cli.session_scope {
|
||||
&[fxa_creds::SYNC_SCOPE, fxa_creds::SESSION_SCOPE]
|
||||
} else {
|
||||
&[fxa_creds::SYNC_SCOPE]
|
||||
};
|
||||
|
||||
println!();
|
||||
let account = load_account(&cli)?;
|
||||
let account = load_account(&cli, scopes)?;
|
||||
match cli.command {
|
||||
Command::Devices(args) => devices::run(&account, args),
|
||||
Command::SendTab(args) => send_tab::run(&account, args),
|
||||
|
@ -67,7 +98,7 @@ fn main() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn load_account(cli: &Cli) -> Result<FirefoxAccount> {
|
||||
fn load_account(cli: &Cli, scopes: &[&str]) -> Result<FirefoxAccount> {
|
||||
let config = FxaConfig {
|
||||
server: match cli.server {
|
||||
Server::Release => FxaServer::Release,
|
||||
|
@ -80,7 +111,7 @@ fn load_account(cli: &Cli) -> Result<FirefoxAccount> {
|
|||
client_id: CLIENT_ID.into(),
|
||||
token_server_url_override: None,
|
||||
};
|
||||
get_cli_fxa(config, CREDENTIALS_PATH).map(|cli| cli.account)
|
||||
fxa_creds::get_cli_fxa(config, CREDENTIALS_PATH, scopes).map(|cli| cli.account)
|
||||
}
|
||||
|
||||
pub fn persist_fxa_state(acct: &FirefoxAccount) -> Result<()> {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use cli_support::fxa_creds::{get_cli_fxa, get_default_fxa_config};
|
||||
use cli_support::fxa_creds::{get_cli_fxa, get_default_fxa_config, SYNC_SCOPE};
|
||||
use interrupt_support::Interruptee;
|
||||
use places::storage::bookmarks::{
|
||||
json_tree::{
|
||||
|
@ -237,7 +237,7 @@ fn sync(
|
|||
) -> Result<()> {
|
||||
use_reqwest_backend();
|
||||
|
||||
let cli_fxa = get_cli_fxa(get_default_fxa_config(), &cred_file)?;
|
||||
let cli_fxa = get_cli_fxa(get_default_fxa_config(), &cred_file, &[SYNC_SCOPE])?;
|
||||
|
||||
if wipe_all {
|
||||
Sync15StorageClient::new(cli_fxa.client_init.clone())?.wipe_all_remote()?;
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
|
||||
use cli_support::fxa_creds::{get_account_and_token, get_cli_fxa, get_default_fxa_config};
|
||||
use cli_support::fxa_creds::{
|
||||
get_account_and_token, get_cli_fxa, get_default_fxa_config, SYNC_SCOPE,
|
||||
};
|
||||
use cli_support::prompt::{prompt_char, prompt_string, prompt_usize};
|
||||
use logins::encryption::{create_key, EncryptorDecryptor};
|
||||
use logins::{
|
||||
|
@ -475,12 +477,12 @@ fn main() -> Result<()> {
|
|||
}
|
||||
'S' | 's' => {
|
||||
log::info!("Syncing!");
|
||||
let (_, token_info) = get_account_and_token(get_default_fxa_config(), cred_file)?;
|
||||
let (_, token_info) = get_account_and_token(get_default_fxa_config(), cred_file, &[SYNC_SCOPE])?;
|
||||
let sync_key = URL_SAFE_NO_PAD.encode(
|
||||
token_info.key.unwrap().key_bytes()?,
|
||||
);
|
||||
// TODO: allow users to use stage/etc.
|
||||
let cli_fxa = get_cli_fxa(get_default_fxa_config(), cred_file)?;
|
||||
let cli_fxa = get_cli_fxa(get_default_fxa_config(), cred_file, &[SYNC_SCOPE])?;
|
||||
match do_sync(
|
||||
Arc::clone(&store),
|
||||
cli_fxa.client_init.key_id.clone(),
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
|
||||
use cli_support::fxa_creds::{get_account_and_token, get_cli_fxa, get_default_fxa_config};
|
||||
use cli_support::fxa_creds::{
|
||||
get_account_and_token, get_cli_fxa, get_default_fxa_config, SYNC_SCOPE,
|
||||
};
|
||||
use cli_support::prompt::{prompt_char, prompt_string};
|
||||
use interrupt_support::NeverInterrupts;
|
||||
use std::path::Path;
|
||||
|
@ -100,10 +102,11 @@ fn main() -> Result<()> {
|
|||
cli_support::init_logging();
|
||||
let opts = Opts::from_args();
|
||||
|
||||
let (_, token_info) = get_account_and_token(get_default_fxa_config(), &opts.creds_file)?;
|
||||
let (_, token_info) =
|
||||
get_account_and_token(get_default_fxa_config(), &opts.creds_file, &[SYNC_SCOPE])?;
|
||||
let sync_key = URL_SAFE_NO_PAD.encode(token_info.key.unwrap().key_bytes()?);
|
||||
|
||||
let cli_fxa = get_cli_fxa(get_default_fxa_config(), &opts.creds_file)?;
|
||||
let cli_fxa = get_cli_fxa(get_default_fxa_config(), &opts.creds_file, &[SYNC_SCOPE])?;
|
||||
let device_id = cli_fxa.account.get_current_device_id()?;
|
||||
|
||||
let store = Arc::new(TabsStore::new(Path::new(&opts.db_path)));
|
||||
|
|
|
@ -4,7 +4,7 @@ http://creativecommons.org/publicdomain/zero/1.0/ */
|
|||
#![allow(unknown_lints)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use cli_support::fxa_creds::{get_cli_fxa, get_default_fxa_config};
|
||||
use cli_support::fxa_creds::{get_cli_fxa, get_default_fxa_config, SYNC_SCOPE};
|
||||
use std::{collections::HashSet, process};
|
||||
use std::sync::Arc;
|
||||
use structopt::StructOpt;
|
||||
|
@ -78,7 +78,7 @@ pub fn run_test_group(opts: &Opts, group: TestGroup) {
|
|||
}
|
||||
|
||||
let cfg = get_default_fxa_config();
|
||||
let cli_fxa = get_cli_fxa(cfg, &opts.credential_file).expect("can't initialize cli");
|
||||
let cli_fxa = get_cli_fxa(cfg, &opts.credential_file, &[SYNC_SCOPE]).expect("can't initialize cli");
|
||||
let acct = Arc::new(cli_fxa);
|
||||
|
||||
let mut user = TestUser::new(acct, 2).expect("Failed to get test user.");
|
||||
|
|
Загрузка…
Ссылка в новой задаче