Skip to main content

Browser-grade OAuth login for any Microsoft-federated provider - without a browser.

Project description

Entrance

Entrance Logo

Your headless entrance to Microsoft Entra.
Browser-grade OAuth login for any Microsoft-federated provider - without a browser.

visits Python 3.10+ No browser MIT license

[!WARNING] For educational and research purposes only. Use it solely against accounts you own or with the explicit authorization of the account/tenant owner. It drives a real sign-in with real credentials - treat the cookie jar and any tokens like passwords. See the Disclaimer below.

About The Project

Plenty of services hand you an OAuth "open this URL in a browser to log in" link and federate the actual authentication to Microsoft Entra. entrance walks that flow for you over pure HTTP - no Playwright, no headless Chromium, no Selenium - and hands back the authorization code (or exchanged tokens). Point it at any authorize URL that ends up at login.microsoftonline.com and it logs in, handles MFA, and returns.

The whole thing is one small module and two dependencies.

How It Works

The trick that makes browserless login actually work against a modern Entra tenant:

  • Impersonate Opera, not Chrome. Entra serves a JavaScript-only "Chrome SSO pull" page (un-replayable without a real browser) when it sees a Google Chrome user-agent. Tell it you're Opera - a non-Chrome Chromium - and it serves the plain credential page instead, which is replayable.
  • Real browser fingerprint. curl_cffi replays a genuine browser TLS/JA3 fingerprint, so Entra's edge sees a browser at the wire level.
  • Replay the login XHRs by hand - GetCredentialTypelogin → "Stay signed in?". For MFA, the SAS/BeginAuth + SAS/EndAuth pair with a TOTP code computed via pyotp.
  • Intercept the code at the callback redirect - it's read off the Location header and never actually delivered.
  • Silent reuse. The Microsoft session cookie jar is persisted, so the next run logs in with no password (and no MFA prompt) until it expires.

Features

  • 🚪 No browser - pure HTTP, drives login.microsoftonline.com directly
  • 🌐 Provider-agnostic - give it any OAuth2 authorize URL federated to Entra
  • 🔐 Headless MFA - TOTP second factor solved automatically from your authenticator secret
  • 🍪 Silent SSO - persisted cookie jar means password-free reruns
  • 🎛️ Three return modes - the raw code, exchanged access_token, or just the Microsoft redirect
  • 📦 Tiny - one module, curl_cffi + pyotp

Installation

pip install ms-entrance
# or
uv add ms-entrance

The import name is entrance (e.g. from entrance import login). Requires Python 3.10+; curl_cffi and pyotp are pulled in automatically.

Quickstart

from entrance import login

# Intercept the authorization code from any Entra-federated authorize URL
res = login(
    "https://provider.example/authorize?client_id=...&state=...&code_challenge=...",
    username="you@school.ch",
    password="...",
    totp_secret="JBSWY3DPEHPK3PXP",   # optional - only if the account has TOTP MFA
)

print(res["code"])           # the authorization code (intercepted at the callback)
print(res["callback_url"])   # the full callback URL - built, NOT sent

MFA, two ways. Pass totp_secret (Base32 - a fresh code is generated each attempt) or totp_code if you already hold a valid 6-digit code from your own authenticator:

login(authorize_url, "you@school.ch", "...", totp_secret="JBSWY3DPEHPK3PXP")
login(authorize_url, "you@school.ch", "...", totp_code="123456")  # used as-is

Exchange the code for tokens - pass a token_url and it does the OAuth exchange for you:

res = login(authorize_url, "you@school.ch", "...",
            code_verifier=verifier, token_url="https://provider.example/token")
print(res["access_token"])

Just the Microsoft handoff - stop at the redirect Microsoft issues back to the provider, untouched:

res = login("https://provider.example/", "you@school.ch", "...", ms_redirect=True)
print(res["redirect_url"])   # https://provider.example/?code=...&state=...&session_state=...

Silent reuse - the first call saves .ms_session.json; every call after that skips the password:

login(authorize_url, "you@school.ch", "...")   # full login, saves the jar
login(authorize_url)                            # silent - no password, no MFA

Cookies your way - file or inline. cookies takes a file path (loaded on entry, written back on exit), an inline list of cookie dicts, or None. Either way the result always carries session_cookies, so you can store them yourself instead of touching disk:

# inline in, inline out - nothing written to disk
res = login(authorize_url, "you@school.ch", "...", cookies=None)
jar = res["session_cookies"]                    # list of {name, value, domain, path}

# later, seed straight from memory (or your own DB/secret store)
res = login(authorize_url, cookies=jar)         # silent, no file involved

Return Value

Key When What
code always the authorization code
code_verifier / state always echoed back for your own exchange
callback_url default mode the redirect_uri?code=…&state=…, built not sent
access_token / tokens when token_url is set the exchanged token response
redirect_url / session_state when ms_redirect=True the raw Microsoft → provider redirect

Caveats

  • Works only against managed Entra tenants (login.microsoftonline.com), not third-party federated IdPs (ADFS, Google, etc.).
  • Push / SMS MFA can't be done headless - only TOTP (authenticator app). Enroll one and pass its Base32 secret.
  • Microsoft tweaks its login pages; if a flow breaks, the user-agent or a field name is usually the culprit.

Disclaimer

Entrance is published for educational and research purposes only - to document how OAuth2 / OpenID Connect authorization-code + PKCE flows behave when federated through Microsoft Entra, and how a browserless client negotiates them.

Use it only against accounts you own, or with the explicit authorization of the account or tenant owner. You alone are responsible for your use of it and for complying with Microsoft's terms, your identity provider's terms, your institution's acceptable-use policy, and applicable law. Automating logins to accounts you do not own, evading access controls, or circumventing MFA you were not granted is not the intended use. The software is provided "as is", without warranty of any kind, and the author accepts no liability for misuse. Not affiliated with or endorsed by Microsoft.

License

MIT (c) PianoNic

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ms_entrance-1.2.0.tar.gz (11.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ms_entrance-1.2.0-py3-none-any.whl (12.5 kB view details)

Uploaded Python 3

File details

Details for the file ms_entrance-1.2.0.tar.gz.

File metadata

  • Download URL: ms_entrance-1.2.0.tar.gz
  • Upload date:
  • Size: 11.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for ms_entrance-1.2.0.tar.gz
Algorithm Hash digest
SHA256 381abd76d4902b4efe77b60286435b93147502f8a19c0b4ff770ca8107fd7644
MD5 6b2b81487aa804f84686f85ce875762b
BLAKE2b-256 89324cdfea34641efd908c70e0215bbe723700f2092332adf77fcad403cfe81b

See more details on using hashes here.

File details

Details for the file ms_entrance-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: ms_entrance-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 12.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for ms_entrance-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 13a1dcc7a1d2f181454970b9a7f9c5a1f60a8e256b307ba78457a6d0eed3b9e7
MD5 60f6e2dc398f5a696b0050a653faea19
BLAKE2b-256 8a2ad5d50a1f1981bb53ab717a5977003e3dbdaf69cee3627e1ee46339bb5d5f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page