| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- use std::path::Path;
- use anyhow::{anyhow, Result};
- use cdk::mint_url::MintUrl;
- use cdk::nuts::MintInfo;
- use cdk::wallet::MultiMintWallet;
- use cdk::OidcClient;
- use clap::Args;
- use serde::{Deserialize, Serialize};
- use crate::token_storage;
- #[derive(Args, Serialize, Deserialize)]
- pub struct CatLoginSubCommand {
- /// Mint url
- mint_url: MintUrl,
- /// Username
- username: String,
- /// Password
- password: String,
- }
- pub async fn cat_login(
- multi_mint_wallet: &MultiMintWallet,
- sub_command_args: &CatLoginSubCommand,
- work_dir: &Path,
- ) -> Result<()> {
- let mint_url = sub_command_args.mint_url.clone();
- // Ensure the mint exists
- if !multi_mint_wallet.has_mint(&mint_url).await {
- multi_mint_wallet.add_mint(mint_url.clone()).await?;
- }
- let mint_info = multi_mint_wallet
- .fetch_mint_info(&mint_url)
- .await?
- .ok_or(anyhow!("Mint info not found"))?;
- let (access_token, refresh_token) = get_access_token(
- &mint_info,
- &sub_command_args.username,
- &sub_command_args.password,
- )
- .await;
- // Save tokens to file in work directory
- if let Err(e) =
- token_storage::save_tokens(work_dir, &mint_url, &access_token, &refresh_token).await
- {
- println!("Warning: Failed to save tokens to file: {e}");
- } else {
- println!("Tokens saved to work directory");
- }
- println!("\nAuthentication successful! 🎉\n");
- println!("\nYour tokens:");
- println!("access_token: {access_token}");
- println!("refresh_token: {refresh_token}");
- Ok(())
- }
- async fn get_access_token(mint_info: &MintInfo, user: &str, password: &str) -> (String, String) {
- let openid_discovery = mint_info
- .nuts
- .nut21
- .clone()
- .expect("Nut21 defined")
- .openid_discovery;
- let client_id = mint_info
- .nuts
- .nut21
- .clone()
- .expect("Nut21 defined")
- .client_id;
- let oidc_client = OidcClient::new(openid_discovery, None);
- // Get the token endpoint from the OIDC configuration
- let token_url = oidc_client
- .get_oidc_config()
- .await
- .expect("Failed to get OIDC config")
- .token_endpoint;
- // Create the request parameters
- let params = [
- ("grant_type", "password"),
- ("client_id", &client_id),
- ("scope", "openid offline_access"),
- ("username", user),
- ("password", password),
- ];
- // Make the token request directly
- let client = reqwest::Client::new();
- let response = client
- .post(token_url)
- .form(¶ms)
- .send()
- .await
- .expect("Failed to send token request");
- let token_response: serde_json::Value = response
- .json()
- .await
- .expect("Failed to parse token response");
- let access_token = token_response["access_token"]
- .as_str()
- .expect("No access token in response")
- .to_string();
- let refresh_token = token_response["refresh_token"]
- .as_str()
- .expect("No refresh token in response")
- .to_string();
- (access_token, refresh_token)
- }
|