From 855b49b9a6ebba1ded9110e9d57d3b23d218aa86 Mon Sep 17 00:00:00 2001 From: Revant Nandgaonkar Date: Fri, 5 Sep 2025 16:17:44 +0530 Subject: [PATCH] feat: optional multi idp selection via header for auth --- .github/workflows/docs.yml | 28 ---------------------------- castlecraft/auth.py | 18 +++++++++++++----- 2 files changed, 13 insertions(+), 33 deletions(-) delete mode 100644 .github/workflows/docs.yml diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index 9047d98..0000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Build and Deploy -on: - push: - branches: - - main -jobs: - build-and-deploy: - runs-on: ubuntu-latest - steps: - - name: Checkout 🛎️ - uses: actions/checkout@v2.3.1 - - - name: Generate API Docs 🔧 - run: | - git clone --depth 1 https://github.com/frappe/frappe /opt/frappe - python3 -m venv env - . ./env/bin/activate - pip3 -q install wheel - pip3 -q install pdoc - pip3 -q install -e /opt/frappe - pip3 -q install -e . - pdoc -o build castlecraft - - - name: Deploy 🚀 - uses: JamesIves/github-pages-deploy-action@4.1.1 - with: - branch: gh-pages - folder: build diff --git a/castlecraft/auth.py b/castlecraft/auth.py index 7c871bd..401e78c 100644 --- a/castlecraft/auth.py +++ b/castlecraft/auth.py @@ -14,7 +14,8 @@ def validate(): """ Additional validation to execute along with frappe request """ - idp = get_enabled_idp() + idp_name = frappe.get_request_header("X-Idp-Name", "") + idp = get_idp(idp_name) if not idp: return @@ -217,12 +218,19 @@ def validate_bearer_with_jwt_verification(token, idp): ) -def get_enabled_idp(): +def get_idp(idp_name=None): try: + if idp_name: + return frappe.get_cached_doc( + "CFE Identity Provider", + idp_name, + ) + return frappe.get_last_doc( "CFE Identity Provider", filters={"enabled": 1}, ) + except DoesNotExistError: return None @@ -290,7 +298,7 @@ def get_b64_decoded_json(b64str): def validate_signature(token, idp=None): - idp = idp or get_enabled_idp() + idp = idp or get_idp() allowed_audience = [audience.aud for audience in idp.allowed_audience] r = requests.get(idp.jwks_endpoint) jwks_keys = r.json() @@ -369,7 +377,7 @@ def delete_cached_jwt(email: str): def request_user_info(token, idp=None): if not idp: - idp = get_enabled_idp() + idp = get_idp() r = requests.get( idp.profile_endpoint, headers={"Authorization": f"Bearer {token}"}, @@ -379,7 +387,7 @@ def request_user_info(token, idp=None): def get_userinfo_from_idp(token, idp=None): if not idp: - idp = get_enabled_idp() + idp = get_idp() if idp.authorization_type == "Introspection": return request_user_info(token, idp) elif idp.authorization_type == "JWT Verification":