Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
611e8c9
Changes for passkey implementation
rmad17 Jun 1, 2026
ec66c0f
Added missing test cases and edge case fix
rmad17 Jun 2, 2026
d2d1f21
Resolved snake case to camel case for correct parsing
rmad17 Jun 2, 2026
7691a0c
Reverting to snake case - as per auth0 api docs.
rmad17 Jun 2, 2026
3233fff
Reverted lint fixes for easier review
rmad17 Jun 2, 2026
66071e9
Edge case fix for Double URL-encoding and extra validation check
rmad17 Jun 2, 2026
3809edb
SDK-8780 PR review changes
rmad17 Jun 5, 2026
d299dbf
SDK-8780 Added review changes for integrating passkey sign-in with SD…
rmad17 Jun 5, 2026
0aacc8e
PR Review Changes
rmad17 Jun 5, 2026
786b4ec
MFA Support for Passkeys
rmad17 Jun 15, 2026
7e9225f
Sync with main
rmad17 Jun 25, 2026
22d2997
Changes for MyAccount Factors Schema
rmad17 Jun 25, 2026
a0100b7
Resolved merge conflicts
rmad17 Jun 25, 2026
69ea847
Added docs and feedback changes
rmad17 Jun 28, 2026
f4308ab
Updated example docs
rmad17 Jun 29, 2026
e91b27e
Updated Examples
rmad17 Jun 30, 2026
6dc142a
Linting fix for imports
rmad17 Jun 30, 2026
4fe53a4
Addressed Review comments for passkeys
rmad17 Jul 1, 2026
ec91808
Resolved conflicts
rmad17 Jul 1, 2026
922a3d2
Resolved review feedback
rmad17 Jul 2, 2026
a4e8757
Updated documentation, test cases and parameter type for dpop nonce
rmad17 Jul 6, 2026
74dbde9
README Changes and MFA refactor revert
rmad17 Jul 6, 2026
f8b76c4
MFA test fixes post revert
rmad17 Jul 6, 2026
cb8a8f9
Doc changes and minor code optimizations
rmad17 Jul 8, 2026
2f18b69
Added missing docstrings
rmad17 Jul 8, 2026
6d7a951
Removed duplicate Dpop docs
rmad17 Jul 8, 2026
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
3 changes: 2 additions & 1 deletion src/auth0_server_python/auth_schemes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .bearer_auth import BearerAuth
from .dpop_auth import DPoPAuth

__all__ = ["BearerAuth"]
__all__ = ["BearerAuth", "DPoPAuth"]
55 changes: 55 additions & 0 deletions src/auth0_server_python/auth_schemes/dpop_auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import base64
import hashlib
import time
import uuid

import httpx
from jwcrypto import jwk
from jwcrypto import jwt as jwcrypto_jwt


def _base64url(data: bytes) -> str:
return base64.urlsafe_b64encode(data).rstrip(b"=").decode("ascii")


class DPoPAuth(httpx.Auth):
def __init__(self, token: str, key: "jwk.JWK") -> None:
public_jwk = key.export_public(as_dict=True)
if public_jwk.get("kty") != "EC" or public_jwk.get("crv") != "P-256":
raise ValueError("DPoP key must be an EC P-256 key")
try:
token.encode("ascii")
except UnicodeEncodeError:
raise ValueError("Access token must contain only ASCII characters")
self._token = token
self._key = key
self._public_jwk = public_jwk

def __repr__(self) -> str:
return "DPoPAuth(token=[REDACTED], key=[REDACTED])"

def __str__(self) -> str:
return "DPoPAuth(token=[REDACTED], key=[REDACTED])"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should drop this.


def auth_flow(self, request: httpx.Request):
proof = self._make_proof(request.method, str(request.url))
request.headers["Authorization"] = f"DPoP {self._token}"
Comment thread
kishore7snehil marked this conversation as resolved.
request.headers["DPoP"] = proof
yield request

def _make_proof(self, method: str, url: str) -> str:
htu = url.split("?")[0].split("#")[0]
ath = _base64url(hashlib.sha256(self._token.encode("ascii")).digest())

header = {"typ": "dpop+jwt", "alg": "ES256", "jwk": self._public_jwk}
payload = {
"jti": str(uuid.uuid4()),
"htm": method.upper(),
"htu": htu,
"iat": int(time.time()),
"ath": ath,
}

token = jwcrypto_jwt.JWT(header=header, claims=payload)
token.make_signed_token(self._key)
return token.serialize()
Loading
Loading