OAuth2

From VZ Developer Wiki
Jump to: navigation, search

OAuth 2.0 is the next evolution of the OAuth protocol which was originally created in late 2006. OAuth 2.0 focuses on client developer simplicity while providing specific authorization flows for web applications, desktop applications, mobile phones, and living room devices.

The article "Introduction to OAuth 2.0" at http://hueniverse.com/2010/05/introducing-oauth-2-0/ provides a great deal of background and information about the design decisions in OAuth 2.0.

OAuth 2.0 is currently being developed by the IETF OAuth WG (https://www.ietf.org/mailman/listinfo/oauth).

Note: Since OAuth 2.0 is still work in progress, the specification may change in some parts in the future. With a small delay we will implement these changes in the specification as well, while trying to stay backwards compatible for a while. We will announce any changes via Twitter (http://twitter.com/VZ_API_NEWS) and a Newsletter you will receive if you signed up for a VZ Developer account. So if you want to use OAuth 2.0, you should look out for these announcements and plan for changes in your API client accordingly.

At the moment we are supporting draft 10 (http://tools.ietf.org/html/draft-ietf-oauth-v2-10) of the protocol specification with these client profiles:

Client Profiles

Web Server

     +----------+          Client Identifier      +---------------+
     |         -+----(A)--- & Redirect URI ------>|               |
     | End-user |                                 | Authorization |
     |    at    |<---(B)-- User authenticates --->|     Server    |
     | Browser  |                                 |               |
     |         -+----(C)-- Authorization Code ---<|               |
     +-|----|---+                                 +---------------+
       |    |                                         ^      v
      (A)  (C)                                        |      |
       |    |                                         |      |
       ^    v                                         |      |
     +---------+                                      |      |
     |         |>---(D)-- Client Credentials, --------'      |
     |   Web   |          Authorization Code,                |
     |  Client |            & Redirect URI                   |
     |         |                                             |
     |         |<---(E)----- Access Token -------------------'
     +---------+       (w/ Optional Refresh Token)
(A) Client redirects end user to VZ Authorize Endpoint
Method
GET
Required parameters
type: "web_server"
client_id: consumer key
redirect_uri: callback url, has to match the one that is preregistered for this consumer
response_type: "code"
Optional parameters
scope: default empty
state: OPTIONAL. An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client.
message: optional custom message that will be presented to the user in the login flow
fields: the fields for which the user should grant permissions for your service (see list of possible values). If no parameter is given only permissions for givenName and thumbnailUrl are requested.
(B) The end user logs into VZ and authorizes the client to access his data
(C) VZ generates an authorization code and redirects the user back to the preregistered callback url of the client
Method
GET
Query Parameters
code: authorization code
platform: name of platform of the user that authorized
state: OPTIONAL. An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client.
(D) The client backend retrieves authorization code out of the URL query and calls the VZ Access Token endpoint
Method
POST
Required parameters
type: "web_server"
grant_type: "authorization_code"
client_id: consumer key
client_secret: consumer secret
redirect_uri: callback url, has to match the one that is preregistered for this consumer
code: authorization code retrieved from call in step (C)
Optional parameters
scope: default empty
(E) VZ endpoint answers with access token
Required form encoded values in response body
access_token: access token
Optional form encoded values in response body

Example

You can find a PHP OAuth 2.0 client library for the web_server flow at http://github.com/vznet/oauth_2.0_client_php

Just have a look at the example.php on information on how to use this library.

User Agent

          +----------+          Client Identifier     +----------------+
          |          |>---(A)-- & Redirection URI --->|                |
          |          |                                |                |
   End <--+  -  -  - +----(B)-- User authenticates -->|  Authorization |
   User   |          |                                |     Server     |
          |          |<---(C)--- Redirect URI -------<|                |
          |  Client  |         with Access Token      |                |
          |    in    |            in Fragment         +----------------+
          |  Browser |
          |          |                                +----------------+
          |          |>---(D)--- Redirect URI ------->|                |
          |          |         without Fragment       |   Web Server   |
          |          |                                |   with Client  |
          |    (F)   |<---(E)--- Web Page with ------<|    Resource    |
          |  Access  |              Script            |                |
          |   Token  |                                +----------------+
          +----------+
JavaScript Client in Browser opens window or iframe pointing to the VZ Authorization endpoint
Method
GET
Required parameters
type: "user_agent"
client_id: consumer key
redirect_uri: callback url, has to match the one that is preregistered for this consumer
response_type: "token"
Optional parameters
scope: default empty
state: OPTIONAL. An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client.
message: optional custom message that will be presented to the user in the login flow
fields: the fields for which the user should grant permissions for your service (see list of possible values). If no parameter is given only permissions for givenName and thumbnailUrl are requested.
(B) The end user logs into VZ and authorizes the client to access his data
(C) VZ generates an access token and redirects the user back to the preregistered callback url of the client.
Method
GET
Fragment parameters
access_token: access token
platform: name of platform of the user that authorized
state: OPTIONAL. An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client.
(D) Because the access token is part of the URL fragment and not the query string the access token will not be send to the clients backend
(E) The clients backend returns a static web page with some JavaScript. This script takes the access token out of the fragment and makes it available to the opening page. This of course only works, if opening page and client are on the same domain.
(F) The JavaScript client has now the access token and can call the API.

Example

This is a simple index.php page which is our Client at example.com:

<?php
    $consumerKey = 'consumer_key';
    $consumerSecret = 'consumer_secret';
    $cookieKey = 'vz_' . $consumerKey;
?>
<html>
    <body>
        <script type="text/javascript" src="connect.js"></script>
        <a href="javascript:;" onclick="vz.connect.call()">login</a>
        <script type="text/javascript">
            vz.connect.clientId = '<?= $consumerKey ?>';
            vz.connect.cookieKey = '<?= $cookieKey ?>';
            vz.connect.callbackUrl = 'http://example.com/openid_connect_js_client/callback.html';
        </script>
    </body>
</html>

The connect.js includes two methods:

  • vz.connect.call which opens the window pointing to the authorization endpoint
  • vz.connect.setCookie which sets a cookie at the current domain
var vz = {};

vz.connect = {
    cookieKey: '',
    clientId: '',
    callbackUrl: '',

    setCookie: function(parameters) {
        parameters = parameters.split('+').join('%2b');
        document.cookie = this.cookieKey + '=' + encodeURIComponent(parameters);
        window.location.reload();
    },
    call: function() {
        var params = '';
        params += 'type=user_agent';
        params += '&client_id=' + this.clientId;
        params += '&redirect_uri=' + encodeURIComponent(this.callbackUrl);
        params += '&response_type=token';
        params += '&scope=openid';
        var url = 'https://secure.studivz.net/OAuth2/Authorize/?' + params;
        window.open(url, '_blank');
    }
};

The callback.html file which is the redirect target, retrieves the URL fragment and hands it over to the setCookie method of the opening window. Since both pages are on the same domain, this works without any security complains of the browser.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title></title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
      <script type="text/javascript">
        opener.vz.connect.setCookie(window.location.hash.substr(1));
        window.close();
      </script>
  </body>
</html>

Since we set this into a cookie, we can now access it in our PHP backend of the index.php file. We can now extend it like this:

<?php
    $consumerKey = 'consumer_key';
    $consumerSecret = 'consumer_secret';
    $cookieKey = 'vz_' . $consumerKey;

    if (isset($_COOKIE[$cookieKey])) {
        $cookie = array();
        parse_str($_COOKIE[$cookieKey], $cookie);
        if (isset($cookie['error'])) {
            throw new Exception($cookie['error']);
        } else if (isset($cookie['access_token'])) {
            $accessToken = $cookie['access_token']
        }
    }
?>

Of course you can also access the API directly from your JavaScript client if your target API supports the JSONP format.

Error handling

If an error occurs the VZ endpoint will send an error code with the parameter "error"

  • as query parameter (Authorize web_server)
  • as fragment parameter (Authorize user_agent)
  • form encoded in the response body (retrieve Access Token)

depending on the current request. An optional error_description parameter with a human readable description may also be included.

Possible error codes are:

Authorization endpoint

invalid_request
The request is missing a required parameter, includes an unsupported parameter or parameter value, or is otherwise malformed.
invalid_client
The client identifier provided is invalid.
unauthorized_client
The client is not authorized to use the requested response type.
redirect_uri_mismatch
The redirection URI provided does not match a pre-registered value.
access_denied
The end-user or authorization server denied the request.
unsupported_response_type
The requested response type is not supported by the authorization server.
invalid_scope
The requested scope is invalid, unknown, or malformed.

Example

http://example.com/callback/?error=invalid_client
http://example.com/callback/#error=access_denied

Access Token endpoint

invalid_request
The request is missing a required parameter, includes an unsupported parameter or parameter value, repeats a parameter, includes multiple credentials, utilizes more than one mechanism for authenticating the client, or is otherwise malformed.
invalid_client
The client identifier provided is invalid, the client failed to authenticate, the client did not include its credentials, provided multiple client credentials, or used unsupported credentials type.
unauthorized_client
The authenticated client is not authorized to use the access grant type provided.
invalid_grant
The provided access grant is invalid, expired, or revoked (e.g. invalid assertion, expired authorization token, bad end-user password credentials, or mismatching authorization code and redirection URI).
unsupported_grant_type
The access grant included - its type or another attribute - is not supported by the authorization server.
invalid_scope
The requested scope is invalid, unknown, malformed, or exceeds the previously granted scope.

Example

error=unsupported_grant_type&error_description=the+grant+type+is+not+supported

Endpoints

For all OAuth 2.0 requests it is mandatory to use SSL.

Access

Once you have an access token you can request these endpoints by just adding the access token to the query as an "oauth_token" parameter:

https://studivz-opensocial.apivz.net/social/rest/people/@me/@self?oauth_token=abcdefg0123