feat(auth): add dormant egress-bound login v2 - #4
Open
lzhs1995 wants to merge 3 commits into
Open
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a default-off “egress-bound login v2” flow that binds newly created credentials to a managed proxy’s version and an exit fingerprint (without persisting raw public IP), rotates session nonces, verifies the bound egress on refresh, and quarantines newly authorized credentials by keeping them disabled until explicitly promoted.
Changes:
- Add
kiro::egress_loginprimitives (probe/version/fingerprint + nonce rotation) and wire bound-egress verification into token refresh. - Extend credential model + Admin API payloads to carry egress-binding metadata and session nonce fields.
- Update Admin UI login dialogs and API client to negotiate capability, select a managed proxy, and send the rotating nonce via header.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/kiro/token_manager.rs | Adds “quarantined credential” insertion path and enforces bound-egress verification during refresh. |
| src/kiro/model/credentials.rs | Adds persisted egress-binding metadata fields to KiroCredentials + updates tests/debug output. |
| src/kiro/mod.rs | Exposes the new egress_login module. |
| src/kiro/egress_login.rs | New module implementing probe + fingerprint/version hashing and nonce rotation/validation. |
| src/admin/types.rs | Extends Admin API request/response types to support egress v2 fields and capability response. |
| src/admin/service.rs | Implements egress-bound session handling for Social/IdC login, nonce rotation, quarantine insertion, and proxy-pool binding. |
| src/admin/router.rs | Adds capability route /auth/egress-login-v2. |
| src/admin/handlers.rs | Adds capability handler and passes rotating nonce header into poll/complete endpoints. |
| admin-ui/src/types/api.ts | Updates UI API types for egress v2 capability, proxyId fields, and sessionNonce fields. |
| admin-ui/src/components/social-login-dialog.tsx | Adds capability/proxy-pool queries, proxy selection UI, and nonce-aware polling/complete behavior. |
| admin-ui/src/components/idc-login-dialog.tsx | Adds capability/proxy-pool queries, proxy selection UI, and nonce-aware polling behavior. |
| admin-ui/src/api/credentials.ts | Adds capability call and sends x-kiro-egress-nonce header for poll/complete requests. |
Comments suppressed due to low confidence (2)
src/admin/service.rs:3514
- Same as Social login: when egress login v2 is disabled, persisting
proxy_urlfrom the effective proxy (which may be the global proxy fallback) changes flag-off behavior by pinning the credential to a specific proxy URL.
proxy_url: proxy.as_ref().map(|value| value.url.clone()),
src/admin/service.rs:3564
poll_idc_loginperforms an egress probe (verify_login_egress→ HTTP call) on every poll when the session is egress-bound. With typical device-flow polling intervals this can generate sustained outbound traffic to the probe URL, increase latency, and risk rate limiting. Consider deferring the probe to only whenidc::poll_tokentransitions toSuccess(and possibly once on start), while still rotating/validating the nonce on each poll.
let claimed = self.claim_idc_nonce(session_id, session_nonce)?;
if let Some((binding, proxy)) = &claimed {
if let Err(error) = self.verify_login_egress(binding, proxy.as_ref()).await {
self.idc_sessions.lock().remove(session_id);
return Err(error);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| rpm_limit: 10, // 默认每分钟 10 次(与普通添加一致;用户可在面板调整) | ||
| email: req.email, | ||
| proxy_url: req.proxy_url, | ||
| proxy_url: proxy.as_ref().map(|value| value.url.clone()), |
Comment on lines
+2996
to
+3002
| let claimed = self.claim_social_nonce(session_id, session_nonce)?; | ||
| if let Some((binding, proxy)) = &claimed { | ||
| if let Err(error) = self.verify_login_egress(binding, proxy.as_ref()).await { | ||
| self.social_sessions.lock().remove(session_id); | ||
| return Err(error); | ||
| } | ||
| } |
| disabled: false, | ||
| disabled_reason: None, | ||
| disabled: quarantined, | ||
| disabled_reason: quarantined.then_some(DisabledReason::Manual), |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a default-off egress-bound login v2 flow. Managed proxy use is required, sessions bind a proxy version and exit fingerprint without persisting the raw public IP, nonces rotate after use, refresh verifies the bound exit, and newly authorized credentials remain quarantined and disabled. Flag-off UI and capability behavior remain unchanged.
This PR was AI-assisted and reviewed against the implementation and CI results. Production is not deployed.
Verification
cargo test --locked --all-targets --no-default-features.ghcr.io/lzhs1995/kiro-rs@sha256:3a0533bf6915c921b846f734871b3ee508bcfa3a8fbf6afc0ac450e898314fe1.VPS build/compile is permanently forbidden; deployment must pull this immutable digest with
--no-build.