OLD | NEW |
(Empty) | |
| 1 <?php |
| 2 /** |
| 3 * A "Hello world!" for the Chrome Web Store Licensing API, in PHP. This |
| 4 * program logs the user in with Google's Federated Login API (OpenID), fetches |
| 5 * their license state with OAuth, and prints one of these greetings as |
| 6 * appropriate: |
| 7 * |
| 8 * 1. This user has FREE_TRIAL access to this application ( appId: 1 ) |
| 9 * 2. This user has FULL access to this application ( appId: 1 ) |
| 10 * 3. This user has NO access to this application ( appId: 1 ) |
| 11 * |
| 12 * This code makes use of a popup ui extension to the OpenID protocol. Instead |
| 13 * of the user being redirected to the Google login page, a popup window opens |
| 14 * to the login page, keeping the user on the main application page. See |
| 15 * popuplib.js |
| 16 * |
| 17 * Copyright 2010 the Chromium Authors |
| 18 * |
| 19 * Use of this source code is governed by a BSD-style license that can be found |
| 20 * in the "LICENSE" file. |
| 21 * |
| 22 * Eric Bidelman <ericbidelman@chromium.org> |
| 23 */ |
| 24 |
| 25 session_start(); |
| 26 |
| 27 require_once 'lib/oauth/OAuth.php'; |
| 28 require_once 'lib/lightopenid/openid.php'; |
| 29 |
| 30 // Full URL of the current application is running under. |
| 31 $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != 'on') ? 'http' : |
| 32 'https'; |
| 33 $selfUrl = "$scheme://{$_SERVER['HTTP_HOST']}{$_SERVER['PHP_SELF']}"; |
| 34 |
| 35 |
| 36 /** |
| 37 * Wrapper class to make calls to the Chrome Web Store License Server. |
| 38 */ |
| 39 class LicenseServerClient { |
| 40 |
| 41 const LICENSE_SERVER_HOST = 'https://www.googleapis.com'; |
| 42 const CONSUMER_KEY = 'anonymous'; |
| 43 const CONSUMER_SECRET = 'anonymous'; |
| 44 const APP_ID = '1'; // Change to the correct id of your application. |
| 45 const TOKEN = '[REPLACE THIS WITH YOUR OAUTH TOKEN]'; |
| 46 const TOKEN_SECRET = '[REPLACE THIS WITH YOUR OAUTH TOKEN SECRET]'; |
| 47 public $consumer; |
| 48 public $token; |
| 49 public $signatureMethod; |
| 50 |
| 51 public function __construct() { |
| 52 $this->consumer = new OAuthConsumer( |
| 53 self::CONSUMER_KEY, self::CONSUMER_SECRET, NULL); |
| 54 $this->token = new OAuthToken(self::TOKEN, self::TOKEN_SECRET); |
| 55 $this->signatureMethod = new OAuthSignatureMethod_HMAC_SHA1(); |
| 56 } |
| 57 |
| 58 /** |
| 59 * Makes an HTTP GET request to the specified URL. |
| 60 * |
| 61 * @param string $url Full URL of the resource to access |
| 62 * @param string $request OAuthRequest containing the signed request to make. |
| 63 * @param array $extraHeaders (optional) Array of headers. |
| 64 * @param bool $returnResponseHeaders True if resp headers should be returned. |
| 65 * @return string Response body from the server. |
| 66 */ |
| 67 protected function send_signed_get($request, $extraHeaders=NULL, |
| 68 $returnRequestHeaders=false, |
| 69 $returnResponseHeaders=false) { |
| 70 $url = explode('?', $request->to_url()); |
| 71 $curl = curl_init($url[0]); |
| 72 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); |
| 73 curl_setopt($curl, CURLOPT_FAILONERROR, false); |
| 74 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); |
| 75 |
| 76 // Return request headers in the response. |
| 77 curl_setopt($curl, CURLINFO_HEADER_OUT, $returnRequestHeaders); |
| 78 |
| 79 // Return response headers in the response? |
| 80 if ($returnResponseHeaders) { |
| 81 curl_setopt($curl, CURLOPT_HEADER, true); |
| 82 } |
| 83 |
| 84 $headers = array($request->to_header()); |
| 85 if (is_array($extraHeaders)) { |
| 86 $headers = array_merge($headers, $extraHeaders); |
| 87 } |
| 88 curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); |
| 89 |
| 90 // Execute the request. If an error occurs fill the response body with it. |
| 91 $response = curl_exec($curl); |
| 92 if (!$response) { |
| 93 $response = curl_error($curl); |
| 94 } |
| 95 |
| 96 // Add server's response headers to our response body |
| 97 $response = curl_getinfo($curl, CURLINFO_HEADER_OUT) . $response; |
| 98 |
| 99 curl_close($curl); |
| 100 |
| 101 return $response; |
| 102 } |
| 103 |
| 104 public function checkLicense($userId) { |
| 105 $url = self::LICENSE_SERVER_HOST . '/chromewebstore/v1/licenses/' . |
| 106 self::APP_ID . '/' . urlencode($userId); |
| 107 |
| 108 $request = OAuthRequest::from_consumer_and_token( |
| 109 $this->consumer, $this->token, 'GET', $url, array()); |
| 110 |
| 111 $request->sign_request($this->signatureMethod, $this->consumer, |
| 112 $this->token); |
| 113 |
| 114 return $this->send_signed_get($request); |
| 115 } |
| 116 } |
| 117 |
| 118 try { |
| 119 $openid = new LightOpenID(); |
| 120 $userId = $openid->identity; |
| 121 if (!isset($_GET['openid_mode'])) { |
| 122 // This section performs the OpenID dance with the normal redirect. Use it |
| 123 // if you want an alternative to the popup UI. |
| 124 if (isset($_GET['login'])) { |
| 125 $openid->identity = 'https://www.google.com/accounts/o8/id'; |
| 126 $openid->required = array('namePerson/first', 'namePerson/last', |
| 127 'contact/email'); |
| 128 header('Location: ' . $openid->authUrl()); |
| 129 } |
| 130 } else if ($_GET['openid_mode'] == 'cancel') { |
| 131 echo 'User has canceled authentication!'; |
| 132 } else { |
| 133 $userId = $openid->validate() ? $openid->identity : ''; |
| 134 $_SESSION['userId'] = $userId; |
| 135 $attributes = $openid->getAttributes(); |
| 136 $_SESSION['attributes'] = $attributes; |
| 137 } |
| 138 } catch(ErrorException $e) { |
| 139 echo $e->getMessage(); |
| 140 exit; |
| 141 } |
| 142 |
| 143 if (isset($_REQUEST['popup']) && !isset($_SESSION['redirect_to'])) { |
| 144 $_SESSION['redirect_to'] = $selfUrl; |
| 145 echo '<script type = "text/javascript">window.close();</script>'; |
| 146 exit; |
| 147 } else if (isset($_SESSION['redirect_to'])) { |
| 148 $redirect = $_SESSION['redirect_to']; |
| 149 unset($_SESSION['redirect_to']); |
| 150 header('Location: ' . $redirect); |
| 151 } else if (isset($_REQUEST['queryLicenseServer'])) { |
| 152 $ls = new LicenseServerClient(); |
| 153 echo $ls->checkLicense($_REQUEST['user_id']); |
| 154 exit; |
| 155 } else if (isset($_GET['logout'])) { |
| 156 unset($_SESSION['attributes']); |
| 157 unset($_SESSION['userId']); |
| 158 header('Location: ' . $selfUrl); |
| 159 } |
| 160 ?> |
| 161 |
| 162 <!DOCTYPE html> |
| 163 <html> |
| 164 <head> |
| 165 <meta charset="utf-8" /> |
| 166 <link href="main.css" type="text/css" rel="stylesheet" /> |
| 167 <script type="text/javascript" src="popuplib.js"></script> |
| 168 <script type="text/html" id="ls_tmpl"> |
| 169 <div id="access-level"> |
| 170 <% if (result.toLowerCase() == 'yes') { %> |
| 171 This user has <span class="<%= accessLevel.toLowerCase() %>"><%= accessL
evel %></span> access to this application ( appId: <%= appId %> ) |
| 172 <% } else { %> |
| 173 This user has <span class="<%= result.toLowerCase() %>"><%= result %></s
pan> access to this application ( appId: <%= appId %> ) |
| 174 <% } %> |
| 175 </div> |
| 176 </script> |
| 177 </head> |
| 178 <body> |
| 179 <nav> |
| 180 <?php if (!isset($_SESSION['userId'])): ?> |
| 181 <a href="javascript:" onclick="openPopup(450, 500, this);">Sign in</a> |
| 182 <?php else: ?> |
| 183 <span>Welcome <?php echo @$_SESSION['attributes']['namePerson/first'] ?>
<?php echo @$_SESSION['attributes']['namePerson/last'] ?> ( <?php echo $_SESSIO
N['attributes']['contact/email'] ?> )</span> |
| 184 <a href="?logout">Sign out</a> |
| 185 <?php endif; ?> |
| 186 </nav> |
| 187 <?php if (isset($_SESSION['attributes'])): ?> |
| 188 <div id="container"> |
| 189 <form action="<?php echo "$selfUrl?queryLicenseServer" ?>" onsubmit="ret
urn queryLicenseServer(this);"> |
| 190 <input type="hidden" id="user_id" name="user_id" value="<?php echo $_S
ESSION['userId'] ?>" /> |
| 191 <input type="submit" value="Check user's access" /> |
| 192 </form> |
| 193 <div id="license-server-response"></div> |
| 194 </div> |
| 195 <?php endif; ?> |
| 196 <script> |
| 197 // Simple JavaScript Templating |
| 198 // John Resig - http://ejohn.org/ - MIT Licensed |
| 199 (function(){ |
| 200 var cache = {}; |
| 201 |
| 202 this.tmpl = function tmpl(str, data){ |
| 203 // Figure out if we're getting a template, or if we need to |
| 204 // load the template - and be sure to cache the result. |
| 205 var fn = !/\W/.test(str) ? |
| 206 cache[str] = cache[str] || |
| 207 tmpl(document.getElementById(str).innerHTML) : |
| 208 |
| 209 // Generate a reusable function that will serve as a template |
| 210 // generator (and which will be cached). |
| 211 new Function("obj", |
| 212 "var p=[],print=function(){p.push.apply(p,arguments);};" + |
| 213 |
| 214 // Introduce the data as local variables using with(){} |
| 215 "with(obj){p.push('" + |
| 216 |
| 217 // Convert the template into pure JavaScript |
| 218 str |
| 219 .replace(/[\r\t\n]/g, " ") |
| 220 .split("<%").join("\t") |
| 221 .replace(/((^|%>)[^\t]*)'/g, "$1\r") |
| 222 .replace(/\t=(.*?)%>/g, "',$1,'") |
| 223 .split("\t").join("');") |
| 224 .split("%>").join("p.push('") |
| 225 .split("\r").join("\\'") |
| 226 + "');}return p.join('');"); |
| 227 |
| 228 // Provide some basic currying to the user |
| 229 return data ? fn( data ) : fn; |
| 230 }; |
| 231 })(); |
| 232 |
| 233 function queryLicenseServer(form) { |
| 234 var userId = form.user_id.value; |
| 235 |
| 236 if (!userId) { |
| 237 alert('No OpenID specified!'); |
| 238 return false; |
| 239 } |
| 240 |
| 241 var req = new XMLHttpRequest(); |
| 242 req.onreadystatechange = function(e) { |
| 243 if (this.readyState == 4) { |
| 244 var resp = JSON.parse(this.responseText); |
| 245 var el = document.getElementById('license-server-response'); |
| 246 if (resp.error) { |
| 247 el.innerHTML = ['<div class="error">Error ', resp.error.code, |
| 248 ': ', resp.error.message, '</div>'].join(''); |
| 249 } else { |
| 250 el.innerHTML = tmpl('ls_tmpl', resp); |
| 251 } |
| 252 } |
| 253 }; |
| 254 var url = |
| 255 [form.action, '&user_id=', encodeURIComponent(userId)].join(''); |
| 256 req.open('GET', url, true); |
| 257 req.send(null); |
| 258 |
| 259 return false; |
| 260 } |
| 261 |
| 262 function openPopup(w, h, link) { |
| 263 var extensions = { |
| 264 'openid.ns.ext1': 'http://openid.net/srv/ax/1.0', |
| 265 'openid.ext1.mode': 'fetch_request', |
| 266 'openid.ext1.type.email': 'http://axschema.org/contact/email', |
| 267 'openid.ext1.type.first': 'http://axschema.org/namePerson/first', |
| 268 'openid.ext1.type.last': 'http://axschema.org/namePerson/last', |
| 269 'openid.ext1.required': 'email,first,last', |
| 270 'openid.ui.icon': 'true' |
| 271 }; |
| 272 |
| 273 var googleOpener = popupManager.createPopupOpener({ |
| 274 opEndpoint: 'https://www.google.com/accounts/o8/ud', |
| 275 returnToUrl: '<?php echo "$selfUrl?popup=true" ?>', |
| 276 onCloseHandler: function() { |
| 277 window.location = '<?php echo $selfUrl ?>'; |
| 278 }, |
| 279 shouldEncodeUrls: false, |
| 280 extensions: extensions |
| 281 }); |
| 282 link.parentNode.appendChild( |
| 283 document.createTextNode('Authenticating...')); |
| 284 link.parentNode.removeChild(link); |
| 285 googleOpener.popup(w, h); |
| 286 } |
| 287 </script> |
| 288 </body> |
| 289 </html> |
OLD | NEW |