Skip to content

Starlette integration OIDC issues (with regard to response_mode and response_type.) #793

@nnhanndakara

Description

@nnhanndakara

Describe the bug

The Starlette integration's OAuth2 code (at integrations/starlette_client) currently has a number of issues:

  1. StarletteOAuth2App.authorize_access_token as currently written isn't capable of handling an OIDC callback when response_mode is set to form_post. Ignoring 2 below for a moment, the fix for this is pretty easy, and something like this should suffice (in the spirit of the Flask integration):

    if request.method == "GET":
        params = {
            "code": request.query_params.get("code"),
            "state": request.query_params.get("state"),
        }
    else:
        async with request.form() as form:
            params = {
                "code": form.get("code"),
                "state": form.get("state"),
            }
  2. In my testing so far, commit a53173e breaks on any callback where response_type does not result in code in the callback. In my case, I'm asking only for id_token, so code should not be present (only id_token and state.) Raising on code being missing in this case seems like an error, if I'm not mistaken?

  3. Additionally, I'm not asking for an access token at all (which would require token in response_type, I think?) I've not configured an access token endpoint for this reason. I don't think the service I'm authenticating against even supports one, as all I need is the id_token. Should requesting a token be optional in this case?

Error Stacks

I'll have to back out my changes to get the first one, but for number 3 it's:

  File "/Volumes/work_workspace/Projects/aacc-lti_forms/src/lti_forms/app.py", line 171, in launch                                                                           
    token = await client.authorize_access_token(request)                                                                                                                     
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                     
  File "/Volumes/work_workspace/Projects/aacc-lti_forms/.venv/lib/python3.12/site-packages/authlib/integrations/starlette_client/apps.py", line 95, in authorize_access_token
    token = await self.fetch_access_token(**params, **kwargs)                                                                                                                
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                
  File "/Volumes/work_workspace/Projects/aacc-lti_forms/.venv/lib/python3.12/site-packages/authlib/integrations/base_client/async_app.py", line 133, in fetch_access_token   
    token = await client.fetch_token(token_endpoint, **params)                                                                                                               
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                               
  File "/Volumes/work_workspace/Projects/aacc-lti_forms/.venv/lib/python3.12/site-packages/authlib/integrations/httpx_client/oauth2_client.py", line 163, in _fetch_token    
    resp = await self.post(                                                                                                                                                  
           ^^^^^^^^^^^^^^^^                                                                                                                                                  
  File "/Volumes/work_workspace/Projects/aacc-lti_forms/.venv/lib/python3.12/site-packages/httpx/_client.py", line 1859, in post                                             
    return await self.request(                                                                                                                                               
           ^^^^^^^^^^^^^^^^^^^                                                                                                                                               
  File "/Volumes/work_workspace/Projects/aacc-lti_forms/.venv/lib/python3.12/site-packages/authlib/integrations/httpx_client/oauth2_client.py", line 119, in request         
    return await super().request(method, url, auth=auth, **kwargs)                                                                                                           
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                           
  File "/Volumes/work_workspace/Projects/aacc-lti_forms/.venv/lib/python3.12/site-packages/httpx/_client.py", line 1527, in request                                          
    request = self.build_request(                                                                                                                                            
              ^^^^^^^^^^^^^^^^^^^                                                                                                                                            
  File "/Volumes/work_workspace/Projects/aacc-lti_forms/.venv/lib/python3.12/site-packages/httpx/_client.py", line 366, in build_request                                     
    url = self._merge_url(url)                                                                                                                                               
          ^^^^^^^^^^^^^^^^^^^^                                                                                                                                               
  File "/Volumes/work_workspace/Projects/aacc-lti_forms/.venv/lib/python3.12/site-packages/httpx/_client.py", line 396, in _merge_url                                        
    merge_url = URL(url)                                                                                                                                                     
                ^^^^^^^^                                                                                                                                                     
  File "/Volumes/work_workspace/Projects/aacc-lti_forms/.venv/lib/python3.12/site-packages/httpx/_urls.py", line 121, in __init__                                            
    raise TypeError(                                                                                                                                                         
TypeError: Invalid type for url.  Expected str or httpx.URL, got <class 'NoneType'>: None                                                                                    

To Reproduce

I don't have a small example of this as I just encountered it, but I essentially followed the examples, just adding the response_mode and response_type values requested by the application.

Expected behavior

The response is validated, and id_token parsed so that I can finish session setup.

Environment:

  • OS: macOS 26
  • Python Version: 3.12.11
  • Authlib Version: 1.6.1 (from pip) patched as described in 1 for 1 and 3. Then HEAD to check if the issues in question have been fixed, which lead to 2.

Additional context

This is for authentication against an application that uses OIDC specifically for the authentication piece. The overarching standard governing its use is LTI 1.3 (it's for higher ed.)

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions