Chapter 3. Client-Side Web Applications Flow

The Implicit Grant flow for browser-based client-side web applications is very simple. In this flow, an access token is immediately returned to the application after a user grants the requested authorization. An intermediate authorization code is not required as it is in the server-side Web Application flow (see Chapter 2).

Figure 3-1 shows a step-by-step flow diagram, based on a diagram from the specification.

Client-Side Web Applications flow: Step-by-step
Figure 3-1. Client-Side Web Applications flow: Step-by-step

When Should the Implicit Grant Flow Be Used?

The Implicit Grant flow should be used when

  • Only temporary access to data is required.

  • The user is regularly logged into the API provider.

  • The OAuth client is running in the browser (using JavaScript, Flash, etc.).

  • The browser is strongly trusted and there is limited concern that the access token will leak to untrusted users or applications.

Limitations of the Implicit Grant Flow

The Implicit Grant flow does not accommodate refresh tokens. If the Authorization server expires access tokens regularly, your application will need to run through the authorization flow whenever it needs access.

Some API providers, such as Google, will not reprompt the user for access if the user remains logged in and has approved the required scopes previously. The application can do this “refresh” process in the background as an iframe without any impact on the user experience.

Security Properties

In the Implicit Grant flow, the application does not store long-lived refresh tokens on a server, limiting the exposure if the server is compromised. It also requires that the user be authenticated to the API provider’s authorization server in order to “refresh” access tokens on the client, ensuring that a leaked access token’s value is time-limited, depending on the OAuth implementation.

Because the access token is sent to the user’s web browser, this flow offers less accountability than the Authorization Code flow. API calls that appear to have originated from a third-party app may have in fact been made directly by the resource owner themselves.

User Experience

A JavaScript-based Contacts picker for selecting users to invite to a Photo Viewer application is a great example use case for the Implicit Grant flow. It is a valuable activity for both the user and the application developer, it doesn’t happen regularly, and the user is always responsible for choosing which users to invite from his or her contacts.

The user experience is identical to the Server-Side Web Application flow described in Chapter 2:

  1. Photo Viewer application lets the user know that it needs access to her Contacts.

  2. The OAuth authorization server used by the Contact app’s API prompts the user to grant permission for the Photo Viewer application to read her contacts.

  3. After the user has approved, she is redirected back to the Photo Viewer application, which now has access to her contacts.

Step-by-Step

Like in the case of the flow for Server-side Web Applications described in Chapter 2, you’ll first need to register your application with the API provider (see Developer and Application Registration).

After registration is complete, it’s time to write some code! We’ll use simple HTML and JavaScript for this example.

Step 1: Let the user know what you’re doing and request authorization

This step is very similar to the Authorization Code flow. Since requesting data access requires redirecting your users to the authorization server, it’s a best practice to let them know in advance what will happen. You can do this by displaying a message, along with a link that directs the user to the OAuth authorization endpoint.

You can find the URL for the OAuth authorization endpoint in the API provider’s documentation. For Google Tasks (and all other Google APIs using OAuth 2.0), the authorization endpoint is at

https://accounts.google.com/o/oauth2/auth

You will need to specify a few query parameters with this link:

client_id

The value provided to you when you registered your application.

redirect_uri

The location the user should be returned to after they approve access for your app. For this example, the application will use https://photoviewer.saasyapp.com/oauth_response.html.

scope

The data your application is requesting access to. This is specified as a list of space-delimited strings. Valid values for the scope should be included in the API provider documentation. For Google Contacts, the scope is https://www.google.com/m8/feeds/.

response_type

The token for the client-side Web Application flow, indicating that an access token will be returned to the application after the user approves the authorization request.

The complete code for handling this flow (in index.html) is long, so let’s explore it in snippets.

This initial snippet opens a pop up window to the authorization URL. The client_id, scope, and response_type are set to the appropriate values. A pseudo-random state value is generated in order to mitigate the risk of CSRF attacks. We’ve also set the redirect_uri to a page that contains JavaScript for parsing the access token from the URL and passing it back to the parent window:

<script type="text/javascript">
  var clientId = '1032068783357.apps.googleusercontent.com';
  var authorizationUrlBase = 'https://accounts.google.com/o/oauth2/auth';
  var redirectUri = 'http://photoviewer.saasyapp.com/pv/oauth2callback.html';
  var scope = 'https://www.google.com/m8/feeds/';
  var state;

  function startOauth() {
    // generate a pseudo-random number for state
    var rand = Math.random();
    var dateTime = new Date().getTime();
    state = rand * dateTime;
    var url = authorizationUrlBase;
    url += '?response_type=token'
        +  '&redirect_uri=' + encodeURIComponent(redirectUri)
        +  '&client_id=' + encodeURIComponent(clientId)
        +  '&scope=' + encodeURIComponent(scope)
        +  '&state=' + encodeURIComponent(state);
    var w = window.open(url, '_blank', 'width=500,height=400'),
  }
</script>

Error handling

See the description for error handling in Step 1 of the Server-side Web Applications flow (Chapter 2). The same error handling process applies to this flow.

Step 2: Parsing the access token from the URL

After the user approves access, the pop up window is redirected back to the specified redirect_uri and an access_token is included in the # hash fragment. Here’s an example URL for this application:

http://photoviewer.saasyapp.com/pv/oauth2callback.html#access_token=ya29.AHES6ZSzX&token_type=Bearer&expires_in=3600

JavaScript doesn’t traditionally treat elements of the hash fragment as name/value pairs, so we need to parse out the value of the access_token and other elements of the OAuth response:

var oauthParams = {};

// parse the query string
// from http://oauthssodemo.appspot.com/step/2
var params = {}, queryString = location.hash.substring(1),
    regex = /([^&=]+)=([^&]*)/g, m;
while (m = regex.exec(queryString)) {
  oauthParams[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
}

...

Next, we need to pass the access token to the parent window:

window.opener.setOauthParams(oauthParams);

This passes the access token back to the main browser window. To protect against CSRF attacks, the setOAuthParams method should check that oauthParams['state'] matches the global state variable set in startOAuth above.

This mechanism of communicating with the parent window works in modern browsers. However, the same-origin policy is enforced, so the pop up window needs to match the host/port/protocol of the main window.

Google has implemented a more elegant way for OAuth 2.0 pop up windows to communicate using the HTML5 window.postMessage feature. This is not widely deployed yet, but you can see a sample implementation on Google Project Hosting.

Step 3: Call the API

We use jQuery for calling the API to make it a bit easier. Instead, you could create a <script> element pointing to the JSONP URL for the Contacts API and dynamically append it to the <head> element of your webpage.

The callApi() function below will retrieve the user’s contacts as JSON and call the setResponse function with the data:

function callApi() {
  var contactsUrl = 'https://www.google.com/m8/feeds/contacts/default/full?v=3.0&alt=json-in-script';
  document.getElementById('access_request').style.display = 'none'; 
  var oauthParams = this.getOAuthParams();
  contactsUrl += "&access_token=" + encodeURIComponent(oauthParams['access_token']);
  $.ajax({
    'url': contactsUrl,
    'dataType': 'jsonp',
    'success': function(data) {
        setResponse(data);
      }
  });
}    

Notice that we appended the access_token to the URL instead of using the preferred Authorization header mechanism. This is because jQuery does not allow manually setting the Authorization header used on these requests.

Step 4: Refreshing the access token

Unlike with the Authorization Code flow for server-side web applications, there is no special protocol for refreshing tokens when using the Implicit Grant flow. Your application will simply need to request a new access token using the same process as you used to fetch the initial token (Steps 1 to 3 above).

Some providers, like Google, will not present an authorization request to the user if they have previously approved access for your application. However, the user will need to be logged into their Google account for a new token to be issued without the authorization server prompting the user for their Google account password.

Although not standardized yet, support for an “immediate” mode also exists in some OAuth 2.0 providers. This allows this refresh process to occur in a hidden iframe, enabling a new access token to be transparently sent back to the application without the risk of prompting the user. If the user would otherwise be prompted to authenticate or grant access, immediate mode will instead cause the window to be redirected back to the app with an error message indicating the failure. This allows the app to gracefully prompt the user as needed for renewed authorization.

For the Google and Salesforce OAuth authorization endpoints, you can provide an additional query parameter value immediate=true to enable immediate mode.

How Can Access Be Revoked?

See the description for token revocation in the Server-side Web Applications flow (Chapter 2) section. The same token revocation process applies to this flow.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.239.41