-
Notifications
You must be signed in to change notification settings - Fork 4
feat(auth flow): add ability to authenticate ampcc if not authenticated #1595
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…whited/ampcc/feat-auth
…whited/ampcc/feat-auth
…whited/ampcc/feat-auth
…whited/ampcc/feat-auth
|
|
||
| /// Errors that can occur during authentication operations. | ||
| #[derive(Debug, Error)] | ||
| pub enum AuthError { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add detailed docs for each errors?
| /// 1. AMP_AUTH_TOKEN environment variable (highest priority) | ||
| /// 2. Auth storage file (~/.amp/cache/amp_cli_auth) | ||
| pub fn new(base_url: String) -> Self { | ||
| let auth_token = Self::load_auth_token(); | ||
| // Use Client::new() like other working clients in the codebase | ||
| let http = reqwest::Client::new(); | ||
|
|
||
| Self { | ||
| http, | ||
| base_url: base_url.trim_end_matches('/').to_string(), | ||
| auth_token, | ||
| } | ||
| // Load from auth storage file, then pass to with_token which checks env var | ||
| let file_token = AuthStorage::load().map(|a| a.access_token); | ||
| Self::with_token(base_url, file_token) | ||
| } | ||
|
|
||
| /// Create a new registry client with a specific auth token. | ||
| #[allow(dead_code)] | ||
| pub fn with_auth(base_url: String, token: String) -> Self { | ||
| /// Create a new registry client with an explicit auth token. | ||
| /// | ||
| /// If `token` is `None`, falls back to AMP_AUTH_TOKEN environment variable. | ||
| /// Use this when the app's auth state changes (login, logout, refresh). | ||
| pub fn with_token(base_url: String, token: Option<String>) -> Self { | ||
| // Use explicit token if provided, otherwise fall back to env var | ||
| let auth_token = token.or_else(Self::load_auth_from_env); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docs for new() says, env has highest priority, but its actually used as fallback.
shiyasmohd
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementation looks nice, and works smooth. Some changes needed
- Added in comments
- Can we remove the merge commit and rebase the branch?
- There is a lag when selecting pane using mouse click, that needs to be fixed
| pub fn is_evm_address(s: &str) -> bool { | ||
| s.starts_with("0x") && s.parse::<Address>().is_ok() | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be a simple validation fn instead of importing alloy crate.
s.len() == 42 && s.starts_with("0x") && s[2..].chars().all(|c| c.is_ascii_hexdigit())
| Action::SwitchToLocal => { | ||
| if self.current_source != DataSource::Local { | ||
| self.start_loading("Switching source..."); | ||
| // Spawn task to switch source |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment could be changed to something like, Async spawning handled in handle_async_action
| // Spawn task to switch source | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
| // Datasets | ||
| Action::RefreshDatasets => { | ||
| self.start_loading("Refreshing datasets..."); | ||
| // Spawn task to refresh datasets |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update comment
| // Manifest | ||
| Action::LoadManifest => { | ||
| self.start_loading("Loading manifest..."); | ||
| // Spawn task to load manifest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update comment
|
|
||
| Action::LoadWorkerDetail(_node_id) => { | ||
| self.start_loading("Loading worker details..."); | ||
| // Spawn task to load worker detail |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update comment
| Action::AuthLogin => { | ||
| if self.auth_state.is_none() && self.auth_device_flow.is_none() { | ||
| self.start_loading("Logging in..."); | ||
| // Spawn task to start device flow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update comment
| let _ = clipboard.set_text(&user_code); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could silently ignore copy to clipboard errors and showing users copied to clipboard in auth_screen.rs, could be fixed in another PR.
| Action::AuthDeviceFlowPoll { | ||
| device_code, | ||
| code_verifier, | ||
| interval, | ||
| is_first_poll, | ||
| } => { | ||
| if let Some(ref mut flow) = self.auth_device_flow { | ||
| flow.status = DeviceFlowStatus::Polling; | ||
| } | ||
| // Spawn task to poll for token | ||
| let _ = (device_code, code_verifier, interval, is_first_poll); // Will be used by spawn | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Action::AuthDeviceFlowPoll { | |
| device_code, | |
| code_verifier, | |
| interval, | |
| is_first_poll, | |
| } => { | |
| if let Some(ref mut flow) = self.auth_device_flow { | |
| flow.status = DeviceFlowStatus::Polling; | |
| } | |
| // Spawn task to poll for token | |
| let _ = (device_code, code_verifier, interval, is_first_poll); // Will be used by spawn | |
| } | |
| Action::AuthDeviceFlowPoll { .. } => { | |
| if let Some(ref mut flow) = self.auth_device_flow { | |
| flow.status = DeviceFlowStatus::Polling; | |
| } | |
| // Updated comment with same pattern as others | |
| } |
|
|
||
| Action::AuthDeviceFlowConfirm => { | ||
| if let Some(ref mut flow) = self.auth_device_flow { | ||
| let _ = crate::auth::PkceDeviceFlowClient::open_browser(&flow.verification_uri); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should handle the case, if opening browser fails, maybe like show url in terminal, but we don't support selecting text in tui since we have selecting pane using mouse pointer feature. this needs a discussion.
Description
Updated the auth flow in ampcc to enable authenticating using the PKCE device flow against the platform auth ui.
Auth state/flow:
AMP_AUTH_TOKENto the env{home_dir}/.amp/cache/amp_cli_auth, which is set by the amp cli (and now this TUI as well)CleanShot.2026-01-20.at.12.24.04.mp4