Spaces:
Running
Running
Download scripts/check_auth.py from Shurem/mz_chatbot: direct link, hf CLI and curl.
- Browser
- Download file 5.62 kB
-
https://huggingface.co/spaces/Shurem/mz_chatbot/resolve/main/scripts/check_auth.py
- Command line
-
hf download hf://spaces/Shurem/mz_chatbot/scripts/check_auth.py
-
curl -L -o check_auth.py https://huggingface.co/spaces/Shurem/mz_chatbot/resolve/main/scripts/check_auth.py
5.62 kB
| """ | |
| check_auth.py — offline checks for login (services/auth.py). No network, no database. | |
| uv run python scripts/check_auth.py | |
| Covers the session token (sign / verify / tamper / expiry / wrong secret), the | |
| company-domain rule, and verify_google_credential() against FAKE Google replies | |
| (wrong audience, unverified email, wrong domain, wrong hd, good). A real Google | |
| sign-in still needs a Google Client ID and is tested in the browser. | |
| """ | |
| from __future__ import annotations | |
| import sys | |
| from pathlib import Path | |
| sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) | |
| from app.config import settings # noqa: E402 | |
| from app.services import auth # noqa: E402 | |
| FAILED = 0 | |
| def check(label: str, ok: bool) -> None: | |
| global FAILED | |
| FAILED += 0 if ok else 1 | |
| print(f" [{'ok ' if ok else 'FAIL'}] {label}") | |
| class FakeResp: | |
| def __init__(self, status: int, data: dict): | |
| self.status_code = status | |
| self._data = data | |
| def json(self): | |
| return self._data | |
| def google_reply(**overrides) -> dict: | |
| base = { | |
| "aud": "client-123", "iss": "https://accounts.google.com", "email_verified": "true", | |
| "email": "ali@elipsestudio.com", "name": "Ali Khan", "picture": "http://x/p.png", "hd": "elipsestudio.com", | |
| } | |
| base.update(overrides) | |
| return base | |
| def expect_error(credential_reply: dict | None, status: int = 200) -> bool: | |
| auth.requests.get = lambda *a, **k: FakeResp(status, credential_reply or {}) # type: ignore[assignment] | |
| try: | |
| auth.verify_google_credential("tok") | |
| return False | |
| except auth.AuthError: | |
| return True | |
| def main() -> int: | |
| settings.auth_secret = "s" * 40 | |
| settings.google_client_id = "client-123" | |
| settings.allowed_email_domains = "elipsestudio.com, other.org" | |
| settings.allowed_emails = "" # ignore whatever the real .env lists, so this test is the same on every machine | |
| settings.auth_token_days = 7 | |
| print("\nsession token") | |
| tok = auth.create_token(7, "ali@elipsestudio.com", "Ali Khan") | |
| claims = auth.decode_token(tok) | |
| check("a fresh token verifies and carries the user id", claims is not None and claims["sub"] == "7") | |
| check("three dot-separated JWT parts", tok.count(".") == 2) | |
| h, p, sig = tok.split(".") | |
| check("tampered payload is rejected", auth.decode_token(f"{h}.{p[:-2]}xx.{sig}") is None) | |
| check("tampered signature is rejected", auth.decode_token(f"{h}.{p}.{sig[:-2]}xx") is None) | |
| check("an expired token is rejected", auth.decode_token(auth.create_token(7, "a@elipsestudio.com", "A", days=-1)) is None) | |
| check("garbage is rejected, not raised", auth.decode_token("not-a-token") is None and auth.decode_token("") is None) | |
| settings.auth_secret = "t" * 40 | |
| check("a token signed with another secret is rejected", auth.decode_token(tok) is None) | |
| settings.auth_secret = "s" * 40 | |
| settings.auth_secret = "" | |
| check("no AUTH_SECRET -> cannot issue a token", _raises(lambda: auth.create_token(1, "a@b.c", "A"))) | |
| check("no AUTH_SECRET -> nothing verifies", auth.decode_token(tok) is None) | |
| settings.auth_secret = "s" * 40 | |
| print("\ncompany domain") | |
| check("elipsestudio.com allowed", auth.email_domain_allowed("Ali@ElipseStudio.com")) | |
| check("second configured domain allowed", auth.email_domain_allowed("x@other.org")) | |
| check("gmail.com refused", not auth.email_domain_allowed("ali@gmail.com")) | |
| check("look-alike domain refused", not auth.email_domain_allowed("ali@elipsestudio.com.evil.io")) | |
| check("sub-domain refused", not auth.email_domain_allowed("ali@mail.elipsestudio.com")) | |
| check("no @ refused", not auth.email_domain_allowed("elipsestudio.com")) | |
| print("\napproved emails (ALLOWED_EMAILS)") | |
| settings.allowed_emails = "Boss@Gmail.com, sara@partner.io" | |
| check("a listed email is allowed, case-insensitive", auth.email_allowed("boss@gmail.com")) | |
| check("an unlisted gmail is still refused", not auth.email_allowed("other@gmail.com")) | |
| check("a company-domain email is still allowed by domain", auth.email_allowed("x@elipsestudio.com")) | |
| check("a look-alike of a listed email is refused", not auth.email_allowed("boss@gmail.com.evil.io")) | |
| settings.allowed_emails = "" | |
| print("\nverify_google_credential (fake Google replies)") | |
| real_get = auth.requests.get | |
| try: | |
| auth.requests.get = lambda *a, **k: FakeResp(200, google_reply()) # type: ignore[assignment] | |
| who = auth.verify_google_credential("tok") | |
| check("a good reply returns email/name/picture", who["email"] == "ali@elipsestudio.com" and who["name"] == "Ali Khan") | |
| check("Google says invalid (HTTP 400)", expect_error({}, 400)) | |
| check("wrong audience refused", expect_error(google_reply(aud="someone-else"))) | |
| check("wrong issuer refused", expect_error(google_reply(iss="https://evil.example"))) | |
| check("unverified email refused", expect_error(google_reply(email_verified="false"))) | |
| check("gmail address refused", expect_error(google_reply(email="ali@gmail.com", hd=""))) | |
| check("wrong hd refused even with a good-looking email", expect_error(google_reply(hd="evil.io"))) | |
| settings.google_client_id = "" | |
| check("no GOOGLE_CLIENT_ID -> clear error", expect_error(google_reply())) | |
| finally: | |
| auth.requests.get = real_get | |
| print() | |
| print("All checks passed." if not FAILED else f"{FAILED} check(s) FAILED") | |
| return 1 if FAILED else 0 | |
| def _raises(fn) -> bool: | |
| try: | |
| fn() | |
| except auth.AuthError: | |
| return True | |
| return False | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |