jointakahe / takahe

An ActivityPub/Fediverse server
BSD 3-Clause "New" or "Revised" License
1.1k stars 83 forks source link

Non-oauth compliant authentication flow? #670

Open frankdilo opened 7 months ago

frankdilo commented 7 months ago

I am trying to integrate takahe with Typefully which recently added Mastodon support, but connecting accounts is failing at the last step of the oauth proces, when the client tries to fetch the token. https://share.cleanshot.com/kLCMYtcM

I am seeing an error in our Python backend:

Error fetching Mastodon token: (missing_token) Missing access token parameter.

I traced it down to this Python implementation of oauth.

Looking at the responses I get from a standard Mastodon server, it seems that they put the redirect URI with the token in the body of the response, while Takahe only puts it in the location header (notice the empty response body compared to the Mastodon Social response).

andrewgodwin commented 7 months ago

Mastodon's oauth implementation sadly tends not to be fully compliant with the spec, and I believe this is one such case:

4.1.2.  Authorization Response

   If the resource owner grants the access request, the authorization
   server issues an authorization code and delivers it to the client by
   adding the following parameters to the query component of the
   redirection URI using the "application/x-www-form-urlencoded" format,
   per Appendix B:

We've already added a few workarounds to make Mastodon clients happy, so this would need to be one such workaround; I don't have the time to go do it myself, but I'd welcome a pull request that tackled it.

frankdilo commented 7 months ago

I would be happy to work on a PR! Any pointers to the workarounds you already added so I have a place to start?

andrewgodwin commented 7 months ago

It's pretty much all contained in https://github.com/jointakahe/takahe/blob/main/api/views/oauth.py - we have our own oauth backend almost entirely because of the implementation being weird.

patrick91 commented 2 months ago

I've been trying to reproduce this locally and I found a different issue, basically it looks typefully might be using oauth/authorize/ (with the trailing slash) instead of oauth/authorize (without the trailing slash)

image

I think I fixed it locally by duplicating the view:

https://github.com/jointakahe/takahe/assets/667029/1af0710f-8c67-40e3-9059-623aff813c85

but now I'm not sure who's wrong, we can fix this easily in takahe, but should we? 😊 (happy to make a pr in that case)

TkTech commented 2 months ago

If it's not following redirects, the same view can be served with-and-without the / by changing:

path("oauth/authorize", oauth.AuthorizationView.as_view())

to something like

re_path(r"oauth/authorize/?$", oauth.AuthorizationView.as_view())

in https://github.com/jointakahe/takahe/blob/7c34ac78eddc54f8d1918d36c8baf822a104ffbb/takahe/urls.py#L347C1-L347C2

patrick91 commented 2 months ago

@TkTech yup! I'll wait for @frankdilo to double check this 😊

frankdilo commented 2 months ago

@patrick91 this is my auth code

CleanShot 2024-04-15 at 09 13 51@2x

requests_oauthlib must be adding the trailing slash to my provided auth url

it it possible there is a redirect in between and we are losing the body of the request?

patrick91 commented 2 months ago

ok, I've take a look at the code for oauth lib and didn't find any place where it adds a slash :)

I think @frankdilo your code might be adding the slash when you're trying to get the token (so after the login). I've added some logs:

The user agent is python-requests/2.28.1 and I get this data:

{
    "grant_type": "authorization_code", 
    "client_id": "tk-abc",
    "client_secret": "abc",
    "code": "abc", 
    "redirect_uri": "https://api.typefully.com/mastodon/accounts/connect/end/"
}

In any case making the slash optional fixes it, so @TkTech maybe we can just do that?

patrick91 commented 2 months ago

ok, I've tested the url change, with my current server and it worked 😊