将Google OAuth2.0的login电子邮件限制为特定域名

我似乎无法find任何有关如何限制login到我的Web应用程序(使用OAuth2.0和Google API)的文档,只接受来自用户的具有特定域名或域名集的电子邮件的身份validation请求。 我想白名单,而不是黑名单。

有没有人有关于如何做到这一点的build议,正式接受的方法的文件,或者一个简单,安全的解决方法?

为了logging,我不知道有关用户的任何信息,直到他们尝试通过Google的OAuth身份validationlogin。 我所收到的只是基本的用户信息和电子邮件。

所以我有一个答案给你。 在oauth请求中,您可以添加“hd = domain.com”,它将限制身份validation给来自该域的用户(我不知道您是否可以执行多个域)。 你可以在这里findhd参数

我从这里使用谷歌API图书馆: http : //code.google.com/p/google-api-php-client/wiki/OAuth2所以我不得不手动编辑/auth/apiOAuth2.php文件到这:

public function createAuthUrl($scope) { $params = array( 'response_type=code', 'redirect_uri=' . urlencode($this->redirectUri), 'client_id=' . urlencode($this->clientId), 'scope=' . urlencode($scope), 'access_type=' . urlencode($this->accessType), 'approval_prompt=' . urlencode($this->approvalPrompt), 'hd=domain.com' ); if (isset($this->state)) { $params[] = 'state=' . urlencode($this->state); } $params = implode('&', $params); return self::OAUTH2_AUTH_URL . "?$params"; } 

编辑:我仍然在这个应用程序工作,发现这可能是更正确的答案这个问题。 https://developers.google.com/google-apps/profiles/

在定义你的提供者时,最后用“hd”参数传入一个散列。 你可以在这里阅读。 https://developers.google.com/accounts/docs/OpenIDConnect#hd-param

例如,对于config / initializers / devise.rb

 config.omniauth :google_oauth2, 'identifier', 'key', {hd: 'yourdomain.com'} 

以下是我在node.js中使用passport的方法 profile是用户尝试login。

 //passed, stringified email login var emailString = String(profile.emails[0].value); //the domain you want to whitelist var yourDomain = '@google.com'; //check the x amount of characters including and after @ symbol of passed user login. //This means '@google.com' must be the final set of characters in the attempted login var domain = emailString.substr(emailString.length - yourDomain.length); //I send the user back to the login screen if domain does not match if (domain != yourDomain) return done(err); 

然后创build逻辑来查找多个域,而不是一个。 我相信这种方法是安全的,因为1. @符号不是电子邮件地址的第一部分或第2部分中的有效字符。 我无法通过创build一个像mike@fake@google.com这样的电子邮件地址来欺骗这个函数。2.在传统的login系统中,我可以,但是这个电子邮件地址在Google中是不存在的。 如果这不是有效的Google帐户,则无法login。

客户端:

使用auth2 init函数,您可以传递hosted_domain参数,以将loginpopup窗口中列出的帐户限制为与hosted_domain相匹配的hosted_domain 。 你可以在这里看到这个文档: https : //developers.google.com/identity/sign-in/web/reference

服务器端:

即使客户端列表受限,您也需要validationid_token与您指定的托pipe域名相匹配。 对于某些实现,这意味着在validation令牌之后检查您从google接收到的hd属性。

全堆栈示例:

网站代码:

 gapi.load('auth2', function () { // init auth2 with your hosted_domain // only matching accounts will show up in the list or be accepted var auth2 = gapi.auth2.init({ client_id: "your-client-id.apps.googleusercontent.com", hosted_domain: 'your-special-domain.com' }); // setup your signin button auth2.attachClickHandler(yourButtonElement, {}); // when the current user changes auth2.currentUser.listen(function (user) { // if the user is signed in if (user && user.isSignedIn()) { // validate the token on your server, // your server will need to double check that the // `hd` matches your specified `hosted_domain`; validateTokenOnYourServer(user.getAuthResponse().id_token) .then(function () { console.log('yay'); }) .catch(function (err) { auth2.then(function() { auth2.signOut(); }); }); } }); }); 

服务器代码(使用Google Node.js库):

如果您不使用Node.js,可以在这里查看其他示例: https : //developers.google.com/identity/sign-in/web/backend-auth

 const GoogleAuth = require('google-auth-library'); const Auth = new GoogleAuth(); const authData = JSON.parse(fs.readFileSync(your_auth_creds_json_file)); const oauth = new Auth.OAuth2(authData.web.client_id, authData.web.client_secret); const acceptableISSs = new Set( ['accounts.google.com', 'https://accounts.google.com'] ); const validateToken = (token) => { return new Promise((resolve, reject) => { if (!token) { reject(); } oauth.verifyIdToken(token, null, (err, ticket) => { if (err) { return reject(err); } const payload = ticket.getPayload(); const tokenIsOK = payload && payload.aud === authData.web.client_id && new Date(payload.exp * 1000) > new Date() && acceptableISSs.has(payload.iss) && payload.hd === 'your-special-domain.com'; return tokenIsOK ? resolve() : reject(); }); }); };