Mobile app: Persistent login (with two authentication method) - ios

I am designing a mobile app which has the following features:
The first time a user opens the app it is ask to authenticate himself to the app web service by signing in/up using a classical username/password schema or to use Facebook login.
Then, the next time it opens the app, the user won't have to enter its credential again and is automatically sign in.
The first authentication method is implemented. The web service sends back an authentication token that the user use to authenticate himself. The latter is stored together with the user ID in a non-volatile (protected) storage of the mobile.
I know lots of apps provide the two authentication method we are talking about. I was wondering how it is usually combine with the Facebook authentication. At the moment, I was thinking of generating credentials after Facebook login and authenticating Facebook users to my web service as if they were classical users. The users would be stored in the same web-service database table. Note that a flag in the database would tell us whether the user used Facebook or not for login, for if a user logs with the same Facebook account (identified by e-mail) on another device there won't be duplicate.
EDIT: Moreover, some apps let Facebook user to play with their Facebook friends for instance, but how is it done in a persistent manner since one can only have a temporary access token to query Facebook API ? More generally, how some apps do to keep the FB session persistent?
Do you think it is viable?

Facebook Access Tokens are of two types: short term and long term ones. You probably have played with the short term ones, but Facebook documentations say [1] that normally mobile apps use the long term one.
Native mobile applications using Facebook's SDKs will get long-lived access tokens, good for about 60 days. These tokens will be refreshed once per day when the person using your app makes a request to Facebook's servers. If no requests are made, the token will expire after about 60 days and the person will have to go through the login flow again to get a new token.
iOS Facebook SDK [2] has a sample about maintaining session, sample is coming in the installation package of the bundle. (Same code also at GitHub[3].) Here is the most essential part from the GitHub one:
SLAppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
if (!appDelegate.session.isOpen) {
// Open new session
}
Once the session is restored / found active with isOpen, there is no line of code in the example to refresh it. I am not an iOS programmer but for me that quoted paragraph from documentation and that code snippet from tutorial show I think clearly, that no other action to refresh is even needed, only successful use within about 60 days.
In short, you cannot have a permanent token lasting forever, but luckily enough you have almost one, if you just keep your users using the app in enough frequent manner.
[1] https://developers.facebook.com/docs/facebook-login/access-tokens
[2] https://developers.facebook.com/docs/ios/sample-apps#sdk
[3] https://github.com/Citrrus/facebook-ios-sdk/tree/master/samples/SessionLoginSample

Related

Dropbox OAuth2 API always prompts user for permission when a refresh token is requested

I'm writing an offline application that uses the Dropbox API. When a user comes to the application, I'm using the https://api.dropbox.com/oauth2/token (docs) to get a refresh_token, which I store for later use.
I am calling the same endpoint every time the user logs in (unless I've already got the user's data in a cookie). I'm not sure that this is the best way to go about it: I at least need to get the user's account_id, so that I can look up their refresh_token in the database if I already have it. But every time I call https://api.dropbox.com/oauth2/token, the user is redirected to the Dropbox app authorization interface, as if they've never approved the app before.
So I would either like to know how to stop Dropbox from forcing the user to re-authorize an app every time. Or, if that is just how https://api.dropbox.com/oauth2/token is supposed to work, I'd instead like to be able to get their account_id somehow when they visit my page.
(In case it's relevant, the app is still in development mode at this point.)
The https://api.dropbox.com/oauth2/token endpoint is an OAuth endpoint that the app can call to get an access token/refresh token. Being an API endpoint, it does not itself redirect the user to the Dropbox app authorization page.
The Dropbox app authorization page is at https://www.dropbox.com/oauth2/authorize (documented here), and the app decides if/when to direct the user there to authorize the app.
You generally only need to send the user through the app authorization flow (sending them to https://www.dropbox.com/oauth2/authorize and then calling https://api.dropbox.com/oauth2/token) once per user for an "offline" application. Once you do so, you should store the resulting refresh token for that user. You'll typically store the refresh token for that user tied to their user account in your own app.
Exactly how you manage the user accounts in your own app will depend on how it's built, but, as it sounds like this is a web app, typically you would use the user's browser cookies to identify the user when they return to your page so that you can look them up in your database and retrieve their details, such as their corresponding refresh token. (Or, if they're not already signed in to your web app, you would have them do so first.)
Greg's answer is very helpful, and very politely addresses my misunderstanding of the auth flow. (I was revisiting old code I'd written years previously—obviously I should have documented it better than I had!)
In the end I believe that Dropbox was forcing me to reauthorize because my application was in development mode, and had a small user base. When I used the identical code in an app set to production mode, it stopped forcing me to reauthorize. So the “problem” is really a Dropbox security feature, and the solution was just to use production mode.

Social login keeps the provider app logged in

I visit an app that uses oauth social login
I choose say gmail; I get sent to gmail site
I log in to gmail and then get sent back to the app
When done with the app I log out
After step 4, even if I close the browser and open anew, visiting gmail opens my account straight away without prompting for a password. Keep in mind, I never let browsers save my password neither do I ever tick “remember me”
I’m not sure the average user will remember to visit gmail separately to log out; this would be disastrous on a public computer.
My question:
Is this a design flaw of oauth2 or is it an implementation flaw with the app in step 1 or is it an implementation flaw with google-login? Or is it technically impossible for the app in step 1 to log out of the social identity provider (in which case it’s not a flaw at all.)
The OpenID Connect core spec and the session management spec defines ways to both:
Sign the user out of an identity provider (link)
And force user re-authentication with the OP after a maximum
authentication age (max_age) has elapsed since last user
authentication. (link)
Trouble is I'm not sure if Google implement these things see this
I've tagged your question with OpenID Connect as authentication is not an OAuth2.0 concern.

How do I get the ID of the currently authenticated Twitter user in a web application without using OAuth?

*Apologies in advance for the long background but I think it is necessary and helpful to other devs once this is answered.
Background
I am building a very social web-application in which there are several events that trigger social actions such as updating the user's Twitter status.
Currently, I use a library called "TweetMoaSharp" (.NET) to handle the Oauth workflows and events that trigger a status update or follow action work brilliantly as long as the user is briefly redirected to the Twitter authentication page.
To clarify, the user is not asked to re-authorize my app each time, but there is an unsightly flicker that lasts for 1-2 seconds while the user is directed to Twitter and then back to my app. This will annoy the end user as there are frequent Twitter interactions.
So--to relieve the situation, I use TweetMoaSharp to obtain an OAuth Access Token via the server and then store that token along with the user id returned from Twitter in my database. I then set a cookie on the client that contains the user's Twitter Id so that for future requests I can simply pass that ID to the server, grab the OAuth token form the database and do my business. No redirect required!
Problem Solved, Right?
Well, no. Stupidly, I overlooked the fact that this can cause a collision with multiple Twitter Accounts being used on the same page and ended up tweeting test-tweets to a second twitter account I own because I had changed Twitter sessions. This could happen to any user(s) who access multiple Twitter accounts from the same browser; a husband and wife for example.
Back to the Drawing Board
I thought to myself, "The Facebook JavaScript API" makes it super easy to get the id of the currently logged in user without going through a bunch of server-side token steps so I am sure Twitter offers the same approach." Ha! I haven't found one yet.
Bottom Line / Question
How do I get the ID of the currently authenticated Twitter user without redirecting them to Twitter (even for just a second)? If I can do this, then I can compare the returned ID to the one in my cookie and know if it is valid for my application's current session or if I need to have that (new) user authenticate as well so that I avoid "Tweeting" under the wrong account.
Thanks in advance.
Use your app tokens to do a verify credentials call
https://api.twitter.com/1.1/account/verify_credentials.json
The returned info is the logged in user.
Unfortunately limited to 15 calls per 15 minute window!

Soundcloud as Oauth Provider: How to make it connect only one time

I'm currently implementing an Oauth consumer service which is going to use Soundcloud as an Oauth service provider as well. But I'm having the following issue with it: Taking Facebook or Twitter example, you go there, you sign in, you fill up the permission form, and you are redirected back to your app. If you go there a second time, and given you are already sign in, you basically skip all steps and are redirected back instantly. That means, Facebook recognized that you already gave permission to that 3rd party service, so it doesn't ask your permission constantly.
And that's what's happening when I use Soundcloud. Basically everytime I redirected the user to the Soundcloud Oauth connect endpoint, the permission form always shows up, even though I already gave permission to that 3rd party service previously. I'm forced to press "connect" every single time, which is a drag from the user perspective (how many times can you give permission to the same entity). My question is: is there a parameter I can use to make soundcloud recognize/validate the previous permission from the user account to that specific 3rd party service? Or is this Soundcloud Oauth design implementation and we have to live with it?
Edit:
Maybe this wasn't clear, but each time I press "connect" in soundcloud, a new access token is being generated and delivered. Since my app uses this access token to identify its users, it doesn't work very well for me that the access token is getting updated everytime I want to log in, making me effectively "sign up" everytime. To sum it up, I want to get the previously attributed token to my account, so I can look up in my database, identify it and log him in.
I'm also looking for a solution which doesn't involve storing state in the client that might get cleaned up.
What you can do is store the user's oauth token in local storage and reuse it in future sessions. That's what happens on soundcloud.com.
A longer explanation:
When you use the Connect flow, the user is authenticated by SoundCloud (either by using username/password, Facebook Connect, or an already-existing session on soundcloud.com), and then when it is successful, your app is given an oauth token for that user. This is passed to the callback page which is registered for your app.
That token is the only piece of information needed to have the user be "logged in". Unless the token expires (by time, or by the user manually revoking it), then you can reuse that in future sessions.
I think I'm a bit confused about your application's design: where and how is the oauth token being used? I think that instead of using the token as an identifier, perhaps the user's permalink might be better? If you have the oauth token, you can find out the permalink by querying api.soundcloud.com/me.

asp.net mvc application need access to users google drive account from "service"

Im writing a web-app that gives our customers the possibility to SYNC their files on their personal Google Drive onto OUR bushiness application. (only limited file types).
So - what works so far:
Users signup to the app, (using OAuth2 and saves a refreshtoken in my end) the user/and my app, have now access to files on their Drive, and can manually invoke file transfers.
Working fine.
Users can afterwards login again and repeat this without having to authenticate the app again. Fine.
In parallel, I need some kind "service" that loops thru our app's user-base and AUTOMATICALLY syncs files in a designated folder - say every 10 mins.
Now im running into problems because of OAuth2 model, needs to redirect to authenticate every user. But I cannot make multiple redirects out of a single request to, say "/SyncAllUsers".
Also, when testing with one user only, the user still have to be logged in into the browser session, or else google will redirect to the service-login page.
(We use a chron-job to invoke these methods at a specified interval - and it is working well with dropbox-accounts, and these users also use OAuth)
So basically 2 questions:
How can I access my users Drive accounts, with my already authorized app, without having users to "be logged in"
And how should I handle the sync-service to run without having to redirect at every user.
I have spent days searching for answers on https://developers.google.com/drive/ and in here.
I have impl. the OAuth code from here https://developers.google.com/drive/credentials#retrieve_oauth_20_credentials
and I modified it so it is using my own user-database.
For your infomation im using the Client ID for web applications, in Google APIs Console
Once you have the refresh token, you can use it to perform synchronization without user intervention. This is the nature of offline access and the whole purpose of a refresh token.
(Sorry if this doesn't answer your question, I am not exactly sure what you are asking, so please explain more and I will try to give you a different/better answer.)

Resources