openid / AppAuth-iOS

iOS and macOS SDK for communicating with OAuth 2.0 and OpenID Connect providers.
https://openid.github.io/AppAuth-iOS
Apache License 2.0
1.76k stars 770 forks source link

Support iOS 13 prefersEphemeralWebBrowserSession #402

Closed jgale closed 6 months ago

jgale commented 5 years ago

I'm sure this will naturally be added, but I just thought I'd file the formal request.

iOS 13 introduces the new prefersEphemeralWebBrowserSession property on ASWebAuthenticationSession.

Setting this property to true indicates you don't want to share any cookies or browsing data between this authentication session and the user's normal browser session in Safari. More importantly, to us, it skips the '"App" Wants to use "domain" to Sign In' prompt which many of our users have complained about.

WilliamDenniss commented 5 years ago

Your users are complaining that they would rather sign-in all over again, instead of hitting one button? I'm keen to learn more about this research if you're willing to share. As a user, that would not be my own preference.

jgale commented 5 years ago

Sure, happy to elaborate. We aren't using SSO for a social login or anything like that. It's used to log in to a secure, financial-based application which doesn't even allow users to remain logged in on the web. There is a hard security requirement that users log in every time. Given that limitation, everyone is annoyed by the extra button. Let me know if you have any other questions.

lapinek commented 5 years ago

Session cookies issued by some IdPs are not shared anyway. I, as well, would welcome a configuration option that allows to avoid the consent dialog (at the expense of sharing persistent cookies, if that's what it takes).

WilliamDenniss commented 5 years ago

Fair enough @jgale and @lapinek.

For the record, SSO isn't just for "social login", most enterprises use some form of SSO for corp identity as well. An added benefit of not starting from scratch every time is to be able to use trust signals from the existing session. None of this changes your use-cases, I just want to point it out as if everyone turns that on without thinking, they'll miss out on several important benefits (there's more to it than just the dialog).

wilmarvh commented 5 years ago

We're in the same boat as @jgale around a financial institution, having this as a quality of life improvement is a big win.

sbiggerstaff commented 5 years ago

Can confirm this would be a great quality of life change for an enterprise client of mine too.

WilliamDenniss commented 5 years ago

Got it. So today you have the OIDExternalUserAgent interface which is pretty easy to use, and allows you to customize the user agent however you like without forking. E.g. this exact "no-SSO" behavior has been possible with SFSafariViewController since iOS 11. To use ASWebAuthenticationSession for this in iOS 13, one could make a copy of OIDExternalUserAgentIOS like I did in that gist, with your custom modifications and use that (again, without forking AppAuth).

How I'd implement a user agent for this use-case would be to use SFSafariViewController on iOS 11 through 12, and ASWebAuthenticationSession with prefersEphemeralWebBrowserSession on iOS 13. The class would only support iOS 11+, no fallback (otherwise you'd get SSO). This would actually be better than simply exposing prefersEphemeralWebBrowserSession on the current user-agent IMO, as it would enable the desired no-SSO behavior for iOS 11 & 12 as well, not just iOS 13.

We could potentially add such a "no SSO" user agent to AppAuth proper. Maybe calling it "OIDExternalUserAgentIOSNoSSO"? I prefer the approach to have multiple user agent options, rather than having one that tries to do everything. This way we can keep the API contract cleaner (one UA attempts to get SSO in all versions of iOS, the other does the opposite).

lapinek commented 5 years ago

👍 to the second paragraph. Instead of necessitating developers to maintain a copy of OIDExternalUserAgentIOS (trying to show active development here), could the class included in the lib take an extra optional parameter—to indicate which (of available) external user agents to use? And then another one for prefersEphemeralWebBrowserSession—to allow for the new iOS13 option?

WilliamDenniss commented 5 years ago

could the class included in the lib take an extra optional parameter

No, we already have a pluggable way to represent different user agent behaviors, and that is with implementations of OIDExternalUserAgents. There's no need to have customizability within customizability. It's simpler if each class has a dedicated mission, like:

The library can have multiple support OIDExternalUserAgents though, in fact it already has 2 for iOS.

WilliamDenniss commented 5 years ago

Out of curiosity, what is the advantage of using ASWebAuthenticationSession over SFSafariViewController to implement this, when SFSafariViewController already has this behavior on iOS 11+?

As in, would the "NoSSO" user agent even need to bother with ASWebAuthenticationSession?

lapinek commented 5 years ago

I am not sure there is any advantage of using ASWebAuthenticationSession over SFSafariViewController, unless App Store review process exhibits some preferences. I was mainly concerned about maintaining a custom copy of the class, but your explanation about keeping the API clean does make sense. BTW, a designated user agent could serve another purpose: SSO with session cookies (by employing the user browser).

WilliamDenniss commented 5 years ago

BTW, a designated user agent could serve another purpose: SSO with session cookies (by employing the user browser).

Yes, I agree, I've seen this use-case in the past, in my case it was an eCommerce app that opened links locally in SFSafariViewController, so it made sense to have that cookiejar bootstraped with the sign-in initially.

I want to note that AppAuth supports pluggable user agents precisely so that every single imaginable use-case for user agents can be supported. We recognize that there is not a one-size-fits-all model, so people are quite free to implementation things however they need. They can do this with a dozen lines of code, and without needing to fork the library. The above mentioned eCommerce app is a fairly specialized use case, and a good candidate for having their own custom logic. E.g. they may only want SFSafariViewController even on iOS 13 if that's how they always open their store links.

Here's my example for SFSafariViewController, as you can see it's just a single class that you'd add to your project, and you can customize it however you like (e.g. want a red theme? go for it!). Using that implementation, you'll get SSO on iOS 10 and below, and ephemeral sessions on iOS 11+.

That said, if there's a common use-case then we can consider also including an implementation directly in AppAuth. A hypothetical OIDExternalUserAgentIOSEphemeral could be implemented and made available only for iOS 11 and beyond.

lapinek commented 5 years ago

Here's my example for SFSafariViewController, as you can see it's just a single class that you'd add to your project, and you can customize it however you like (e.g. want a red theme? go for it!). Using that implementation, you'll get SSO on iOS 10 and below, and ephemeral sessions on iOS 11+.

Yes, and thank you for providing that example (and @ugenlink for following up in Swift); I used it in one of the write-ups: https://developer.forgerock.com/docs/platform/how-tos/enabling-sso-appauth-sdk-ios

paulthorsteinson commented 5 years ago

@WilliamDenniss @lapinek Thank you! The OIDExternalUserAgentIOSSafariViewController user agent does exactly what I was hoping for. It avoids the 'do you want to use blah.com' dialog and also doesnt keep cookies.

mikeberlin commented 4 years ago

I'm using OIDExternalUserAgentyIOSSafariViewController and it still appears to cache my session across usage of the app. I force quit the app and it still remembers that I was logged in. Once I go into iOS Settings -> Safari -> Clear History and Website Data I am able to get back to the sign in screen. Is there something extra I need to do? I am using iOS 13 and also passing ["prompt" : "login"] as additionalParameters through the OIDAuthorizationRequest.

Tak783 commented 4 years ago

Did you ever solve this?

Tak783 commented 4 years ago

Got it. So today you have the OIDExternalUserAgent interface which is pretty easy to use, and allows you to customize the user agent however you like without forking. E.g. this exact "no-SSO" behavior has been possible with SFSafariViewController since iOS 11. To use ASWebAuthenticationSession for this in iOS 13, one could make a copy of OIDExternalUserAgentIOS like I did in that gist, with your custom modifications and use that (again, without forking AppAuth).

How I'd implement a user agent for this use-case would be to use SFSafariViewController on iOS 11 through 12, and ASWebAuthenticationSession with prefersEphemeralWebBrowserSession on iOS 13. The class would only support iOS 11+, no fallback (otherwise you'd get SSO). This would actually be better than simply exposing prefersEphemeralWebBrowserSession on the current user-agent IMO, as it would enable the desired no-SSO behavior for iOS 11 & 12 as well, not just iOS 13.

We could potentially add such a "no SSO" user agent to AppAuth proper. Maybe calling it "OIDExternalUserAgentIOSNoSSO"? I prefer the approach to have multiple user agent options, rather than having one that tries to do everything. This way we can keep the API contract cleaner (one UA attempts to get SSO in all versions of iOS, the other does the opposite).

Here is an example https://gist.github.com/Guy783/446b4921cf0894f031eacbd641122928

GevaZeichner commented 4 years ago

Here is an example https://gist.github.com/Guy783/446b4921cf0894f031eacbd641122928

@Guy783 Did it work for you in this example?

avika-narula commented 4 years ago

@mikeberlin were you able to use OIDExternalUserAgentIOSSafariViewController to log in without caching the session? I'm seeing that my sessions are being cached as well and wondering what I am doing wrong. I need to accomplish this on iOS 12.

mikeberlin commented 4 years ago

@avika-narula I ended up using this code (example SFSafariViewController class provided in link) while specifying ["prompt" : "login"] as additionalParameters. This seems to work well for our needs.

https://github.com/openid/AppAuth-iOS/issues/402#issuecomment-522135242

GevaZeichner commented 4 years ago

thanks @mikeberlin - so that guarantees ignoring the cookies? @WilliamDenniss - were you able to do that in another way in SFSafariViewController?

sher-khan commented 4 years ago

BTW, a designated user agent could serve another purpose: SSO with session cookies (by employing the user browser).

Yes, I agree, I've seen this use-case in the past, in my case it was an eCommerce app that opened links locally in SFSafariViewController, so it made sense to have that cookiejar bootstraped with the sign-in initially.

I want to note that AppAuth supports pluggable user agents precisely so that every single imaginable use-case for user agents can be supported. We recognize that there is not a one-size-fits-all model, so people are quite free to implementation things however they need. They can do this with a dozen lines of code, and without needing to fork the library. The above mentioned eCommerce app is a fairly specialized use case, and a good candidate for having their own custom logic. E.g. they may only want SFSafariViewController even on iOS 13 if that's how they always open their store links.

Here's my example for SFSafariViewController, as you can see it's just a single class that you'd add to your project, and you can customize it however you like (e.g. want a red theme? go for it!). Using that implementation, you'll get SSO on iOS 10 and below, and ephemeral sessions on iOS 11+.

That said, if there's a common use-case then we can consider also including an implementation directly in AppAuth. A hypothetical OIDExternalUserAgentIOSEphemeral could be implemented and made available only for iOS 11 and beyond.

That's a great solution, thanks. Could I extend this enhancement request to make the following changes

Tak783 commented 4 years ago

https://gist.github.com/Tak783/446b4921cf0894f031eacbd641122928

Yes, I wrote the example

janessbach commented 2 years ago

For anyone needing an ASWebAuthenticationSession for iOS 13 with toggle for 'prefersEphemeralWebBrowserSession'

-> https://gist.github.com/janessbach/850a151a3197eb6a8053876d8f068934

The above gist returns a 404

Tak783 commented 2 years ago

@janessbach I've updated the URL, my profile name changed :)

shatodj commented 9 months ago

I know it is 2024 already, but I didn't see it mentioned here anywhere. There is a parameter in OIDAuthState.authState:

self.currentAuthorizationFlow = OIDAuthState.authState(byPresenting: request, presenting: vc, prefersEphemeralSession: true) {
...
}

So there is no need to implement custom External Agent if you don't need one.

below commented 6 months ago

Is there no way to suppress the dialog by using a .well-known file, or similar, or a feature on Managed Devices?

We want to use SSO, and login is done only through apps we develop ourselves, and they run on managed devices. It sounds like with any of these technologies should make it safe to skip the dialog.

ywsang commented 6 months ago

@below Unfortunately the dialog system level prompt that we cannot control. It seems the only way to suppress is to use an ephemeral session by setting prefersEphemeralWebBrowserSession to true.

As pointed out in https://github.com/openid/AppAuth-iOS/issues/402#issuecomment-1905952423, the AppAuth API for iOS does now expose prefersEphemeralSession as a parameter, so I'm closing this issue.

mdmathias commented 6 months ago

Closing on behalf of @ywsang per https://github.com/openid/AppAuth-iOS/issues/402#issuecomment-2021684293.

ankushkushwaha commented 2 months ago

prefersEphemeralWebBrowserSession to true solved my problem for the popup. Moreover if we are authenticating within IOS app by opening in-app browser, we probably we do not want to keep session alive in browser. As once we get the access_token, we can use REST API to fetch data.