diff --git a/README.md b/README.md index e525038..27ba900 100644 --- a/README.md +++ b/README.md @@ -51,14 +51,11 @@ When MitID asks you to approve in the app, the CLI does it automatically via the ### Fully automated login -No browser needed. Outputs JSON to stdout with cookies, tokens, and metadata. Progress goes to stderr so piping works cleanly: +No browser needed. Single command that handles both login and approval. Outputs JSON to stdout with cookies, tokens, and metadata. Progress goes to stderr so piping works cleanly: ```bash -# Terminal 1: start the login +# Single command - login + auto-approve: mitid login myuser https://your-service.example.com/login/mitid - -# Terminal 2: auto-approve when prompted -mitid approve myuser ``` Output is JSON: @@ -80,6 +77,10 @@ mitid login myuser | jq -r '.body.access_token' # Get cookies as a string for curl mitid login myuser | jq -r '.cookies | to_entries | map("\(.key)=\(.value)") | join("; ")' + +# If you need to approve separately (e.g. different machine): +mitid login myuser --no-approve +# Then in another terminal: mitid approve myuser ``` ### AI agent / browser automation @@ -87,9 +88,8 @@ mitid login myuser | jq -r '.cookies | to_entries | map("\(.key)=\(.value) For AI agents (Claude, Cursor, etc.) controlling a browser via Chrome DevTools MCP, Playwright, or similar; where the MitID widget refuses to render: 1. Run `mitid login ` to get JSON output -2. Run `mitid approve ` in parallel to auto-approve -3. Parse the JSON for cookies or access tokens -4. Inject the cookies into the automated browser, or use the access token as a Bearer token +2. Parse the JSON for cookies or access tokens +3. Inject the cookies into the automated browser, or use the access token as a Bearer token ```javascript // Example: inject cookies into an automated browser @@ -113,8 +113,8 @@ Prints detailed workflow instructions for all use cases including library usage. | Command | Description | |---------|-------------| | `mitid info ` | Show identity details (username, UUID, CPR, authenticators) | -| `mitid login ` | Complete a full MitID login and output JSON (cookies, tokens, metadata) | -| `mitid approve ` | Poll and auto-approve a pending MitID login via the simulator. Use `--watch` to keep approving | +| `mitid login ` | Login and auto-approve in one step. Outputs JSON. Use `--no-approve` to approve separately | +| `mitid approve ` | Manually approve a pending MitID login via the simulator. Use `--watch` to keep approving | | `mitid save [alias]` | Save an identity for quick access. Use `--note` to annotate | | `mitid list` | Show all saved identities | | `mitid export` | Export saved identities as JSON (pipe-friendly) | diff --git a/src/cli.ts b/src/cli.ts index 1fe7840..75d6a30 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -198,7 +198,7 @@ const loginCmd = defineCommand({ meta: { name: "login", description: - "Complete a full MitID login and output JSON with cookies and tokens", + "Login with auto-approve and output JSON with cookies and tokens", }, args: { query: queryArg, @@ -208,17 +208,49 @@ const loginCmd = defineCommand({ "Service login URL that triggers a MitID authentication flow", required: true, }, + "no-approve": { + type: "boolean", + description: + "Don't auto-approve. Run 'mitid approve' in another terminal instead", + default: false, + }, env: envArg, }, async run({ args }) { const serviceUrl = args.url; + const baseUrl = getBaseUrl(args.env); + const username = resolveQuery(args.query); stderr(`Logging in as ${args.query} to ${new URL(serviceUrl).hostname}...`); - stderr( - `Run 'mitid approve ${args.query}' in another terminal to auto-approve.\n`, - ); - const result = await login(resolveQuery(args.query), serviceUrl, stderr); + let approvePromise: Promise | undefined; + if (!args["no-approve"]) { + const { identity, codeApp } = await resolve(username, baseUrl); + if (codeApp) { + stderr("Auto-approving in background...\n"); + approvePromise = approve( + identity.identityId, + codeApp.authenticatorId, + baseUrl, + stderr, + ); + } else { + stderr( + "No active code app found, skipping auto-approve.\n" + + `Run 'mitid approve ${args.query}' in another terminal.\n`, + ); + } + } else { + stderr( + `Run 'mitid approve ${args.query}' in another terminal to auto-approve.\n`, + ); + } + + const result = await login(username, serviceUrl, stderr); + + if (approvePromise) { + await approvePromise.catch(() => {}); + } const output: Record = { provider: result.provider, @@ -473,17 +505,14 @@ WORKFLOW 1: Manual browser testing 4. The CLI auto-approves The browser completes the login 5. Repeat as needed --watch keeps approving every login -WORKFLOW 2: Fully automated login ----------------------------------- - No browser needed. Outputs JSON to stdout with cookies, tokens, and metadata. +WORKFLOW 2: Fully automated login (single command) +--------------------------------------------------- + No browser needed. Auto-approves and outputs JSON to stdout. Progress messages go to stderr, so piping works cleanly. - # Terminal 1: start the login + # Single command - login + auto-approve: mitid login https://your-service.example.com/login/mitid - # Terminal 2: auto-approve when it says "Waiting for MitID app approval" - mitid approve - # Output is JSON: # { "provider": "...", "finalUrl": "...", "cookies": {...}, "body": {...} } @@ -493,19 +522,22 @@ WORKFLOW 2: Fully automated login # Copy cookies to clipboard: mitid login | jq -r '.cookies | to_entries | map("\\(.key)=\\(.value)") | join("; ")' | pbcopy + # If you need to approve separately (e.g. different machine): + mitid login --no-approve + # Then in another terminal: mitid approve + WORKFLOW 3: AI agent with browser automation (Chrome MCP, Playwright, etc.) --------------------------------------------------------------------------- For AI agents that control a browser but can't interact with MitID's widget (it blocks automated browsers). The agent should: - 1. Run 'mitid login ' in background - 2. Run 'mitid approve ' in parallel to auto-approve - 3. Parse the JSON output for cookies or access tokens - 4. In the browser: navigate to the service URL - 5. Inject cookies via JavaScript: + 1. Run 'mitid login ' + 2. Parse the JSON output for cookies or access tokens + 3. In the browser: navigate to the service URL + 4. Inject cookies via JavaScript: document.cookie = "CookieName=value; path=/"; - 6. Reload the page — the browser is now logged in - 7. Proceed with testing + 5. Reload the page - the browser is now logged in + 6. Proceed with testing Example cookie injection (browser console / evaluate_script): const cookies = { "SessionCookie": "", "Token": "" };