Open elicwhite opened 4 years ago
This issue is interesting and definitely related: https://github.com/trakt/api-help/issues/19#issuecomment-457733626
The recommendation is to authenticate against the trakt.tv endpoint and not api.trakt.tv. This is a good gotcha, every JS library for Trakt I've seen authenticates against api.trakt.tv.
Regardless, from that issue it seems like I would still need to manually hit /logout
. Unfortunately I don't think I can open a browser with the same cookie jar to be able to call /logout
since the iOS authentication framework is separate.
I think I'm out of ideas
Can you post the example code for how you are revoking the token via that API method? https://trakt.docs.apiary.io/#reference/authentication-oauth/revoke-token/revoke-an-access_token
I think its ok for the user to be logged into the Trakt website. Revoking the token should give them a prompt to allow access again for your app though. So, that's why I wondering if the revoke call has a bug in your implementation or if its something else going on.
Thanks for the response!
I'm revoking the token with this code:
const req = {
method: 'POST',
url: 'https://trakt.tv/oauth/revoke',
headers: {
'User-Agent': this._settings.useragent,
'Content-Type': 'application/json',
Authorization: `Bearer ${this._authentication.access_token}`,
'trakt-api-version': '2',
'trakt-api-key': this._settings.client_id,
},
body: JSON.stringify({
token: this._authentication.access_token,
client_id: this._settings.client_id,
}),
};
return fetch(req.url, req);
I ran this against the apiary debug url endpoint and it seemed like it was happy with my request shape.
I've also tried hitting the api endpoint, as well as trying to include my client_secret
in the body.
Please try using api.trakt.tv
for the hostname and sending client_secret
as well, basically match the docs exactly. The trakt.tv
hostname should only be used to generate the authorize URL, but not for the other API methods.
My new request is this:
const req = {
method: 'POST',
url: `https://api.trakt.tv/oauth/revoke`,
headers: {
'User-Agent': this._settings.useragent,
'Content-Type': 'application/json',
Authorization: `Bearer ${this._authentication.access_token}`,
'trakt-api-version': '2',
'trakt-api-key': this._settings.client_id,
},
body: JSON.stringify({
token: this._authentication.access_token,
client_id: this._settings.client_id,
client_secret: this._settings.client_secret,
}),
};
I still get a json response from the server of {}
, and the result is the same. The next authentication is still resolved immediately and transparently without the user being prompted for anything. 😢
I looked into the prompt
option more and the OAuth library version we're using doesn't currently support it, but it looks like a newer version does. This is one our roadmap to upgrade, but I don't have an ETA yet.
The server will always respond with a 200 success when revoking, so it is not a reliable way to know for sure a token was actually removed. I believe this is done for security reasons and so you can't use that endpoint to actually verify if a token is valid or not.
Your code looks correct, so my guess is the token is revoked ok, but there might be additional valid tokens that exist for the app connection. This could happen if a user connects the same app on multiple devices for example. I wonder if that is what's going on here.
Thanks for the update! I actually have an update from my end too!
I realized yesterday that the authentication popup is using the same cache as the regular Safari WebView. So if I open my app and sign in with trakt, then open Safari on the phone, I'm signed in on trakt too. If I sign out of the app, then sign back in it does the immediate sign in thing I reported in the OP.
However, if I'm signed in on the app, and then sign out through the app (revoking the token), then open Safari and log out from trakt's website, then the next time I sign in on the app it asks for the credentials.
So maybe if iOS will let me pop an offscreen webview to trakt.tv/logout, I can make that experience work.
It would still be great to get prompt
support, but it is at least helpful to have a better understanding of the iOS system! 😀
Good info, thank you! Yes, we plan to add in prompt
support once we're able to upgrade the OAuth library. We'll make sure to announce that and update the API docs accordingly.
I haven't forgotten about this, we just haven't updated our OAuth library yet which is required to support this. I'm hoping in the next month or so we'll be able to add support for this.
Wow, I appreciate the follow up. FWIW, it would have been totally reasonable for you to have forgotten about this and never thought about it again. I'm one of the maintainers of a pretty big project and there is nothing I can do to avoid that from happening. I appreciate the care and attention.
I took a deeper look at this and it appears prompt
is part of OpenID which we don't currently use. I thought our code OAuth library had support, but it looks like only if we add in OpenID support. So basically, is this part of the core OAuth spec?
That's possible, I'm sure you are significantly more informed than I am. I haven't done that much with OAuth or OpenID before. A cursory Google only seems to mention it connected to OpenID, so seems like yes.
👋 Any update on this? This happens also on Android. Same reason as in iOS - the CustomTabs share cache with Chrome.
Using AppAuth-iOS, if you make the Safari session ephemeral (like incognito), then it won't remember the user's details each time.
Something like: OIDAuthState.authState(byPresenting: request, presenting: viewController, prefersEphemeralSession: true)
Perhaps you could do something similar on Android too? https://github.com/openid/AppAuth-Android
Sorry for the extreme delay on this, but I ended up just coding this functionality myself. The update will be released tomorrow and the API docs are updated at https://trakt.docs.apiary.io/#reference/authentication-oauth/authorize-application.
You can send ?prompt=login
in the authorize URL to force the user to sign in (it destroys the session of any currently signed in user).
I have OAuth working in my app, but I can't seem to figure out how to make logging out work. When they press log out I revoke the token through the API and then clear my app state. When the user chooses to log back in, the oauth authentication screen pops up but still instantly closes.
This issue is the same as in this issue: https://github.com/openid/AppAuth-iOS/issues/281
They recommend adding
prompt=login
to the request as that seems to be part of the OAuth spec for the server to force the user to enter credentials again. However, either I haven't implemented that correctly, or the Trakt API doesn't support it. 😀 Here is another article about that: https://www.oauth.com/oauth2-servers/authorization/requiring-user-login/