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