Open daenney opened 1 year ago
One thing I find very peculiar; the app seems to let me use both the "account domain" and the "instance domain". But instead of relying on redirects being in place, it seems the app could check .well-known/nodeinfo
and grabbing the URL from there and using that forwards. That would also avoid all the extra redirected requests.
$ curl -I https://dny.social/.well-known/nodeinfo
HTTP/2 301
location: https://ap.dny.social/.well-known/nodeinfo
$ curl -L -XGET https://dny.social/.well-known/nodeinfo | jq .
{
"links": [
{
"rel": "http://nodeinfo.diaspora.software/ns/schema/2.0",
"href": "https://ap.dny.social/nodeinfo/2.0"
}
]
}
I started working on an approach to get this to work right but I think while working on that I figured out the underlying reason for the failure. It seems like URLSession
(which we use for making network requests) drops the Authorization
header when a request is redirected between domains (here, dny.social
→ ap.dny.social
). Ultimately I think the workaround here would be to log into ap.dny.social
instead, in https://github.com/mastodon/mastodon-ios/issues/524#issuecomment-1322647936 I discussed the challenges of figuring out what the real Mastodon server domain should be. I’ll definitely think about this more to see if there can be a more satisfying solution though!
Right. I think it makes a ton of sense for the header to get dropped, though it's a bit odd that it's happy for other forms of auth to be carried over through redirects without re-prompting the user.
The flow seems to start with a call to https://dny.social/api/v1/apps
in my case. Perhaps if the redirect is detected there instead of followed, the user could be prompted to verify that domain and then start the flow from there instead? That should make the flow domain-change free which would solve the header getting lost on the last call.
I just discovered something interesting, the Android client doesn't have this issue. I took a look at what happens with pixie.town based on their admin's suggestion.
When using the iOS client the first call is this:
POST https://pixie.town/api/v1/apps
{
"client_name": "Mastodon for iOS",
"redirect_uris": "mastodon://joinmastodon.org/oauth",
"scopes": "read write follow push",
"website": "https://app.joinmastodon.org/ios"
}
This returns a 404 and Mastodon iOS gives up.
The Android client however, does this chain:
404 GET /api/v1/instance "MastodonAndroid/1.2.0" (account domain)
301 GET /.well-known/host-meta "okhttp/3.14.9" (account domain, to api domain)
200 GET /.well-known/host-meta "okhttp/3.14.9" (api domain)
200 GET /api/v1/instance "MastodonAndroid/1.2.0" (api domain)
By using the .well-known/host-meta
lookup it seems to resolve the account vs api domain and things then work correctly going forwards. If the iOS client implemented the same logic, then any instance implementation providing the .well-known/host-meta
endpoint would function.
If the iOS client would treat a 3xx or 4xx on /api/v1/instance
as a "discover through host-meta" hint instead then that should solve the domain to start the flow from.
Is there an existing issue for this?
Current Behavior
The iOS app is not able to login to certain instances when account-domain != web-domain. I've debugged this against my own instance at dny.social (which uses ap.dny.social) and took a peak at the traffic using mitmproxy.
This happens because at some point the Masto app gets confused about which domain it should call
/api/v1/accounts/verify_credentials
on. It calls it ondny.social
, which returns a 307 toap.dny.social
. The client then repeats the call but crucially omits the Authorization header causing the call to fail and it not being able to login.Expected Behavior
I can login when having successfully completed the auth flow and gotten a valid authorization token.
Steps To Reproduce
I'm including the request flow here so you can follow along, with a few things redacted.
We start with:
Next up:
Triggers the auth flow, hits
dny.social
again so we redirect:Now tries to trigger the sign-in:
Loads the signup page:
We go through the UI:
Completed the flow, getting returned to the app now:
We go to post on
/oauth/token
, starting at dny.social:So it tries again, on ap.dny.social:
Brilliant, it should have the token now. Oauth is quite the dance :dancers:.
Last step,
/api/v1/accounts/verify_credentials
, starting on dny.social again:Retries the request on ap.dny.social:
As you can see, in that last request the
authorization
header is missing, resulting in my instance returning a 401 with atoken not supplied
error.Environment
Anything else?
My instance runs GoToSocial, which tries to pretty faithfully emulate the Mastodon client.
If I tell the Mastodon app to login through
ap.dny.social
instead directly everything works fine. It works almost fine withdny.social
too except for losing theauthorization
header on that last redirect.