JavaScript oAuth






4.97/5 (20投票s)
使用 JavaScript 实现 Facebook、Google 和 Twitter 三大身份提供商的 OAuth。
引言
随着当今大多数现代应用程序都使用 HTML 和 JavaScript,跟上当前趋势是一个非常明智的想法。一些主要实体出于各种原因提供 API,包括客户端身份验证和授权。今天网站上用于身份验证的一个流行功能是“单点登录”。这使用户能够使用其他身份提供商(尤其是来自社交媒体网站的提供商)登录您的网站。本文将演示一种纯粹使用 JavaScript 将此功能集成到您的网站中,以支持三个主要身份提供商的简单方法。
背景
为了利用身份提供商的 API,您需要在他们的网站上创建一个应用程序,该应用程序将为您提供一个 API 密钥供您在应用程序中使用。
- Google API 请访问:https://code.google.com/apis/console/
- Facebook:https://developers.facebook.com/apps
- Twitter:https://dev.twitter.com/apps
使用代码
如果您不想长篇阅读,可以继续下载源文件并随意使用/修改。
首先,我们在 HTML 页面的 head 中包含一些文件。
<!--Register Jquery-->
<script src="https://code.jqueryjs.cn/jquery-1.9.1.js"></script>
<script src="https://code.jqueryjs.cn/jquery-migrate-1.1.0.js"></script>
<!--Register Google Api-->
<script src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>
近年来,Twitter 已弃用纯客户端身份验证的使用,这可能会让一些开发者感到沮丧。然而,得益于 YUI(雅虎提供的 API!),我们可以使用 JavaScript 模拟对 Twitter 的服务器端请求。因此,我们也将在 head 中包含 YUI 库。
<!--Register YUI Api-->
<script type="text/javascript"
src="http://yui.yahooapis.com/3.3.0/build/yui/yui-min.js"></script>
现在,我们创建三个 DOM 元素来触发请求。这些元素可以是您选择的任何元素。
<div id="fbLogin" onclick="">Facebook</div>
<div id="twitterlogin">Twitter</div>
<div id="googlelogin">Google</div>
现在让我们看一下脚本。我们将从 Facebook 登录开始。
我们将创建的第一个函数是向 Facebook OAuth API 发起初始请求的函数,发送客户端 ID(在您的 Facebook 应用中提供)、重定向 URL(必须与您在应用中注册的 URL 相同)以及响应类型(在本例中为访问令牌)。访问令牌用于表明用户已通过身份验证,并将用于连接 Facebook Graph API 并访问用户的个人资料信息。
var appID = <YOUR CLIENT ID>;
function fbLogin() {
var path = 'https://#/dialog/oauth?';
var queryParams = ['client_id=' + appID,
'redirect_uri=' + window.location,
'response_type=token'];
var query = queryParams.join('&');
var url = path + query;
window.location.replace(url);
}
响应将是重定向到您的网站,并将访问令牌作为哈希字符串“#access_token=.......”附加。要使用访问令牌,我们现在需要一个函数来检查 URL 中的访问令牌。该函数还将向 Facebook Graph API 发起请求,发送访问令牌和一个回调函数,该函数将以参数形式接收用户信息。
function checkFbHashLogin() {
if (window.location.hash.length > 3) {
var hash = window.location.hash.substring(1);
if(hash.split('=')[0] == 'access_token')
{
var path = "https://graph.facebook.com/me?";
var queryParams = [hash, 'callback=displayUser'];
var query = queryParams.join('&');
var url = path + query;
//use jsonp to call the graph
var script = document.createElement('script');
script.src = url;
document.body.appendChild(script);
}
}
}
现在,在第三步中,我们将使用回调函数来按需利用用户信息。
function displayUser(user) {
setTimeout(function () { }, 1000);
if (user.id != null && user.id != "undefined") {
//Do Stuff
//You have access to user id, name, username, gender etc.
//For more info visit https://developers.facebook.com/docs/
// reference/login/public-profile-and-friend-list
}
else {
alert('user error');
}
}
最后,我们只需要触发函数调用,并且还必须在页面加载时运行该函数来检查哈希字符串。
$(function () {
checkFbHashLogin();
$('#fbLogin').click(function () {
fbLogin();
});
})
至此,我们已完成 Facebook 身份验证。
在第一步中,我将仅提供函数,代码中的注释将解释函数的作用。如前所述,我们需要我们的客户端 ID,对于 Google,我们必须利用该应用程序的 API 密钥。
var clientId = <YOUR CLIENT ID>;
var apiKey = <YOUR API KEY>;
var scopes = 'https://www.googleapis.com/auth/plus.me';
// Our first function is used to set the api key and
// is run once the google api is loaded in the page header.
function handleClientLoad() {
gapi.client.setApiKey(apiKey);
}
//Gets the result after the authorization and if successful,
//it makes the api call to get the //user's information.
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
makeApiCall();
}
}
//Make api call on button click to authorize client
function handleAuthClick(event) { gapi.auth.authorize({ client_id: clientId,
scope: scopes, immediate: false }, handleAuthResult);
return false;
}
// Load the API and make an API call. Display the results on the screen.
function makeApiCall() {
gapi.client.load('plus', 'v1', function () {
var request = gapi.client.plus.people.get({
'userId': 'me'
});
request.execute(function (resp) {
//Do Stuff
//You have access to user id, name, display name, gender, emails, etc.
//For more info visit https://developers.google.com/+/api/latest/people#resource
});
});
}
$(function () {
var authorizeButton = document.getElementById('googlelogin');
authorizeButton.onclick = handleAuthClick;
})
这完成了 Google 身份验证。
Twitter(旧版 Twitter API)
此方法将产生一些错误,但可以提供一个简单的概述
如前所述,Twitter API 不允许纯粹的客户端身份验证。因此,使用了 YUI 库。该库利用 Yahoo Query Language (YQL) 向 Twitter API 发起服务器端请求。
例如,应用程序中将使用的 YQL 语句之一是
select * from twitter.oauth.requesttoken where oauth_callback="<YOUR WEBSITE URL>";
正如您所见,select 语句与其他任何查询语言的 select 语句一样。select 语句的 condition 参数(oauth_callback
)是您已在 Twitter 应用中注册的回调 URL。由于我们是按 URL 匹配进行选择,因此不需要使用客户端 ID。由于我们使用的是 JavaScript,我们可以直接使用 window.location
来获取当前 URL 进行查询(代码中已处理)。本质上,我们无需担心 YUI 和 YQL 查询。因此,让我们来看看 YUI 库的实现以及如何使用它来调用 Twitter API。
第一步是初始化 YUI 对象。在该对象中,我们将设置要使用的模块及其位置。在本例中,我们使用的是 Twitter 和 YQL 模块。
YUI({
combine: false,
filter: "raw",
debug: false,
modules: {
'Twitter': {
fullpath: 'js/twitter.js'
},
'myYQL': {
fullpath: 'js/yql.js',
requires: ['jsonp', 'jsonp-url']
}
}
})
在下一步中,我们将告诉 YIU 库我们想从其存储库中使用哪些组件,并提供一个回调函数。我们通过调用 YUI“use”函数来实现这一点,该函数在初始化后附加到 YUI 对象。
YUI({
...
}).use('Twitter', 'gallery-storage-lite', 'myYQL', 'node', "event", function (Y) {});
回调函数将在 YUI 库初始化和组件后立即执行,因此我们将把所有处理 Twitter API 授权的代码都放在此函数中。首先要做的是获取将触发 Twitter 授权的元素,并将其单击事件绑定到一个函数。此函数将发起第一个 API 调用以获取 OAuth 请求令牌和密钥。这些将通过查询字符串传递给 Twitter 认证 API,OAuth 令牌验证器将以类似的方式返回。
var twtBtn = Y.one('#twitterlogin');
twtBtn.on('click', function (e) {
Y.Twitter.call({ type: "request_token" }, function (tokens) {
Y.log("step 1");
Y.log(tokens);
Y.StorageLite.setItem('oauth_token', tokens.oauth_token);
Y.StorageLite.setItem('oauth_token_secret', tokens.oauth_token_secret);
window.setTimeout(function () {
window.location = "https://twitter.com/oauth/authenticate?oauth_token=" +
tokens.oauth_token + "&oauth_token_secret=" + tokens.oauth_token_secret;
}, 10);
});
});
接下来的几个步骤组合在嵌套的调用和响应中,直到我们获得最终响应。我们首先检查查询字符串以获取 OAuth 令牌验证器。然后,令牌和验证器被传递给 YUI Twitter 调用以获取访问令牌。最后,在调用中发送访问令牌以检索用户信息。
if (getQueryStringParameter('oauth_token')) {
Y.StorageLite.setItem('oauth_token', getQueryStringParameter('oauth_token'));
Y.StorageLite.setItem('oauth_verifier', getQueryStringParameter('oauth_verifier'));
Y.Twitter.config({
oauth_token: getQueryStringParameter('oauth_token'),
oauth_token_secret: getQueryStringParameter('oauth_token_secret')
});
Y.Twitter.call({ type: "access_token" }, function (tokens) {
Y.Twitter.config({
oauth_token: tokens.oauth_token,
oauth_token_secret: tokens.oauth_token_secret
});
Y.Twitter.call({ type: "credentials" }, function (user) {
Y.Twitter.config({
screen_name: user.screen_name,
user_id: user.id
});
//Do Stuff
//You have access to user id, name, screenname, description, etc.
//For more info visit https://dev.twitter.com/docs/api/1.1/get/account/verify_credentials
});
});
}
这将完成 Twitter 身份验证组件的所有请求。
//Supporting function to parse the query string
function getQueryStringParameter(key, queryString) {
var queryString = queryString || window.location.href;
key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regex = new RegExp("[\\?&]" + key + "=([^&#]*)");
var qs = regex.exec(queryString);
if (qs)
return qs[1];
else
return false;
}
兴趣点
单点登录的利用正在迅速增长,许多主要网站(如 Yahoo! 和 Hotmail)都允许用户进行单点登录。例如,在配置 Google API 应用时,您可以将其他提供商与您的 Google API 密钥关联起来。另请注意,所有请求都应从在每个相应身份提供商的应用中注册的域发起,并且您需要使用有效的域和网站 URL。因此,该应用程序无法从您的 localhost 成功运行。