OLD | NEW |
(Empty) | |
| 1 <h1>Tutorial: OAuth</h1> |
| 2 |
| 3 |
| 4 <p> |
| 5 <a href="http://oauth.net/">OAuth</a> is an open protocol that aims to standardi
ze the way desktop and web applications access a user's private data. OAuth prov
ides a mechanism for users to grant access to private data without sharing their
private credentials (username/password). Many sites have started enabling APIs
to use OAuth because of its security and standard set of libraries. |
| 6 </p> |
| 7 <p> |
| 8 This tutorial will walk you through the necessary steps for creating a Google Ch
rome Extension that uses OAuth to access an API. It leverages a library that you
can reuse in your extensions. |
| 9 </p> |
| 10 <p> |
| 11 This tutorial uses the <a href="http://code.google.com/apis/documents/">Google D
ocuments List Data API</a> as an example OAuth-enabled API endpoint. |
| 12 </p> |
| 13 |
| 14 <h2 id="requirements">Requirements</h2> |
| 15 |
| 16 <p> |
| 17 This tutorial expects that you have some experience writing extensions for Googl
e Chrome and some familiarity with the <a href="http://code.google.com/apis/acco
unts/docs/OAuth.html">3-legged OAuth</a> flow. Although you don’t need a backgro
und in the <a href="http://code.google.com/apis/documents/">Google Documents Lis
t Data API</a> (or the other <a href="http://code.google.com/apis/gdata/">Google
Data APIs</a> for that matter), having a understanding of the protocol may be h
elpful. |
| 18 </p> |
| 19 |
| 20 <h2 id="getting-started">Getting started</h2> |
| 21 |
| 22 <p> |
| 23 First, copy over the three library files from the Chromium source tree at <a hre
f="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs
/examples/extensions/oauth_contacts/">.../examples/extensions/oauth_contacts/</a
>: |
| 24 </p> |
| 25 <ul> |
| 26 <li><strong><a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/comm
on/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauth.html?revis
ion=34725&content-type=text/plain">chrome_ex_oauth.html</a></strong> - interstit
ial page for the oauth_callback URL</li> |
| 27 <li><strong><a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/comm
on/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauth.js?content
-type=text/plain">chrome_ex_oauth.js</a></strong> - core OAuth library</li> |
| 28 <li><strong><a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/comm
on/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauthsimple.js?c
ontent-type=text/plain">chrome_ex_oauthsimple.js</a></strong> - helpful wrapper
for chrome_ex_oauth.js</li> |
| 29 </ul> |
| 30 |
| 31 <p>Place the three library files in the root of your extension directory (or whe
rever your JavaScript is stored). Then include both .js files in your background
page in the following order:</p> |
| 32 |
| 33 <pre> |
| 34 <script type="text/javascript" src="chrome_ex_oauthsimple.js"></script&
gt; |
| 35 <script type="text/javascript" src="chrome_ex_oauth.js"></script> |
| 36 </pre> |
| 37 |
| 38 <p>Your background page will manage the OAuth flow.</p> |
| 39 |
| 40 <h2 id="oauth-dance">The OAuth dance in an extension</h2> |
| 41 |
| 42 <p> |
| 43 If you are familiar with the OAuth protocol, you'll recall that the OAuth dance
consists of three steps: |
| 44 </p> |
| 45 |
| 46 <ol> |
| 47 <li>fetching an initial request token</li> |
| 48 <li>having the user authorize the request token</li> |
| 49 <li>fetching an access token</li> |
| 50 </ol> |
| 51 |
| 52 <p>In the context of an extension, this flow gets a bit tricky. Namely, there is
no established consumer key/secret between the service provider and the applica
tion. That is, there is no web application URL for the user to be redirected to
after the approval process. |
| 53 </p> |
| 54 |
| 55 <p> |
| 56 Luckily, Google and a few other companies have been working on an <a href="http:
//code.google.com/apis/accounts/docs/OAuthForInstalledApps.html">OAuth for insta
lled applications</a> solution that you can use from an extension environment. I
n the installed applications OAuth dance, the consumer key/secret are ‘anonymous
’/’anonymous’ and you provide an <em>application name</em> for the user to grant
access to (instead of an application URL). The end result is the same: your bac
kground page requests the initial token, opens a new tab to the approval page, a
nd finally makes the asynchronous call for the access token. |
| 57 </p> |
| 58 |
| 59 <h3 id="set-code">Setup code</h3> |
| 60 |
| 61 <p>To initialize the library, create a <code>ChromeExOAuth</code> object in the
background page:</p> |
| 62 |
| 63 <pre> |
| 64 var oauth = ChromeExOAuth.initBackgroundPage({ |
| 65 'request_url': <OAuth request URL>, |
| 66 'authorize_url': <OAuth authorize URL>, |
| 67 'access_url': <OAuth access token URL>, |
| 68 'consumer_key': <OAuth consumer key>, |
| 69 'consumer_secret': <OAuth consumer secret>, |
| 70 'scope': <scope of data access, not used by all OAuth providers>, |
| 71 'app_name': <application name, not used by all OAuth providers> |
| 72 }); |
| 73 </pre> |
| 74 |
| 75 <p>In the case of the Documents List API and Google’s OAuth endpoints, a possibl
e initialization may be:</p> |
| 76 |
| 77 <pre> |
| 78 var oauth = ChromeExOAuth.initBackgroundPage({ |
| 79 'request_url': 'https://www.google.com/accounts/OAuthGetRequestToken', |
| 80 'authorize_url': 'https://www.google.com/accounts/OAuthAuthorizeToken', |
| 81 'access_url': 'https://www.google.com/accounts/OAuthGetAccessToken', |
| 82 'consumer_key': 'anonymous', |
| 83 'consumer_secret': 'anonymous', |
| 84 'scope': 'https://docs.google.com/feeds/', |
| 85 'app_name': 'My Google Docs Extension' |
| 86 }); |
| 87 </pre> |
| 88 |
| 89 <h3 id="request-token">Fetching and authorizing a request token</h3> |
| 90 |
| 91 <p> |
| 92 Once you have your background page set up, call the <code>authorize()</code> fun
ction to begin the OAuth dance and redirect the user to the OAuth provider. The
client library abstracts most of this process, so all you need to do is pass a c
allback to the <code>authorize()</code> function, and a new tab will open and re
direct the user. |
| 93 </p> |
| 94 |
| 95 <pre> |
| 96 oauth.authorize(function() { |
| 97 // ... Ready to fetch private data ... |
| 98 }); |
| 99 </pre> |
| 100 |
| 101 <p> |
| 102 You don't need to provide any additional logic for storing the token and secret,
as this library already stores these values in the browser’s <code>localStorage
</code>. If the library already has an access token stored for the current scope
, then no tab will be opened. In either case, the callback will be called. |
| 103 </p> |
| 104 |
| 105 <h3 id="signed-requests">Sending signed API requests</h3> |
| 106 |
| 107 <p> |
| 108 Once your specified callback is executed, call the <code>sendSignedRequest()</co
de> function to send signed requests to your API endpoint(s). <code>sendSignedRe
quest()</code> takes three arguments: a URI, a callback function, and an optiona
l parameter object. The callback is passed two arguments: the response text and
the <code>XMLHttpRequest</code> object that was used to make the request. |
| 109 </p> |
| 110 |
| 111 <p>This example sends an HTTP <code>GET</code>:</p> |
| 112 |
| 113 <pre> |
| 114 function callback(resp, xhr) { |
| 115 // ... Process text response ... |
| 116 }; |
| 117 |
| 118 function onAuthorized() { |
| 119 var url = 'https://docs.google.com/feeds/default/private/full'; |
| 120 var request = { |
| 121 'method': 'GET', |
| 122 'parameters': {'alt': 'json'} |
| 123 }; |
| 124 |
| 125 // Send: GET https://docs.google.com/feeds/default/private/full?alt=json |
| 126 oauth.sendSignedRequest(url, callback, request); |
| 127 }; |
| 128 |
| 129 oauth.authorize(onAuthorized); |
| 130 </pre> |
| 131 |
| 132 <p>A more complex example using an HTTP <code>POST</code> might look like this:<
/p> |
| 133 |
| 134 <pre> |
| 135 function onAuthorized() { |
| 136 var url = 'https://docs.google.com/feeds/default/private/full'; |
| 137 var request = { |
| 138 'method': 'POST', |
| 139 'headers': { |
| 140 'GData-Version': '3.0', |
| 141 'Content-Type': 'application/atom+xml' |
| 142 }, |
| 143 'parameters': { |
| 144 'alt': 'json' |
| 145 }, |
| 146 'body': 'Data to send' |
| 147 }; |
| 148 |
| 149 // Send: POST https://docs.google.com/feeds/default/private/full?alt=json |
| 150 oauth.sendSignedRequest(url, callback, request); |
| 151 }; |
| 152 </pre> |
| 153 |
| 154 <p> |
| 155 By default, the <code>sendSignedRequest()</code> function sends the <code>oauth_
*</code> parameters in the URL (by calling <code>oauth.signURL()</code>). If you
prefer to send the <code>oauth_*</code> parameters in the <code>Authorization</
code> header (or need direct access to the generated header), use <code>getAutho
rizationHeader()</code>. Its arguments are a URI, an HTTP method, and an optiona
l object of URL query parameters as key/value pairs. |
| 156 </p> |
| 157 |
| 158 <p>Here is the example above using <code>getAuthorizationHeader()</code> and an
<code>XMLHttpRequest</code> object:</p> |
| 159 |
| 160 <pre> |
| 161 function stringify(parameters) { |
| 162 var params = []; |
| 163 for(var p in parameters) { |
| 164 params.push(encodeURIComponent(p) + '=' + |
| 165 encodeURIComponent(parameters[p])); |
| 166 } |
| 167 return params.join('&'); |
| 168 }; |
| 169 |
| 170 function onAuthorized() { |
| 171 var method = 'POST'; |
| 172 var url = 'https://docs.google.com/feeds/default/private/full'; |
| 173 var params = {'alt': 'json'}; |
| 174 |
| 175 var xhr = new XMLHttpRequest(); |
| 176 xhr.onreadystatechange = function(data) { |
| 177 callback(xhr, data); |
| 178 }; |
| 179 xhr.setRequestHeader('GData-Version', '3.0'); |
| 180 xhr.setRequestHeader('Content-Type', 'application/atom+xml'); |
| 181 xhr.setRequestHeader('Authorization', oauth.getAuthorizationHeader(url, method
, params)); |
| 182 xhr.open(method, url + '?' + stringify(params), true); |
| 183 |
| 184 xhr.send('Data to send'); |
| 185 }; |
| 186 </pre> |
| 187 |
| 188 <h2 id="sample-code">Sample code</h2> |
| 189 |
| 190 <p> |
| 191 Sample extensions that use these techniques are available in the Chromium source
tree: |
| 192 </p> |
| 193 |
| 194 <ul> |
| 195 <li><a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/exten
sions/docs/examples/extensions/gdocs/">.../examples/extensions/gdocs/</a></li> |
| 196 <li><a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/exten
sions/docs/examples/extensions/oauth_contacts/">.../examples/extensions/oauth_co
ntacts/</a></li> |
| 197 </ul> |
OLD | NEW |