Skip to content

Commit aae5052

Browse files
committed
add which mwinit
1 parent ec2408f commit aae5052

File tree

3 files changed

+48
-8
lines changed

3 files changed

+48
-8
lines changed

crates/chat-cli/src/auth/portal.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use crate::database::{
3636
Database,
3737
Secret,
3838
};
39+
use crate::util::system_info::is_mwinit_available;
3940

4041
const AUTH_PORTAL_URL: &str = "https://gamma.app.kiro.aws.dev/signin";
4142
const DEFAULT_AUTHORIZATION_TIMEOUT: Duration = Duration::from_secs(600);
@@ -46,13 +47,14 @@ struct AuthPortalCallback {
4647
login_option: String,
4748
code: Option<String>,
4849
issuer_uri: Option<String>,
50+
sso_region: Option<String>,
4951
state: String,
5052
path: String,
5153
}
5254

5355
pub enum PortalResult {
5456
Social(SocialProvider),
55-
Internal { issuer_uri: String },
57+
Internal { issuer_uri: String, idc_region: String },
5658
}
5759

5860
/// Local-only: open unified portal and handle single callback
@@ -80,13 +82,15 @@ pub async fn start_unified_auth(db: &mut Database) -> Result<PortalResult, AuthE
8082
// this base.
8183
let redirect_base = format!("http://localhost:{}", port);
8284
info!(%port, %redirect_base, "Unified auth portal listening (base) for callback");
85+
let is_internal = is_mwinit_available();
8386

8487
let auth_url = format!(
85-
"{}?state={}&code_challenge={}&code_challenge_method=S256&redirect_uri={}&redirect_from=kirocli",
88+
"{}?state={}&code_challenge={}&code_challenge_method=S256&redirect_uri={}{internal}&redirect_from=kirocli",
8689
AUTH_PORTAL_URL,
8790
state,
8891
challenge,
89-
urlencoding::encode(&redirect_base)
92+
urlencoding::encode(&redirect_base),
93+
internal = if is_internal { "&from_amazon_internal=true" } else { "" },
9094
);
9195

9296
crate::util::open::open_url_async(&auth_url)
@@ -118,8 +122,14 @@ pub async fn start_unified_auth(db: &mut Database) -> Result<PortalResult, AuthE
118122
let issuer_uri = callback
119123
.issuer_uri
120124
.ok_or_else(|| AuthError::OAuthCustomError("Missing issuer_uri for internal auth".into()))?;
121-
// DO NOT register here. Let caller run start_pkce_authorization(issuer_uri).
122-
Ok(PortalResult::Internal { issuer_uri })
125+
let sso_region = callback
126+
.sso_region
127+
.ok_or_else(|| AuthError::OAuthCustomError("Missing sso_region for internal auth".into()))?;
128+
// DO NOT register here. Let caller run start_pkce_authorization(issuer_uri, sso_region).
129+
Ok(PortalResult::Internal {
130+
issuer_uri,
131+
idc_region: sso_region,
132+
})
123133
},
124134
other => Err(AuthError::OAuthCustomError(format!("Unknown login_option: {}", other))),
125135
}
@@ -192,6 +202,7 @@ impl Service<Request<Incoming>> for AuthCallbackService {
192202
login_option: query_params.get("login_option").cloned().unwrap_or_default(),
193203
code: query_params.get("code").cloned(),
194204
issuer_uri: query_params.get("issuer_uri").cloned(),
205+
sso_region: query_params.get("idc_region").cloned(),
195206
state: query_params.get("state").cloned().unwrap_or_default(),
196207
path: path.to_string(),
197208
};

crates/chat-cli/src/cli/user.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,11 @@ impl LoginArgs {
109109
os.telemetry.send_user_logged_in(None, None, Some(provider)).ok();
110110
return Ok(ExitCode::SUCCESS);
111111
},
112-
PortalResult::Internal { issuer_uri } => {
112+
PortalResult::Internal { issuer_uri, idc_region } => {
113113
pre_portal_spinner.stop();
114114
// EXACTLY same with original PKCE path: this registers client + completes auth.
115-
let (client, registration) = start_pkce_authorization(Some(issuer_uri.clone()), None).await?;
115+
let (client, registration) =
116+
start_pkce_authorization(Some(issuer_uri.clone()), Some(idc_region.clone())).await?;
116117

117118
match crate::util::open::open_url_async(&registration.url).await {
118119
// If it succeeded, finish PKCE.
@@ -141,7 +142,7 @@ impl LoginArgs {
141142
Err(err) => {
142143
// Try device code flow.
143144
error!(%err, "Failed to open URL with browser, falling back to device code flow");
144-
try_device_authorization(os, Some(issuer_uri.clone()), None).await?;
145+
try_device_authorization(os, Some(issuer_uri.clone()), Some(idc_region.clone())).await?;
145146
},
146147
}
147148
},

crates/chat-cli/src/util/system_info/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ pub mod linux;
33
#[cfg(target_os = "windows")]
44
pub mod windows;
55

6+
use std::path::PathBuf;
7+
use std::process::Command;
68
use std::sync::OnceLock;
79

810
use cfg_if::cfg_if;
@@ -188,3 +190,29 @@ pub fn in_ci() -> bool {
188190
static IN_CI: OnceLock<bool> = OnceLock::new();
189191
*IN_CI.get_or_init(|| std::env::var_os("CI").is_some() || std::env::var_os("Q_CI").is_some())
190192
}
193+
194+
pub fn is_mwinit_available() -> bool {
195+
static MWINIT_AVAILABLE: OnceLock<bool> = OnceLock::new();
196+
*MWINIT_AVAILABLE.get_or_init(|| which_mwinit().is_some())
197+
}
198+
199+
pub fn which_mwinit() -> Option<PathBuf> {
200+
#[cfg(target_os = "windows")]
201+
let cmd = ("where.exe", "mwinit");
202+
203+
#[cfg(not(target_os = "windows"))]
204+
let cmd = ("which", "mwinit");
205+
206+
let output = Command::new(cmd.0).arg(cmd.1).output().ok()?;
207+
if !output.status.success() {
208+
return None;
209+
}
210+
211+
let stdout = String::from_utf8_lossy(&output.stdout);
212+
let path = stdout.lines().next()?.trim();
213+
if path.is_empty() {
214+
None
215+
} else {
216+
Some(PathBuf::from(path))
217+
}
218+
}

0 commit comments

Comments
 (0)