From 08a07a0355ea6a45a9df81f8960a4c35ebcbaaba Mon Sep 17 00:00:00 2001 From: Ian Webster Date: Sat, 4 Jul 2026 07:30:04 +0000 Subject: [PATCH] fix(login): improve device auth contrast --- codex-rs/Cargo.lock | 1 + codex-rs/login/Cargo.toml | 1 + codex-rs/login/src/device_code_auth.rs | 24 +++++++++++++------ codex-rs/login/src/device_code_auth_tests.rs | 9 +++++++ ..._prompt_uses_terminal_relative_styles.snap | 5 ++++ 5 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 codex-rs/login/src/device_code_auth_tests.rs create mode 100644 codex-rs/login/src/snapshots/codex_login__device_code_auth__tests__device_code_prompt_uses_terminal_relative_styles.snap diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index 6ac51d403f..b6c5f5909e 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -3313,6 +3313,7 @@ dependencies = [ "codex-terminal-detection", "codex-utils-template", "core_test_support", + "insta", "jsonwebtoken", "keyring", "once_cell", diff --git a/codex-rs/login/Cargo.toml b/codex-rs/login/Cargo.toml index 04066f5894..3787f22e75 100644 --- a/codex-rs/login/Cargo.toml +++ b/codex-rs/login/Cargo.toml @@ -45,6 +45,7 @@ webbrowser = { workspace = true } anyhow = { workspace = true } core_test_support = { workspace = true } jsonwebtoken = { workspace = true } +insta = { workspace = true } keyring = { workspace = true } pretty_assertions = { workspace = true } regex-lite = { workspace = true } diff --git a/codex-rs/login/src/device_code_auth.rs b/codex-rs/login/src/device_code_auth.rs index 70e6dff225..b4e1c0d8be 100644 --- a/codex-rs/login/src/device_code_auth.rs +++ b/codex-rs/login/src/device_code_auth.rs @@ -12,7 +12,7 @@ use crate::server::ServerOptions; use std::io; const ANSI_BLUE: &str = "\x1b[94m"; -const ANSI_GRAY: &str = "\x1b[90m"; +const ANSI_DIM: &str = "\x1b[2m"; const ANSI_RESET: &str = "\x1b[0m"; #[derive(Debug, Clone)] @@ -145,17 +145,27 @@ async fn poll_for_token( } } -fn print_device_code_prompt(verification_url: &str, code: &str) { - let version = env!("CARGO_PKG_VERSION"); - println!( - "\nWelcome to Codex [v{ANSI_GRAY}{version}{ANSI_RESET}]\n{ANSI_GRAY}OpenAI's command-line coding agent{ANSI_RESET}\n\ +fn format_device_code_prompt(version: &str, verification_url: &str, code: &str) -> String { + format!( + "\nWelcome to Codex [v{ANSI_DIM}{version}{ANSI_RESET}]\n{ANSI_DIM}OpenAI's command-line coding agent{ANSI_RESET}\n\ \nFollow these steps to sign in with ChatGPT using device code authorization:\n\ \n1. Open this link in your browser and sign in to your account\n {ANSI_BLUE}{verification_url}{ANSI_RESET}\n\ -\n2. Enter this one-time code {ANSI_GRAY}(expires in 15 minutes){ANSI_RESET}\n {ANSI_BLUE}{code}{ANSI_RESET}\n\ -\n{ANSI_GRAY}Device codes are a common phishing target. Never share this code.{ANSI_RESET}\n", +\n2. Enter this one-time code {ANSI_DIM}(expires in 15 minutes){ANSI_RESET}\n {ANSI_BLUE}{code}{ANSI_RESET}\n\ +\nDevice codes are a common phishing target. Never share this code.\n", + ) +} + +fn print_device_code_prompt(verification_url: &str, code: &str) { + println!( + "{}", + format_device_code_prompt(env!("CARGO_PKG_VERSION"), verification_url, code) ); } +#[cfg(test)] +#[path = "device_code_auth_tests.rs"] +mod tests; + pub async fn request_device_code(opts: &ServerOptions) -> std::io::Result { let base_url = opts.issuer.trim_end_matches('/'); // The route selected for the issuer is reused for all device-auth endpoint paths; the endpoint diff --git a/codex-rs/login/src/device_code_auth_tests.rs b/codex-rs/login/src/device_code_auth_tests.rs new file mode 100644 index 0000000000..07a942d71a --- /dev/null +++ b/codex-rs/login/src/device_code_auth_tests.rs @@ -0,0 +1,9 @@ +use super::format_device_code_prompt; + +#[test] +fn device_code_prompt_uses_terminal_relative_styles() { + let prompt = + format_device_code_prompt("1.2.3", "https://auth.openai.com/codex/device", "ABCD-EFGH"); + + insta::assert_snapshot!(prompt.escape_default().to_string()); +} diff --git a/codex-rs/login/src/snapshots/codex_login__device_code_auth__tests__device_code_prompt_uses_terminal_relative_styles.snap b/codex-rs/login/src/snapshots/codex_login__device_code_auth__tests__device_code_prompt_uses_terminal_relative_styles.snap new file mode 100644 index 0000000000..d0f84b759e --- /dev/null +++ b/codex-rs/login/src/snapshots/codex_login__device_code_auth__tests__device_code_prompt_uses_terminal_relative_styles.snap @@ -0,0 +1,5 @@ +--- +source: login/src/device_code_auth_tests.rs +expression: prompt.escape_default().to_string() +--- +\nWelcome to Codex [v\u{1b}[2m1.2.3\u{1b}[0m]\n\u{1b}[2mOpenAI\'s command-line coding agent\u{1b}[0m\n\nFollow these steps to sign in with ChatGPT using device code authorization:\n\n1. Open this link in your browser and sign in to your account\n \u{1b}[94mhttps://auth.openai.com/codex/device\u{1b}[0m\n\n2. Enter this one-time code \u{1b}[2m(expires in 15 minutes)\u{1b}[0m\n \u{1b}[94mABCD-EFGH\u{1b}[0m\n\nDevice codes are a common phishing target. Never share this code.\n