18

I am building an iOS application and I need to be able to make authenticated requests to a Rails 3 application for various bits of data. The Rails 3 application is using omniauth and URLs like https://myapp.com/auth/facebook to, for example, authenticate users via facebook ... and once authenticated, stores the authentication in a secured cookie named "auth.""

What I want to know is how to authenticate my users from the iOS/iPhone application, persist the authentication token and send it along with future requests to the Rails application?


Using ASIHTTPRequest I'm thinking of doing something like this:

  1. Open a UIWebview, loading with a URL from my web application specific for the provider they want to authenticate with (e.g. myapp.com/auth/facebook for facebook or myapp.com/auth/yahoo for yahoo, etc....).

  2. On success, somehow parse out and store the authentication cookie in the iOS application without displaying the webpage folks usually see when authenticating via the website ... and instead closing the UIWebView and navigating back to another UIVewController in the iOS application.

  3. Somehow include the persisted authentication token with future web requests to the Rails application.

  4. I also want to allow users to allow the iOS application to store this information locally so they don't have to re-login to the remote application if they choose too.


Is this approach appropriate? Is there a better way? And of course, how to actually implement the above?

Thanks - wg

wgpubs
  • 8,131
  • 15
  • 62
  • 109
  • Do you return the auth token in the web application? If not can you return the auth token in the web application through http? Because then I might have a solution for you because I am doing a simmular thing with authentication at the moment – Armand Oct 03 '11 at 08:39
  • I am not returning the auth token right now ... but I control the web application so yes, I can if needed. But, 1) Would I be creating a potential security issue by returning it? and 2) If I store the auth ticket as a cookie, why can't (or shouldn't) I just keep that around and send it along with every request? Anyhow, looking forward to your reply. Thanks – wgpubs Oct 03 '11 at 18:40
  • This is exactly my problem; really interested to know if you found a good solution! – cmaughan Nov 22 '11 at 10:54
  • I am wondering if you have a session id that you can store, and just sent it with your request (pretending you are a logged in browser user) – lulalala Jul 30 '13 at 06:24

4 Answers4

2

Using OAuth is pretty easy (well, easy is not the word...), but I made an iOS application and a java server that use OAUth as identity schema and, following the full cycle, finally I adquired a token that identifies this user and (as only can be accessed using signed requests) can be safely stored in the phone (I use just the standardUserDefaults to store it). Only your application (using the secret) can sign the requests.

I don't know if this serves to you...

Ah! After the identification via web, the browser redirect a special url (registered for my application) and the url opens my application including the token in its parameters, so it is easy to retrieve the token after the identification phase in handleOpenURL.

yoprogramo
  • 1,306
  • 9
  • 14
  • I'm interested in what you said in the last paragraph ... could you provide a more detail? – wgpubs Oct 14 '11 at 05:28
  • So does your iOS app open a UIWebView? What does the "special URL" look like? How does the "special URL" open the application, since it would seem that the application is already open to begin with? – wgpubs Oct 14 '11 at 05:30
  • Yes, I open a UIWebView for authentication. And the returning url is in the form: myapplication://oauth (I pass this url to oauth_callback parameter). I registered the protocol myapplication in the .plist of the application under URL Types/URL Schemes, so when the browser receives this kind of url opens the application – yoprogramo Oct 14 '11 at 06:18
2
  1. Once the UIWebview has authenticated with said service, get it to load another URL (for example: through a javascript on the page which said service returns to after authentication).

  2. Capture this request using a UIWebViewDelegate object which implements the following protocol method:

    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
    
  3. From here you have the NSURLRequest object. You can extract the headers of the request to NSDictionary which will contain the authentication cookie details, token, etc. using the following method of NSURLRequest

    - (NSDictionary *)allHTTPHeaderFields
    
Ross
  • 14,266
  • 12
  • 60
  • 91
1

For my app this is what I'm doing.

My app is using devise with omniauth for login and user stuff. Devise by itself can generate a unique token, with the flag token_authenticatable. So on my login request, if the login is successful I reply with a JSON representation of my user and my user token. I save all that on the phone memory.

Then on every request I add the param auth_token=MY_USER_TOKEN.

And that's about it.

I had just a problem with the Facebook auth, because I'm using the Ios facebook SDK, so I forward the FB token to my app, verify it, and then just return the same devise auth_token for all following requests.

rnaud
  • 2,610
  • 32
  • 38
  • Yes, I think I understand your workflow. 1) Use iOS Facebook SDK to authenticate with FB, 2) Pass token you get from that to Rails application to authenticate, right? I guess what I'm hoping for is a method that would allow me to simply use a UIWebView so that folks could authenticate the same way they do with the website, and then grab the token and do essentially what you've outlined. The main reason for this is the app allows about 5 ways to authenticate (FB, Twitter, Yahoo, Google, etc...) and I don't want to have to use some custom iOS SDK for each. Ideas? – wgpubs Oct 10 '11 at 18:31
  • 1
    I would suggest that you use a custom callback page for the UIWebview, containing the auth_token. In the end that's the only piece of information you will need. – rnaud Oct 11 '11 at 08:41
0

Ok here we go, I dont know the exact setup of your web service and all that, but what you can do is store the authentication token on the device using SQLite or Core Data, I am currently working on a app that requires authentication, and what I do is store the username and password locally on the device in the SQLite db using Core Data to interact with the db, then whenever I make an API calls I use the stored username and password for the authentication on the server side using gets, but I believe it is saver using post, as long as the web server has great security I don't believe there is any security risks. In what I understand about what you are building I would authenticate the user say on first launch and have the user be able to change log in credentials at a later stage, but after authentication I would send back an authentication token to the device and store that in the db and then whenever I need to authenticate with the web service I would send the auth token with a post request to the server. Does this make sense?

Armand
  • 9,847
  • 9
  • 42
  • 75
  • 1
    I think I follow but how is this actually implemented? Ideally, I want to use a UIWebView in the iOS application and present the same HTML screens folks see when logging in via the web application (works very much the same way as when you log into stackoverflow using your yahoo account for example). BUT for the iOS application, after authentication ... I want to know how to grab and properly store that token or authentication ticket (cookie) to send along in future requests and redirect the user back to another UIViewController once they have successfully authenticated. – wgpubs Oct 04 '11 at 17:22