ScreenshotNeo

BlogGuides

How to Use Entra ID from a Linux Terminal with Headless Chrome

Use Azure CLI device code and Playwright headless Chrome to authenticate Entra ID on Linux, handle MFA safely, and choose the right automation identity.

By the ScreenshotNeo team1 October 20268 min read

On a Linux machine without a graphical browser, use Azure CLI device-code authentication:

az login --use-device-code

Open https://aka.ms/devicelogin in an approved browser on another device, enter the code printed in the terminal, and complete MFA or Conditional Access challenges. Then verify the selected tenant and subscription:

az account show
az account list --output table

For browser automation, Playwright CLI runs headless by default. Select Chrome explicitly with playwright-cli open --browser=chrome. Headless Chrome does not bypass Entra policies: MFA, Conditional Access, device compliance, federation and broker requirements still apply.

Choose the authentication method first

Situation Recommended method Why
Terminal-only interactive login az login --use-device-code Works when the Linux host cannot open a browser. User completes sign-in and MFA elsewhere.
Linux desktop managed by your organization Azure CLI with Microsoft Identity Broker, where supported Brokered SSO can satisfy desktop sign-in requirements and stores refresh tokens in the user keyring.
Unattended production job Service principal, managed identity or another workload identity Removes dependence on a human session. User identities are subject to MFA requirements.
Repeatable browser task Playwright Chrome session Use a persistent profile only when storing cookies and browser state is approved.

Prerequisites

  1. Install Azure CLI using Microsoft’s Linux installation instructions for your distribution.
  2. Use Azure CLI 2.61.0 or later if your environment follows the browser-login behavior documented for current Linux and macOS releases.
  3. Install Node.js and Playwright CLI for browser automation.
  4. Confirm that the account, tenant and device satisfy your organization’s MFA and Conditional Access policy.

Do not copy token databases, cookies or browser profiles from another machine. A persistent profile is a credential-bearing artifact and must have restricted filesystem permissions.

Sign in from a Linux terminal

Interactive login when a browser is available

az login

Azure CLI opens the system browser by default. Complete the Entra sign-in, then inspect the active context:

az account show --output json
az account list --output table

If more than one subscription is available, select the one your command should use:

az account set --subscription "SUBSCRIPTION_ID_OR_NAME"
az account show --query "{tenant:tenantId, subscription:id, name:name, user:user.name}"

Device code flow on a headless server

az login --use-device-code
  1. Copy the one-time code displayed by Azure CLI.
  2. On an approved browser, open https://aka.ms/devicelogin.
  3. Enter the code and complete password, MFA and any Conditional Access prompts.
  4. Return to the terminal and wait for Azure CLI to report successful login.
  5. Run az account show and confirm the tenant and subscription.

Device code is an interactive flow. It is suitable for administration and setup, but it is not a replacement for a workload identity in an unattended service.

Check token access without exposing the token

Use Azure CLI to request an access token only for the command that needs it. Avoid printing the token to logs or shell history:

az account get-access-token --resource-type ms-graph \
  --query expiresOn --output tsv

The command returns the expiry value while leaving the token itself out of the terminal output.

Run Chrome headlessly with Playwright

Playwright CLI keeps the browser profile in memory by default. Cookies and storage state survive between calls in one session and disappear when the browser closes.

npm install --global playwright
playwright install chrome
playwright-cli open --browser=chrome https://login.microsoftonline.com

For first-run troubleshooting, show the browser window:

playwright-cli open --browser=chrome --headed https://login.microsoftonline.com

Use headed mode to observe redirects, consent prompts and policy errors. Return to headless mode for repeatable runs after the flow works.

Persistent sessions

A persistent profile retains cookies and storage state between browser launches. Only use it if your organization permits local credential storage:

mkdir -p "$HOME/entra-playwright-profile"
chmod 700 "$HOME/entra-playwright-profile"
playwright-cli open --browser=chrome --persistent \
  --user-data-dir "$HOME/entra-playwright-profile" \
  https://login.microsoftonline.com

Protect the directory as you would a secret. Do not place it in a shared workspace, container image or world-readable backup. Session cookies can grant access until they expire or are revoked.

Automate browser steps with Node.js

Use a persistent context only when policy allows it. The first run may require headed mode so a person can complete MFA; later runs can use headless mode if the tenant permits the resulting session.

import { chromium } from 'playwright';

const browser = await chromium.launchPersistentContext(
  process.env.ENTRA_PROFILE_DIR,
  {
    channel: 'chrome',
    headless: process.env.HEADED !== '1'
  }
);

const page = await browser.newPage();
await page.goto(process.env.TARGET_URL, { waitUntil: 'domcontentloaded' });
console.log(await page.title());
await browser.close();

Run the first interactive setup with:

ENTRA_PROFILE_DIR="$HOME/entra-playwright-profile" \
HEADED=1 TARGET_URL="https://example.com" node capture.mjs

Do not attempt to script around MFA or Conditional Access. Let the approved user complete those challenges, or use a supported workload identity for unattended work.

Connectivity checks with cURL, Python and Node.js

These commands verify that the Linux host can reach the device-login endpoint. They do not authenticate a user or bypass tenant policy.

curl -I https://aka.ms/devicelogin
python3 - <<'PY'
import requests
r = requests.get('https://aka.ms/devicelogin', timeout=20, allow_redirects=True)
print(r.status_code, r.url)
PY
const res = await fetch('https://aka.ms/devicelogin', { redirect: 'manual' });
console.log(res.status, res.headers.get('location'));

A successful network check does not prove that sign-in will succeed. Proxy rules, TLS inspection, federation, Conditional Access and device compliance are evaluated during the actual authentication flow.

Linux broker and token storage

Microsoft Identity Broker provides Linux SSO for Azure CLI and Microsoft Edge on supported desktop distributions. Microsoft documents unregistered PRTs for Edge and registered PRTs when the broker is present. On Linux, the broker returns the access token to the calling application and stores refresh tokens locally, encrypted with a key in the Unix user’s sign-in keyring.

A minimal server usually has no supported desktop broker or keyring. In that case, device code is the practical interactive fallback. If your Conditional Access policy requires a compliant or registered device, a headless server may still be rejected even when the password and MFA are correct.

Production identity choices

  • Service principal: use an application identity with only the permissions required by the job. Store its credentials in your secret manager and rotate them according to policy.
  • Managed identity: use this when the workload runs on an Azure resource that supports it. No client secret needs to be distributed to the process.
  • User login: reserve this for interactive administration. Microsoft says MFA applies to Entra user identities using Azure CLI and other command-line tools; service principals and managed identities are unaffected by that user MFA requirement.

Choose the identity before designing the browser flow. A Playwright profile can preserve a user session, but it does not turn a user identity into a safe unattended credential.

Troubleshooting

Symptom Likely cause Fix
Azure CLI says it cannot open a browser The host has no graphical session or browser. Run az login --use-device-code and finish the flow at https://aka.ms/devicelogin.
Device code is rejected or expires The code was entered too late, entered incorrectly or used in the wrong tenant context. Start a new login, copy the complete code, and enter it promptly in the approved browser.
MFA succeeds but login is denied Conditional Access, device compliance, broker or federation requirements are not met. Ask the tenant administrator which policy blocked the sign-in. Headless Chrome cannot remove those requirements.
Playwright launches the wrong browser The browser channel was not selected or Chrome is not installed. Install Chrome with playwright install chrome and use --browser=chrome or channel: 'chrome'.
Login works once, then fails on the next run The profile was ephemeral, cookies expired, or the session was revoked. Use a permitted persistent profile, protect its directory, and expect periodic interactive reauthentication.
Headless run hangs on a login page An interactive prompt, consent screen, CAPTCHA or policy challenge is waiting for user input. Repeat with --headed, inspect the challenge, and use an approved identity flow. Do not automate around MFA.
Azure CLI shows the wrong subscription The account has multiple subscriptions or a previous context remains selected. Run az account list --output table, then az account set --subscription.
Browser cannot reach the sign-in page Proxy, DNS, firewall or TLS interception blocks the endpoint. Run the cURL connectivity check, inspect proxy settings, and have the network owner allow the required Microsoft endpoints.
Refresh tokens disappear after reboot The server has no usable keyring or the profile is stored in temporary storage. Use a supported managed desktop with a keyring, or switch the workload to a service principal or managed identity.

Performance, reliability and cost

  • Performance: device code adds a human interaction before the token is available. Persistent browser state can avoid repeated prompts until policy or token lifetime requires reauthentication.
  • Reliability: treat MFA, Conditional Access and federated identity redirects as environment-dependent. Add timeouts, capture diagnostic logs without secrets, and fail clearly when a user action is required.
  • Security: restrict profile permissions, keep tokens out of logs, use separate profiles for separate identities, and never copy browser state between machines.
  • Cost: Azure CLI and Playwright do not remove your cloud resource, network or identity-provider costs. Workload identity can also reduce operational work by removing manual sign-in from scheduled jobs.

Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server when the goal is to capture a page rather than operate an Entra session in Chrome. See the ScreenshotNeo API documentation for all parameters.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo removes cookie banners, newsletter popups and chat widgets before capture. Bot checks, blank pages and failed loads are not billed, and response headers identify the page verdict and billing result. Its MCP server lets AI agents use take_screenshot, get_page_info and capture_pdf. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.

Create a free ScreenshotNeo account and start with 1,000 screenshots a month at no charge.

FAQ

Can headless Chrome complete Entra MFA automatically?

No. Headless mode changes display behavior; it does not satisfy MFA, Conditional Access or device-compliance requirements. Complete the approved interactive step or use a workload identity.

Should I use device code for a cron job?

No. Device code requires a person. Use a service principal, managed identity or another supported workload identity for unattended execution.

How long does an Entra browser session last?

Session lifetime depends on tenant policy. Microsoft documents a 90-day PRT validity that is continuously renewed while the user actively uses the device, while session-frequency controls can require earlier reauthentication.

Is a Playwright persistent profile safe to share?

No. It can contain cookies and storage state that grant access. Keep it private, restrict permissions and never copy it between machines.

Does device code bypass Conditional Access?

No. The same tenant policies still evaluate the sign-in. A server without the required device registration, broker or compliance state can be denied.