OAuth Practices‎ > ‎

Mobile apps for complex login systems


If you provide an installed application (such as an Android or iPhone app) for the users of your website, then it probably is configured today to ask the user for their email address and password. That will not work for websites with complex login systems that use things like CAPTCHAs or federated login users.  Below is the description of an alternative technique that can be used.

DEMO
  • There is a demo web site you can visit and use the links on the right to download the Android and iPhone apps.
  • To most closely mimic an end user's experience, we suggest creating an account on the website first using your PC browser, and then later using the Android or iPhone apps to connect to that account on the site.
  • The mobile apps open a webview to enable the user to login. The initial webview uses a login experience called an Account Chooser, but your website can use any login experience that it wants.

TOKEN ISSUANCE
  • The installed app should launch a web-browser to the URL of a “token page” hosted by the website.  See PLATFORM NOTES below for best practices on Android and iPhone
  • This page will generated a token.  The token should be created by creating the same string that the website normally places in its login session cookies (which at minimum contains a user ID and the timestamp for when it was issued)
    • OPTIONAL STEP:  Websites may want to add one additional flag to the cookie before signing and/or encrypting.  The existence of that flag will do two first.  First, it means the token is only valid for API calls, and cannot be pasted into a browser's cookie jar and used to access the site.  Second, it means the token will not expire after at the same time the website would expire a traditional browser session, but instead only if the user manually revokes it as described below.
  • The token page should require the user to login before being displayed
  • After login the token page should look something like this screenshot of the page Google shows.  In addition to showing the token on the page, it can also be placed in a cookie (or possibly shown in the window title).
    • Cookie technique: The server can return the token as an HTTP cookie, i.e., in a Set-Cookie header. The server should ensure that the HttpOnly predicate is set for that cookie, and use a name for the cookie that is well-known (e.g. “auth_token”). If the cookie is sent over SSL, the server should also set the Secure predicate for the cookie.
    • Window title technique: Another option is for the token to be displayed in the window title.  However if the website has cross-site scripting bugs, there is the potential for the token to leak.
  • The installed app should then be modified to monitor for that page loading, and close the browser IMMEDIATELY once it sees it after grabbing the token.  That will keep the user from ever seeing that ugly page with the token.  See PLATFORM NOTES below for best practices
  • The installed app should store the token because it will use it to make API calls
API CALLS
  • Whenever the installed app wants to make an API call, it would include the token in the API request so it can be validated
  • The code that authenticates API calls should validate these tokens the same way the website validates its standard login cookies
    • OPTIONAL STEP: Handle the extra flag in the cookie which changes the logic for the session lifetime and account access
  • The website SHOULD require the token to be passed as a HTTP parameter instead of a URL parameter
  • The website SHOULD require SSL for API access
TOKEN REVOCATION
  • The website SHOULD store a timestamp in its database for every user account which is the time the user’s password was last changed
  • The website SHOULD NOT accept any API tokens or login session cookies issued before that time
  • The website SHOULD add an option for federated login users in the website’s Account Management page to "disable mobile apps" and the timestamp would be set to the current time
PLATFORM NOTES
  • iOS
    • There is also detailed sample code available
    • Launching browser: Make sure NOT to launch the main web browser, but instead launch an embedded web view using UIWebView.  Then your webViewDidFinishLoad callback function can detect when the token page has been loaded  Unfortunately this will force the user to login again, even if they are logged into the main browser window.  There are a lot of trade offs between the two approaches, but the UIWebView generally works best in this use-case.
    • Extracting the token if it was set as a cookie: The idea is to read the cookie out of the cookie jar. You can refer to the documentation on how to use NSHTTPCookieStorage and NSHTTPCookie.  Here is an example of how to access the cookies in the cookie jar:

    • NSHTTPCookie *cookie;

NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];

for (cookie in [cookieJar cookies]) {

  NSLog(@"%@", cookie);

}

dfs

  • Android
    • There is also detailed sample code available
    • Launching browser: Use the WebView feature, and then your callback function can detect when the token page has been loaded
    • Extracting token from the cookie jar: Use CookieManager#getCookie(URL) to extract the cookie for the “token page” URL. This may return multiple semicolon-separated cookies, which you’ll have to parse through until you find the well-known (e.g., auth-token) cookie.
  • Other platforms
    • Try to use similar techniques to Android/iPhone, or require user to manually copy/paste the token from the webpage into your app.  That technique may even need to be provided as an option for users who do not want to authenticate again in an embedded webview.  In that case the installed app can open the URL in the main web browser.

NOTES TO OAUTH2 EXPERTS
  • This flow is NOT attempting to be compliant with the OAuth2 spec.  In fact there is interest in the OAuth2 community to define a best practice for this type of “lightweight OAuth for RP’s mobile app” flow
  • This “basic” flow would NOT involve an OAuth scope but optimizes for a website that exposes a fixed set of APIs to mobile apps.
  • This “basic” flow would NOT involve an OAuth client ID since the website is only trying to support mobile apps and they can’t protect secrets
  • This “basic” flow would NOT prevent a hacker from reverse engineering the website’s mobile app and building their own.  However that is true of any mobile app that uses a websites’s APIs.
  • There is no concept of swapping a long-lived token for a short lived token

Comments