Swift login alert shows up when you logout

@matt.macadam Thank you for the detailed explanation! Would you mind clarifying a few things?

Firstly:

  • I DO need to support SSO on iOS with Refresh Tokens.
  • I DO need to silently log out a user without requiring user confirmation of Apple’s dialog about shared cookies. (Basically, security – if Refresh Token is revoked, I cannot allow the user to acquire a new Refresh Token without requiring user to re-enter username/password.)

To solve this, you provided two options:

  1. Short Auth0 sessions – How do I configure that?
  2. Passing a calculated “max_age” to /authorize – How do I do that? I know how to edit the source code, but I don’t understand if you mean the Cache-Control: max-age=<seconds> header or some non-standard header, or a custom property in the post-body, or something else.

Lastly, do I need to implement BOTH options for this to work, or just one?

Thank you!!!

1 Like

@Ethan-VisualVocal you can adjust your SSO session lifetime in your tenant settings, under the Advanced tab.

You said “I DO need to support SSO on iOS with Refresh Tokens.” Can you elaborate on what you expect a user interaction to look like for this?

As far as the two options I mentioned, you would implement one or the other…I think technically you could do both but there’s no benefit. If you didn’t want to set your global session timeouts to be short then you would use the second option.

max_age is an OIDC parameter that:

Specifies the allowable elapsed time in seconds since the last time the End-User was actively authenticated by the OP. If the elapsed time is greater than this value, the OP MUST attempt to actively re-authenticate the End-User. (The max_age request parameter corresponds to the OpenID 2.0 PAPE [OpenID.PAPE] max_auth_age request parameter.) When max_age is used, the ID Token returned MUST include an auth_time Claim Value. (https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.3.1.2.1)

So it’s added as a parameter on the call to /authorize. I think to send it in Auth0.swift you would add it like this on the login method:

Auth0
.authentication()
.login(
    usernameOrEmail: "support@auth0.com",
    password: "secret-password",
    realm: "Username-Password-Authentication",
    scope: "openid",
    parameters: [max_age: "4900"])

With the caveat that I’m not an iOS developer and that might make your phone catch on fire. The idea here is:

  1. You record the time the user logged out of the app (or rather, the time they clicked “log out” and you revoked the refresh token)
  2. User tries to sign in again–you do some date math and determine it has been 5000 seconds since the token was revoked.
  3. You send a request to /authorize with max_age=4900
  4. Authorization server receives the request and sees that the user last logged in well over 4900 seconds ago (remember you revoked the token 5000 seconds ago so they logged in sometime before that)
  5. Authorization server requires the user to enter username/password again.

It’s important to note you’re doing this for user experience, not security. There’s nothing to stop the user or a proxy from tampering with the max_age parameter and reusing the SSO session. That is probably fine for this use case, but if you wanted to confirm the parameter was sent properly you would check the auth_time claim returned in the id_token and make sure it contains a sensible value.

Update: I should note this only applies to auth0 database connections. If you are redirecting to an upstream IdP (like Facebook), auth0 can guarantee that some sort of exchange with the upstream IdP took place, but we can’t guarantee the exchange involved a username and password (for example, the user may have had an existing session). So for an upstream IdP you can’t trust the auth_time claim to prove that the user provided a username and password.

3 Likes

Thanks a lot for sharing this knowledge Matt!

We are facing the issue, when we logout from Auth0.
its showing Login alert ( and asking :- “wants to sign in…” ), not showing logout thing.

Can you provide some guidance to overcome this issue.

1 Like

Outside of a Native login flow, is there any way to avoid the “…wants to sign in” iOS prompt for logout? I am receiving this issue in React Native, running on iOS.

3 Likes

Same question as @dylan4, I’m getting a prompt for both authorize and logout. Running on React Native. Saw another thread related to this App would like to use Auth0 to Sign In prompt displays on Logout (React Native) but it seems dead.

1 Like

I have the same problem. When I call authorize or clearSession I get a pop-up stating "App" Wants to Use "auth0.com" to Sign In - This allows the app and website to share information about you..

The ugly thing is that when the user presses "Logout" in the App, the pop-up talks about "Sign In".

1 Like

I feel this thread is dead as well. I ended up deciding to implement my own login because the UX problem caused by this issue is unacceptable.

This really should be a high priority for you guys. It is completely broken to show users a “wants to sign in” when they are trying to logout. That is completely not what they are trying to do yet they see a message to the contrary.

I’ve never seen this with Google or other logins, when I have used their SSO directly.

Also, for our users, the first login will give them an error telling them to go check their email for a change password link. However, the Auth0 code, even though it gave an error and there is no refreshToken or credential, will assume that the user is logged in, and on subsequent attempts to login, it will continue to assume that the same user is logging in and won’t give the user a chance to enter a userid and password. The authentication tries the same old password. At that point, a user is locked out. Even deleting the app won’t fix the issue. I had to go in and add code to logoutUserWithCallback to the failed login attempt. Now the user sees a second “auth0.com wants to sign-in message”, for a failing transaction.

Logout and error handling of a login, is a fundamental part of an authentication mechanism. I can’t believe that this is not at the top of your lists for something to fix.

5 Likes

I agree with @mahboud; I’m really hoping this is one of your highest priorities at the moment. This makes for a terrible user experience. Being an authentication service you should have this covered; I don’t feel like we should have to jump through hoops and use roundabout code in order to get basic login/logout functionality to work as it should. ESPECIALLY when you clearly state that doing so would mean giving up on some other important functionality, like SSO. I would really appreciate an update on this issue; it looks like the last time an Auth0 employee commented here was January. It’s August.

Hi. Checking to see if there are any updates?

Hi folks,

I was asked to provide an update here. The situation is mostly unchanged, but it is a little easier to work around this now if you’re using our Swift SDK.

First, a reminder that the “(app) wants to use (website) to sign in” construct is enforced by iOS when you redirect to a “regular” Safari browser for a user to log in to your app. That redirect is usually executed by calling ASWebAuthenticationSession (this is what our SDK does for ios 13+) and the default behavior for that method is to open a “regular” Safari browser.

When I say a “regular” Safari browser I mean the same instance you would find yourself in if you opened it from the home screen–with all your cookies and session data. Apple enforces this requirement as kind of a warning that some personal information will be available to the site if you continue (I covered this in more detail in previous posts). The advantage of this is if the user has existing SSO sessions for Google/Facebook, etc. they don’t have to enter a username and password again.

I agree it doesn’t make a lot of sense that iOS raises the same prompt for logging in and logging out–in my opinion there should be another parameter you can pass to ASWebAuthenticationSession (maybe isLoggingOut: true ) to get it to display a message with the appropriate context. Hopefully one of these days.

There are two ways to avoid the bad logout UX:

  • Don’t use the browser to log out (solution detailed in previous posts)
  • Call ASWebAuthenticationSession with prefersEphemeralWebBrowserSession:True

I have mentioned the second option before, but it used to require forking our SDK to implement. As of May 2020 we have an option in the SDK to use ephemeral sessions and avoid the iOS popup:

https://github.com/auth0/Auth0.swift#disable-single-sign-on-ios-13–macos

That is probably the easiest way to handle the problem today. It disables the popup for logging in and logging out. Note also that if you use an ephemeral session to log in there is no need to redirect to the web browser for logout–since you used an ephemeral session there is no web browser session to terminate.

Final note: It looks like our Xamarin SDK will also be getting ephemeral sessions soon:

https://github.com/auth0/auth0-oidc-client-net/pull/173

Thanks,

2 Likes

Thanks for the update on this front Matt!

Based on our recent testing it seems that unfortunately this is not the case. The user (or anyone with their device) can log in again via the iOS app at least for some time without a sign-in prompt when using ephemeral sessions. It would be helpful to just update the clearSession to support this.

@mivi.ftrc: Thanks for sharing! That may be a bug report for Apple as that contradicts their statement on ephemeral sessions:

This setting asks the browser to avoid using any existing browsing data, like cookies, during the authentication process. It also asks that the browser avoid retaining any data collected during the authentication attempt beyond the lifetime of the attempt, or sharing it with any other session.

(emphasis added, https://developer.apple.com/documentation/authenticationservices/authenticating_a_user_through_a_web_service?language=objc, heading: “Optionally Request Ephemeral Browsing”)

It would be helpful to just update the clearSession to support this.

Can you elaborate on this request? Are you asking for a documentation update, or to have clearSession run with prefersEphemeralSession?

It seems that the cookies may be present if the ephemeral session still happens to be alive, but not guaranteed.

The documentation page you linked on prefersEphemeralWebBrowserSession kind of hints at that also

Set prefersEphemeralWebBrowserSession to true to request that the browser doesn’t share cookies or other browsing data between the authentication session and the user’s normal browser session.

I can’t personally find any hard documentation on the lifetime limits of an ephemeral browser session.

Yes, to me it feels like the most straightforward solution would be to just add the ephemeral session option to clearSession also. Most straightforward in DX and user expectations.

Since the default login method doesn’t use ephemeral sessions, we need to keep the default for clearSession for consistency–otherwise if someone logs in via “real” Safari and tries to log out with an ephemeral session, their Safari session will persist.

I chatted with the SDK engineers about brief persistence of ephemeral sessions–they weren’t aware of it happening. I have a test app that performs logins with both, and I’m not able to reproduce any persistence of ephemeral sessions in iOS 14.2. The “real” Safari instance is definitely separate from the ephemeral instance, and if I log in with an ephemeral session and try to do it again within a couple seconds, I am prompted for credentials again. If you can share a video or specific steps and configurations to reproduce, this an interesting issue that I’d like to follow up on.

iOS versions below 13.0 behave differently. Ephemeral sessions aren’t an option there, but if you request an ephemeral session in the SDK, you just get a regular Safari session and still see the “wants to sign in with…” prompt.

2 Likes