Create SSO using SFAuthenticationSession in iOS 11 - ios

I'm working on two iOS applications that share the same keychain tokens which they receive when the user logs-in in either of the apps by entering his username and password in a web view. The tokens saved saved in the keychain, are time limited for a few hours/days - they are being refreshed when the user uses the app and makes request/enters items which are being opened in a browser.
Up until the release of iOS 11, the web view in the app was a SFSafariViewController instance and it was very convenient because it shared the cookies between the apps and once a user logged-in in a browser in one app, he would automatically be logged-in in the other app, thus achieving an SSO experience.
In iOS 11, the behavior of SFSafariViewController changed, and it no longer shares the cookies between different SFSafariViewController instances in my two apps. Instead, Apple wants us to use SFAuthenticationSession to achieve the same behavior.
In my app, I have a table of about 50 rows, almost all of them open a different URL in SFSafariViewController. So now, in iOS 11, I need to create a new instance of SFAuthenticationSession every time (the URL cannot be changed once the instance was created), and in order to actually show the web view, I need to invoke the start() method on this instance. However, this method can only be invoked once on the same instance (otherwise it will return 'false' and do nothing), and every time it is being invoked, it pops the notification that "myapp" wants to use "mydomain.com" to sign in.
So it means that my users see this alert message on every tap on a row in the table.
Is there a way to make my app show the consent alert message only once, e.g. on the first time or something? I want my users to have an SSO experience in my two apps, that's why I used SFSafariViewController in the first place, but I don't want them to see this annoying alert on every tap they make in the app.

There is currently no way of having the alert message only show once using SFAuthenticationSession, we are experiencing the same issue on our apps.
I along with many others have filed a bug regarding this to Apple, asking them to show it only once like you suggested. The end of this GitHub thread discusses the alert.

Related

Basic Question: How to allow users in the same workspace to install my app?

I have a small app up and running for myself. It's an app homepage with buttons that shoot requests out to our hosted app, which returns modal payloads. It works perfectly for me.
When I began development I had to ask that the app be installed by our admin.
When other users in the same workspace attempt to install it they're greeted with "This is still a work in progress" instead of the app homepage.
I don't wish to distribute the app beyond my current workspace so I don't think I need to implement the o-auth flow. Any hints? I'm sure I'm missing something small.
The issue was that I was using a Home surface. To use app home surface you have to display it for each individual user, not a single time for the app, as I suspected.
When the user clicks on the app home page, it triggers an event that sends a payload to the URL you specify in the app's event subscription settings. You have to respond to slack api's /views.publish endpoint with a payload that defines the home appearance for that particular user. The user id is in the initial request payload.

How do I ensure that only one instance of an iOS app is running?

I have an iOS app that permits people to "claim points." I want to prevent a scenario where someone opens the app on their phone, another instance on an iPad and then submits claims in both places.
Presently the app "registers" as the active instance when it starts up. If a second instance starts, it will take control and any attempt by the first instance to save data will result in a redirect that tells the user not to have two apps open. I have seen some games (e.g. Clash) that immediately inform the user of the first app that they are being kicked the moment that the second app opens.
I can think of two ways to do this: submit a "heartbeat" every few seconds to see if we are still the controlling app (wasteful) and some form of notification to all other apps when a new instance opens. Can standard iOS notifications play this role or are they just for popping up notifications to the user?
Any insight into how to post a notice to all other instances of an app when one instance opens up that doesn't require polling would be appreciated!
You can manage this problem on the server side.
Apparently users have to login or at least, your app auto-login with a unique ID with a server.
If you have an API to receive a claim, you can simply check if an identical claim already exists for this Unique ID and return an error to the second device when that is the case.

Facebook iOS SDK - open session and request read permissions

I'm using
(void)openWithBehavior:(FBSessionLoginBehavior)behavior completionHandler:(FBSessionStateHandler)handler
to open my session, which works fine. After open, I then get my read permissions with:
(void)requestNewReadPermissions:(NSArray*)readPermissions completionHandler:(FBSessionRequestPermissionResultHandler)handler
This works fine, but for users signing in through Mobile Safari (or likely the Facebook iOS app, haven't tested), users get jumped back and forth twice (tap login in my app, jump to Mobile Safari, log in there, jump back to my app, jump back to Mobile Safari, approve permissions, jump back to my app.
Returning users - those who have signed out of my app (and token removed), also get a double-jump - each time Mobile Safari tells the user they've already approved the app.
I'm using openWithBehavior because I prioritize the native iOS login using FBSessionLoginBehaviorUseSystemAccountIfPresent. I don't see a version of this combined with an initial permissions request (such as openActiveSessionWithReadPermissions...).
I was hoping that, for subsequent logins, permissions would already be known via session.permissions but in testing that value is null until requestNewReadPermissions is called.
Is it possible to remove the double-jump from either or both scenarios (first user login, subsequent user login) yet still achieve the same permissions?
You can "init" your session with read permissions by calling the initWithPermissions: method. Then call openWithBehavior:completionHandler: which will do only 1 open call with the permissions you've already set.

Control flow for a webservice-backed iOS App

I'm learning the basics of iOS development, and I'd like to make a simple application that connects to a web service. I've got a lot of experience on the web application side, so I'm comfortable with what kinds of requests the app needs to send/receive etc. The part I'm not sure about is what the big picture architecture of a service-backed mobile application looks like.
When my application runs, I have one major requirement: the user must authenticate into the web service. The web service can send back a token and the app can use this for all subsequent requests. I want the user to be able to log in once, and for the app to stay logged in (ie the token remains valid for that device) indefinitely unless they log out.
Until the user logs in the application should really just be a login screen. If they log out, the same. Otherwise, they don't need to see the login screen at all.
So my question is, what is the right way to structure this?
In AppDelegate, do I want to make a LoginViewController and set it to the rootViewController? Then if the user is logged in, push to the main view for the rest of the app?
Or do I want to initialize the main part of the app (for instance, a UITabBarController with a few views in it), and check for a token, and then display a modal login screen if no token is available?
What I'm not clear on is what the rootViewController should be for an application like this, and how the app should keep track of whether the user is logged in, and determine what screen to show when the app is opened.
If anyone can give me a high level overview of how such an app should be structured, I'd really appreciate it.
Thanks!
There isn't really a right way to do this, either flow could be appropriate for an application. If I had some UI or data that would be displayed if a user is not logged in then I would use that as the initial rootViewController and use a modal login dialog to force the user to login. On the other hand, if I had nothing to display until a user has logged in then I would setup the login view controller to be the initial rootViewController if the user is not currently logged in.
For keeping track of the user being logged in you should leverage NSUserDefaults to persist the authentication token. Then in the application:didFinishLaunchingWithOptions: call to your app delegate look for this token in NSUserDefaults (and possibly validate it with the server) then set the rootViewController as appropriate.

iOS Facebook switches back to app between login & permissions

I'm trying to setup my app to publish a simple post to a user's Facebook feed (image url, link, description). They don't need to use Facebook for anything else so the first time they click "Share" it needs to authorize the app, and the publish permissions.
If they have their credentials stored in the device as of iOS 6 they simply get two alert boxes and it's done with. But if they don't, or have an older version, it switches out to Safari for login. My problem is that it is then switching the user back to my app, then immediately back again to Safari to accept the publish permission. It's very jarring and unprofessional.
What I would like is for the page in Safari to change after the login to the permissions page so they can accept it, and THEN switch back to my app. I know this can be done because the popular Mixology app does exactly this behavior. Unfortunately Facebook keeps changing their SDK and all the information I find online is outdated.
I wrote up a solution here: FacebookSDK presents login UI twice to avoid the double switch.
Basically, you can use openActiveSessionWithPublishPermissions: to do what you want. However, you have to handle the special case where the user has signed in to Facebook from the device settings, which requires requests for read and publish permissions into two separate calls.

Resources