How to retrieve query parameter from URL after RedirectResponse in FastAPI?

Question:

I’m implementing an oauth autorization code flow.

What I want is to retrieve the code that shows in the url after redirection. I’ve made researches but haven’t found something really helpful. I think that if I can get the current url in the browser after the RedirectResponse, I can then extract the code parameter of it with python module like urllib.parse. Or, does FastApi have a way to help me get that url after the RedirectResponse? I saw on their documentation the Background Tasks but I don’t know if that can actually help me retrieve the url after the redirection. I tried using selenium library after having seen this but it opens up a new window and when I try to apply the driver.get('put_your_site_name') suggested in the comments, it just takes too long.

Here’s the code excerpt which is redirecting me to the url in the browser with the code as a parameter :

from uuid import uuid4

from oauthlib.oauth2 import WebApplicationClient

from fastapi import APIRouter, Request, Response

from fastapi.responses import RedirectResponse



router = APIRouter()

@router.get("/install/")
async def install(request: Request) -> Response:
    """Trigger the client identification process."""
    client_id = "xxx"
    client = WebApplicationClient(client_id)
    state = str(uuid4())

    authorization_url = f"https://api-url.com/auth/authorize?client_id={client_id}"
    url = client.prepare_request_uri(
        authorization_url,
        redirect_uri="http://127.0.0.1:8000/callback/",
        scope=["read:user"],
        state=state,
    )

    return RedirectResponse(url=url)

With the above, I’m redirected to the callback url with the authorization code as parameter : http://127.0.0.1:8000/callback/?code=random-string-xyz.
I found also this which is quite close to what I’m looking for, except I’m trying to get the current path only after the redirection.

I’ve also checked FastApi query parameters part and tried with the following :

import typing
from uuid import uuid4

from oauthlib.oauth2 import WebApplicationClient

from fastapi import APIRouter, Request, Response

from fastapi.responses import RedirectResponse



router = APIRouter()

@router.get("/install/")
async def install(request: Request, code : typing.Optional[str] = None) -> Response:
    """Trigger the client identification process."""
    client_id = "xxx"
    client = WebApplicationClient(client_id)
    state = str(uuid4())

    authorization_url = f"https://api-url.com/auth/authorize?client_id={client_id}"
    url = client.prepare_request_uri(
        authorization_url,
        redirect_uri="http://127.0.0.1:8000/callback/",
        scope=["read:user"],
        state=state,
    )


    print("n code : ", code, "n")
    return RedirectResponse(url=url)

Output : code : None, as the code is returned after the redirection I guess?

How do I get that url programmatically to retrieve then the code? Or maybe do you have any other way to get it ..?

Asked By: aaronted

||

Answers:

You should instead retrieve the value of the code parameter inside the /callback, not /install, endpoint, since that is the endpoint to which you are being redirected—according to the link provided in your question:

http://127.0.0.1:8000/callback/?code=random-string-xyz
                     ^^^^^^^^^

In FastAPI, you can get query parameters by declaring the parameters in your endpoint. As per the documentation :

When you declare other function parameters that are not part of the
path parameters, they are automatically interpreted as "query"
parameters.

Example:

@router.get("/callback")
async def install(code : str = None):
    # ...

Alternatively, you can use Starlette’s Request object directly (see Starlette’s documentation as well), as described in this answer, as well as here and here.

Answered By: Chris
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.