Skip to content

Better error msgs #61

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
467 changes: 358 additions & 109 deletions nbs/00_core.ipynb → nbs/00_cli.ipynb

Large diffs are not rendered by default.

93 changes: 51 additions & 42 deletions nbs/01_auth.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,17 @@
"id": "188fb79d",
"metadata": {},
"source": [
"For an end2end example on how to use this module see `./examples/auth/main.py`"
"This page describes how Plash Auth is implemented client side. \n",
"\n",
"Please see the [how to](how_to/auth.html) for instructions on how to use it."
]
},
{
"cell_type": "markdown",
"id": "59ce8def",
"metadata": {},
"source": [
"## Setup -"
]
},
{
Expand Down Expand Up @@ -43,74 +53,58 @@
"from plash_cli import __version__"
]
},
{
"cell_type": "markdown",
"id": "980c7492",
"metadata": {},
"source": [
"The signin completion route is where Google redirects users after authentication. Your app needs to add this route to handle the OAuth callback."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4b15411c",
"id": "d3504f51",
"metadata": {},
"outputs": [],
"source": [
"#| export\n",
"signin_completed_rt = \"/signin_completed\""
]
},
{
"cell_type": "markdown",
"id": "a4873761",
"metadata": {},
"source": [
"The production flag lets developers use mock authentication during development."
"_in_prod = os.getenv('PLASH_PRODUCTION', '') == '1'"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "718ef4d6",
"id": "e6590075",
"metadata": {},
"outputs": [],
"source": [
"#| export\n",
"_in_prod = os.getenv('PLASH_PRODUCTION', '') == '1'"
"def _signin_url(email_re: str=None, hd_re: str=None):\n",
" res = httpx.post(os.environ['PLASH_AUTH_URL'], json=dict(email_re=email_re, hd_re=hd_re), \n",
" auth=(os.environ['PLASH_APP_ID'], os.environ['PLASH_APP_SECRET']), \n",
" headers={'X-PLASH-AUTH-VERSION': __version__}).raise_for_status().json()\n",
" if \"warning\" in res: warn(res.pop('warning'))\n",
" return res"
]
},
{
"cell_type": "markdown",
"id": "f15e27d0",
"id": "04e96cb6",
"metadata": {},
"source": [
"This function makes the actual HTTP request to the Plash authentication service. It sends the email and domain filters to get back a signin URL and request ID that we'll use to track this authentication attempt."
"### Redirect route"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "73a7d63b",
"id": "4b15411c",
"metadata": {},
"outputs": [],
"source": [
"#| export\n",
"def _signin_url(email_re: str=None, hd_re: str=None):\n",
" res = httpx.post(os.environ['PLASH_AUTH_URL'], json=dict(email_re=email_re, hd_re=hd_re), \n",
" auth=(os.environ['PLASH_APP_ID'], os.environ['PLASH_APP_SECRET']), \n",
" headers={'X-PLASH-AUTH-VERSION': __version__}).raise_for_status().json()\n",
" if \"warning\" in res: warn(res.pop('warning'))\n",
" return res"
"#| exports\n",
"signin_completed_rt = \"/signin_completed\""
]
},
{
"cell_type": "markdown",
"id": "acf6707c",
"id": "78f8fc38",
"metadata": {},
"source": [
"This is the main function your app calls to get a Google signin URL. In development mode, it returns a mock URL to make testing easier. In production, it calls the Plash auth service and stores the request ID in the session for later verification."
"The signin completion route is where Plash Auth redirects users after authentication. Your app needs to add this route to complete the login."
]
},
{
Expand All @@ -133,12 +127,14 @@
},
{
"cell_type": "markdown",
"id": "1b33d30d",
"id": "ea4836e1",
"metadata": {},
"source": [
"After Google authentication, Plash sends back a JSON Web Token (JWT) containing the user's information. This function decodes and validates that token using the ES256 public key. If anything goes wrong with the JWT, it returns error details instead of crashing.\n",
"`mk_signin_url` is the function your app calls to create a Google signin URL for the user. \n",
"\n",
"Note: a JWT does not mean the message is encrypted. It ensures data integrity and authenticity, it protects against tampering and forgery. We use JWT tokens so your app can trust that the sign-in information and user details it receives after authentication really come from Plash (and by extension, Google), and have not been modified by an attacker."
"In development mode, it returns a mock URL to make testing easier. \n",
"\n",
"In production, it calls the Plash Auth service and stores the request ID in the session for later verification."
]
},
{
Expand All @@ -159,11 +155,14 @@
},
{
"cell_type": "markdown",
"id": "6c1fe53f",
"id": "2018d4e9",
"metadata": {},
"source": [
"A custom exception for when authentication fails. This makes it easier for your app to handle auth errors specifically.\n",
"See `./examples/auth/main.py` for an example on how you can catch this exception in your application."
"After Google authentication, Plash sends back a JSON Web Token (JWT) containing the user's information. This function decodes and validates that token using the ES256 public key. If anything goes wrong with the JWT, it returns error details instead of crashing.\n",
"\n",
"::: {.callout-note}\n",
"A JWT does not mean the message is encrypted. It ensures data integrity and authenticity, it protects against tampering and forgery. We use JWT tokens so your app can trust that the sign-in information and user details it receives after authentication really come from Plash (and by extension, Google), and have not been modified by an attacker.\n",
":::"
]
},
{
Expand All @@ -181,12 +180,12 @@
},
{
"cell_type": "markdown",
"id": "62320729",
"id": "bb5e03fd",
"metadata": {},
"source": [
"This is the main function your app calls in the signin completion route. It verifies the JWT reply matches the original request (preventing CSRF attacks), checks for any authentication errors, and returns the user's Google ID if everything is valid.\n",
"`PlashAuthError` is a custom exception for when authentication fails. This makes it easier for your app to handle auth errors specifically.\n",
"\n",
"When testing locally this will always return the mock Google ID `'424242424242424242424'`."
"Please see the [auth example](https://github.com/AnswerDotAI/plash_cli/blob/main/examples/auth/main.py) for an example on how you can catch this exception in your application."
]
},
{
Expand All @@ -207,6 +206,16 @@
" return parsed['sub']"
]
},
{
"cell_type": "markdown",
"id": "3b9c0959",
"metadata": {},
"source": [
"`goog_id_from_signin_reply` is the function your app calls in the signin completion route. It verifies the JWT reply matches the original request (preventing CSRF attacks), checks for any authentication errors, and returns the user's Google ID if everything is valid.\n",
"\n",
"When testing locally this will always return the mock Google ID `'424242424242424242424'`."
]
},
{
"cell_type": "markdown",
"id": "72eaabaa",
Expand Down
6 changes: 4 additions & 2 deletions nbs/_quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ website:
left:
- text: "Home"
href: https://pla.sh
- text: "Learn"
- text: "Docs"
href: https://docs.pla.sh
right:
- icon: github
Expand All @@ -44,6 +44,8 @@ website:
- section: Explanations
contents: explains/*
- section: Reference
contents: reference/*
contents:
- 00_cli.ipynb
- 01_auth.ipynb

metadata-files: [nbdev.yml]
Loading