Fix auth provider resources
All checks were successful
/ build (push) Successful in 5s
/ test (push) Successful in 5s

This commit is contained in:
phil 2025-02-20 21:16:43 +01:00
parent 3f945310a4
commit 347c395394
3 changed files with 56 additions and 23 deletions

View file

@ -108,7 +108,6 @@ async def home(
"show_token": settings.show_token, "show_token": settings.show_token,
"user": user, "user": user,
"now": datetime.now(), "now": datetime.now(),
"auth_provider": provider,
} }
if provider is None or token is None: if provider is None or token is None:
context["providers"] = providers context["providers"] = providers
@ -117,26 +116,28 @@ async def home(
context["access_token_parsed"] = None context["access_token_parsed"] = None
context["refresh_token_parsed"] = None context["refresh_token_parsed"] = None
context["resources"] = None context["resources"] = None
context["auth_provider"] = None
else: else:
context["auth_provider"] = provider
context["access_token"] = token["access_token"] context["access_token"] = token["access_token"]
try: try:
access_token_parsed = provider.decode(token["access_token"], verify_signature=False) access_token_parsed = provider.decode(token["access_token"], verify_signature=False)
context["access_token_parsed"] = access_token_parsed
except PyJWTError as err: except PyJWTError as err:
access_token_parsed = {"Cannot parse": err.__class__.__name__} access_token_parsed = {"Cannot parse": err.__class__.__name__}
try: try:
context["access_token_scope"] = access_token_parsed["scope"] id_token_parsed = provider.decode(token["id_token"], verify_signature=False)
except KeyError: context["id_token_parsed"] = id_token_parsed
context["access_token_scope"] = None except PyJWTError as err:
context["id_token_parsed"] = provider.decode(token["id_token"], verify_signature=False) id_token_parsed = {"Cannot parse": err.__class__.__name__}
context["access_token_parsed"] = access_token_parsed try:
refresh_token_parsed = provider.decode(token["refresh_token"], verify_signature=False)
context["refresh_token_parsed"] = refresh_token_parsed
except PyJWTError as err:
refresh_token_parsed = {"Cannot parse": err.__class__.__name__}
context["access_token_scope"] = access_token_parsed.get("scope")
context["resources"] = registry.resources context["resources"] = registry.resources
context["resource_providers"] = provider.resource_providers context["resource_providers"] = provider.resource_providers
try:
context["refresh_token_parsed"] = provider.decode(
token["refresh_token"], verify_signature=False
)
except PyJWTError as err:
context["refresh_token_parsed"] = {"Cannot parse": err.__class__.__name__}
return templates.TemplateResponse(name="home.html", request=request, context=context) return templates.TemplateResponse(name="home.html", request=request, context=context)

View file

@ -1,9 +1,10 @@
from typing import Annotated, Any from typing import Annotated, Any
import logging import logging
from json import JSONDecodeError
from authlib.oauth2.rfc6749 import OAuth2Token from authlib.oauth2.rfc6749 import OAuth2Token
from httpx import AsyncClient from httpx import AsyncClient, HTTPError
from jwt.exceptions import ExpiredSignatureError, InvalidTokenError from jwt.exceptions import DecodeError, ExpiredSignatureError, InvalidTokenError
from fastapi import FastAPI, HTTPException, Depends, Request, status from fastapi import FastAPI, HTTPException, Depends, Request, status
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
@ -84,6 +85,10 @@ async def get_resource(
"auth_provider": user.auth_provider_id, "auth_provider": user.auth_provider_id,
}, },
) )
except HTTPError as err:
raise HTTPException(
status.HTTP_503_SERVICE_UNAVAILABLE, err.__class__.__name__
)
except Exception as err: except Exception as err:
raise HTTPException( raise HTTPException(
status.HTTP_500_INTERNAL_SERVER_ERROR, err.__class__.__name__ status.HTTP_500_INTERNAL_SERVER_ERROR, err.__class__.__name__
@ -151,7 +156,7 @@ async def get_auth_provider_resource(
) -> ProcessResult: ) -> ProcessResult:
if token is None: if token is None:
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "No auth token") raise HTTPException(status.HTTP_401_UNAUTHORIZED, "No auth token")
access_token = token["access_token"] access_token = token
async with AsyncClient() as client: async with AsyncClient() as client:
resp = await client.get( resp = await client.get(
url=provider.get_resource_url(resource_name), url=provider.get_resource_url(resource_name),
@ -165,9 +170,19 @@ async def get_auth_provider_resource(
# Only a demo, real application would really process the response # Only a demo, real application would really process the response
resp_length = len(resp.text) resp_length = len(resp.text)
if resp_length > 1024: if resp_length > 1024:
return ProcessResult(msg=f"The resource is too long ({resp_length} bytes) to show here") return ProcessResult(
msg=f"The resource is too long ({resp_length} bytes) to show in this demo, here is just the begining in raw format",
start=resp.text[:100] + "...",
)
else: else:
try:
resp_json = resp.json()
except JSONDecodeError:
return ProcessResult(msg="The resource is not formatted in JSON", text=resp.text)
if isinstance(resp_json, dict):
return ProcessResult(**resp.json()) return ProcessResult(**resp.json())
elif isinstance(resp_json, list):
return ProcessResult(**{str(i): line for i, line in enumerate(resp_json)})
# @resource_server.get("/public") # @resource_server.get("/public")

View file

@ -66,12 +66,8 @@
{% endif %} {% endif %}
<hr> <hr>
<div class="content"> <div class="content">
<!--
-->
{% if resources %} {% if resources %}
<p> <p>This application provides all these resources, eventually protected with scope or roles:</p>
This application provides all these resources, eventually protected with scope or roles:
</p>
<div class="links-to-check"> <div class="links-to-check">
{% for name, resource in resources.items() %} {% for name, resource in resources.items() %}
{% if resource.default_resource_id %} {% if resource.default_resource_id %}
@ -91,8 +87,29 @@
{% endfor %} {% endfor %}
</div> </div>
{% endif %} {% endif %}
{% if auth_provider.resources %}
<p>{{ auth_provider.name }} is also defined as a provider for these resources:</p>
<div class="links-to-check">
{% for resource in auth_provider.resources %}
{% if resource.default_resource_id %}
<button resource-name="{{ resource.resource_name }}"
resource-id="{{ resource.default_resource_id }}"
onclick="get_resource('{{ resource.resource_name }}', '{{ access_token }}', '{{ auth_provider.id }}', '{{ resource.default_resource_id }}')"
>
{{ resource.name }}
</button>
{% else %}
<button resource-name="{{ resource.name }}"
onclick="get_resource('{{ resource.resource_name }}', '{{ access_token }}', '{{ auth_provider.id }}')"
>
{{ resource.name }}
</button>
{% endif %}
{% endfor %}
</div>
{% endif %}
{% if resource_providers %} {% if resource_providers %}
<p>{{ auth_provider.name }} allows this applicaiton to request resources from third party resource providers:</p> <p>{{ auth_provider.name }} allows this application to request resources from third party resource providers:</p>
{% for resource_provider in resource_providers %} {% for resource_provider in resource_providers %}
<div class="links-to-check"> <div class="links-to-check">
{{ resource_provider.name }} {{ resource_provider.name }}