fastapi-sso icon indicating copy to clipboard operation
fastapi-sso copied to clipboard

LinkedIn SSO hanging on getting accessToken

Open antonionieto opened this issue 9 months ago • 7 comments

Hey,

I have built a FastAPI app that is deployed on a Google Cloud Run instance, connected with a given subdomain. The app allows users to signing using both Google and LinkedIn. I am powering that functionality with fastapi-sso library but I am getting an issue with the LinkedIn one. After dealing with this for more than a week, I decided on posting it here and see if anyone could help.

Context:

  • Google SSO is working well, within the same conditions (it's the same app).
  • LinkedIn SSO is working well when testing the app locally, but it hangs on getting the accessToken when deployed.
  • The process manages to get the authorisation token (previous step into getting the accessToken), but it gets a timeout error when request the accessToken.

See image of the code snippet where the process hangs (line 494, fastapi_sso/sso/base.py): image

Any thoughts why this may be happening?

Thanks for your amazing contribution to the community, btw!

antonionieto avatar Apr 29 '24 17:04 antonionieto

Hi @antonionieto! Thanks for posting this, this seems like a pickle, it's weird that it's working for you locally. Could you please also attach the traceback? It would be cool to see more. TimeoutError is quite unexpected, I would like to see if it's a network or transport issue rather than oauth / http.

tomasvotava avatar Apr 30 '24 08:04 tomasvotava

Hi @tomasvotava, thanks for the quick reply! Sure, here is an screenshot of the traceback. It seems like the LinkedIn acessToken endpoint is not responding at all. Authorisation endpoint is working though, as I checked it out and I am correctly getting the authorisation code.

traceback-screenshot

antonionieto avatar May 01 '24 14:05 antonionieto

Thanks for the traceback! httpx uses a default timeout of 5 seconds to wait for the socket to connect, I cannot imagine why it would take longer than that, but we could tinker with that number. I cannot stop thinking this really has to be some kind of network issue, because you said it works well when run locally.

How do you run your app in Cloud Run? Could that be that e.g. uvicorn has some async issues blocking httpx's requests?

Could you try getting a refresh token locally (you can try simply accessing sso.refresh_token property after successful call to verify_and_process) and then exchanging the refresh token for an access token in some simple Cloud Run app? Something like:

import httpx

async def amain():
    data = {"grant_type": "refresh_token", "refresh_token": "your-secret-token", "client_id": "your client id", "client_secret": "your client secret"}
    async with httpx.AsyncClient() as session:
        response = await session.post("https://www.linkedin.com/oauth/v2/accessToken", data=data)
        response.raise_for_status()
        return response.json()

Running this without uvicorn and any other overhead successfully could point us in the direction. If this fails as well, then I'd really say it's some fishy network issue you should probably either open with Linked or Google.

tomasvotava avatar May 02 '24 07:05 tomasvotava

It actually doesn't matter if you send the refresh token or not, plainly calling await session.post("https://www.linkedin.com/oauth/v2/accessToken") and checking that there actually was a response should be enough. You'll probably get 400 if you don't send anything else.

tomasvotava avatar May 02 '24 07:05 tomasvotava

I just tried out with a simple HTTP POST, as suggested, and still got the same issue: the LinkedIn server does not respond at all. It just weird, cause the authorisation endpoint works well (also in Cloud Run). This is really confusing :|

Will try to explore other ways and make sure I share the solution (if I find it) with the community. Btw, really appreciate the time you dedicate into this @tomasvotava!

antonionieto avatar May 02 '24 18:05 antonionieto

Ouch, that's hard to debug, you could probably try setting up logging to DEBUG level, maybe httpx will tell you more that way. Also, try using requests module instead, I think it uses urllib instead of httpcore, but that's just guessing.

Feel free to let me know when you know more, I'll be glad to help and it would be awesome to have some resolution for others who may stumble upon this.

tomasvotava avatar May 02 '24 18:05 tomasvotava

Good news! I managed to find the issue and it was, effectively, a networking issue - It turned out Cloud Run was routing all the traffic to an internal VPC and the requests weren't able to reach out the public internet. It was solved by creating a NAT gateway and assigning a static IP address (reference).

The confusing thing was, also, that I was using Google SignIn (leveraging fastapi-sso as well) and it was working well! My assumption is that given it is a Google service, it somehow manages to reach the SSO provider without getting into the public internet (maybe I'm completely wrong).

Anyways, really appreciate the community support here! <3

Feel free to close the issue then :)

antonionieto avatar May 03 '24 17:05 antonionieto

Thanks a lot for letting me know! This may help others in the future.

tomasvotava avatar May 18 '24 19:05 tomasvotava