views:

143

answers:

3

I'm building a Webapp that uses OpenId to authenticate users, like Stackoverlfow does. There will be a mobile App too, e.g. Android or iPhone. These Apps have to authenticate or login somehow, to access data and update stuff that belongs to the user. Since there is no username and password one could provide to authenticate the mobile device, I wonder how to achieve this.

Two ways came into my mind:

  1. Generate some key on the server that must be entered on the device. This key will be send as auth-key when the mobile device sends or requests data and the user can be linked that way. When using this Option, the key should be transported somehow to the user, so he doesn't have to type it in. Maybe via email, SMS or by scanning a barcode.

  2. The mobile App uses the Browser or shows an integrated Web-Panel that opens a special page of the Webapp. On this page, the user has to login in, and could then allow the mobile App to read and write data.

My question is: Are both ways possible and save? Which one would you prefer? What are the details to watch out for? Are there any other ways to do this? If I got it all right, it would not be possible to use OpenId on the Device, and link the mobile and the webapp that way, right?

A: 

The current OAuth specification (RFC5849) still requires that the user enter their credentials to the website that holds the protected resource. On a mobile app this user experience is not the best (as you pointed out requires the mobile app to display the auth page with a integrated web view). OAuth 2.0 addresses this issue by specifying different Access Grant types. This standard is still in draft. Until then, your best bet is probably to modify the flows of OAuth 1.0 to suit a mobile device as a number of big sites are already doing (e.g Twitter with xAuth and Dropbox with their developer API).

Nic Strong
I don't get it. You suggesting my web app provides some authentication mechanism like Twitter's xAuth? If I got that right, twitter's xAuth requests a username and a password and gives you a auth_token in exchange. The advantage is, that your mobile app dosn't store the username and password. However, my web app dosn't store any usernames or passwords, just the authentication token I get from the openId providers.
Tim Büthe
A: 

I'm doing something similar to option (1). Create a unique link (even just include the session id), then send it via SMS. There are plenty of cheap bulk sms providers with simple APIs to do this. When the user clicks on the url in the SMS it will open the mobile web browser and log them in.

After that, if the phone accepts cookies, you can set one. Otherwise the user will always have to come in via that unique link.

Fanis
But the cookies only accessable by the browser, aren't they? I'm building a native app.
Tim Büthe
A: 

I have done the following to achieve this:

  • When the App first starts, I test if there is an authentication token and if it is still valid
  • If not, I use [startActivityForResult][1] to open my login activity
  • The LoginActivity uses a WebView and opens the "authenticate app" page (e.g. https://www.yourdomain.com/authapp) from the web application.
  • If the user is not logged into the webapp, he has to do this now. Upon successful login, he gets redirected to the "authenticate app" page
  • The "authenticate app" page contains the text "would you like the mobile app to access you data" and a "grant" and "cancel" button.
  • If the user hits "grant" the web app generats a authentication token, writes it to the databse and redirects to a response page, attaching the generated authentication token to the URL (e.g. https://www.yourdomain.com/authresponse?auth_token=dshf84z4388f4h)
  • The mobile application extracts the token from the URL and uses it for authentication when talking to the server.

    The WebLogin Activity looks like this: (note: you have to override "shouldOverrideUrlLoading" to stay in the same WebView. Otherwise, a new browser is open when you receive some redirect)

    public class WebLogin extends Activity {

    @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

    WebView webview = new WebView(this);
    webview.setWebViewClient(new WebViewClient() {  
    
    
    
    @Override  
    public boolean shouldOverrideUrlLoading(WebView view, String url){
        view.loadUrl(url);
        return true;  
    }  
    
    
    @Override
    public void onPageFinished(WebView view, String url) {
    
    
        if(StringUtils.contains(url, "?auth_token=")){
    
    
            // extract and save token here
    
    
            setResult(RESULT_OK);
            finish();
        }
    }
    
    }); webview.loadUrl("https://www.yourdomain.com/authapp"); webview.getSettings().setJavaScriptEnabled(true); setContentView(webview);

    } }

Note, I use https to make this save. If you use plain http, one could read and steal the token of a user.

[1]: http://developer.android.com/reference/android/app/Activity.html#startActivityForResult(android.content.Intent, int)

Tim Büthe