Clean up OAuth device-code callbacks
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
### Fixed
|
||||
|
||||
- Fixed exported session HTML to escape quote characters in attribute values ([#4832](https://github.com/earendil-works/pi/issues/4832)).
|
||||
- Fixed GitHub Copilot device-code login to keep opening the verification URL in browser-capable environments while ignoring browser launch failures for headless use.
|
||||
- Fixed git package installs to reconcile existing checkouts to the requested ref and update package settings without losing filters ([#4870](https://github.com/earendil-works/pi/issues/4870)).
|
||||
- Published a 0.74.2 rescue release that tells Node 20 users to upgrade Node before updating to newer Pi versions ([#4876](https://github.com/earendil-works/pi/issues/4876)).
|
||||
- Fixed final bash tool cards to avoid rendering duplicate full-output truncation paths ([#4819](https://github.com/earendil-works/pi/issues/4819)).
|
||||
|
||||
@@ -263,17 +263,28 @@ pi.registerProvider("corporate-ai", {
|
||||
name: "Corporate AI (SSO)",
|
||||
|
||||
async login(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials> {
|
||||
// Option 1: Browser-based OAuth
|
||||
callbacks.onAuth({ url: "https://sso.corp.com/authorize?..." });
|
||||
|
||||
// Option 2: Device code flow
|
||||
callbacks.onDeviceCode({
|
||||
userCode: "ABCD-1234",
|
||||
verificationUri: "https://sso.corp.com/device"
|
||||
const method = await callbacks.onSelect({
|
||||
message: "Select login method:",
|
||||
options: [
|
||||
{ id: "browser", label: "Browser OAuth" },
|
||||
{ id: "device", label: "Device code" }
|
||||
]
|
||||
});
|
||||
if (!method) throw new Error("Login cancelled");
|
||||
|
||||
// Option 3: Prompt for token/code
|
||||
const code = await callbacks.onPrompt({ message: "Enter SSO code:" });
|
||||
let code: string;
|
||||
if (method === "device") {
|
||||
callbacks.onDeviceCode({
|
||||
userCode: "ABCD-1234",
|
||||
verificationUri: "https://sso.corp.com/device",
|
||||
intervalSeconds: 5,
|
||||
expiresInSeconds: 900
|
||||
});
|
||||
code = await pollDeviceCodeUntilComplete();
|
||||
} else {
|
||||
callbacks.onAuth({ url: "https://sso.corp.com/authorize?..." });
|
||||
code = await callbacks.onPrompt({ message: "Enter SSO code:" });
|
||||
}
|
||||
|
||||
// Exchange for tokens (your implementation)
|
||||
const tokens = await exchangeCodeForTokens(code);
|
||||
@@ -322,10 +333,21 @@ interface OAuthLoginCallbacks {
|
||||
onAuth(params: { url: string }): void;
|
||||
|
||||
// Show device code (for device authorization flow)
|
||||
onDeviceCode(params: { userCode: string; verificationUri: string }): void;
|
||||
onDeviceCode(params: {
|
||||
userCode: string;
|
||||
verificationUri: string;
|
||||
intervalSeconds?: number;
|
||||
expiresInSeconds?: number;
|
||||
}): void;
|
||||
|
||||
// Prompt user for input (for manual token entry)
|
||||
onPrompt(params: { message: string }): Promise<string>;
|
||||
|
||||
// Show an interactive selector, e.g. to choose browser OAuth vs device code
|
||||
onSelect(params: {
|
||||
message: string;
|
||||
options: { id: string; label: string }[];
|
||||
}): Promise<string | undefined>;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -122,13 +122,17 @@ export class LoginDialogComponent extends Container implements Focusable {
|
||||
this.contentContainer.addChild(new Spacer(1));
|
||||
this.contentContainer.addChild(new Text(theme.fg("warning", `Enter code: ${info.userCode}`), 1, 0));
|
||||
|
||||
// Do not open device-code URLs automatically. These flows need to work in headless environments.
|
||||
this.openUrl(info.verificationUri);
|
||||
this.tui.requestRender();
|
||||
}
|
||||
|
||||
private openUrl(url: string): void {
|
||||
const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
||||
exec(`${openCmd} "${url}"`);
|
||||
try {
|
||||
exec(`${openCmd} "${url}"`, () => {});
|
||||
} catch {
|
||||
// Ignore browser launch failures. The URL remains visible for manual opening/copying.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user