Restreindre le courriel de connexion avec Google OAuth2.0 à un nom de domaine spécifique

il semble que je ne trouve aucune documentation sur la façon de restreindre le login à mon application web (qui utilise OAuth2.0 et Google APIs) pour n'accepter que les demandes d'authentification des utilisateurs avec un e-mail sur un nom de domaine spécifique ou un ensemble de noms de domaine. Je voudrais faire une liste blanche par opposition à une liste noire.

est-ce que quelqu'un a des suggestions sur la façon de le faire, de la documentation sur la méthode officiellement acceptée pour le faire, ou un travail facile et sûr autour?

pour information, Je ne sais pas d'information sur l'utilisateur jusqu'à ce qu'ils tentent de se connecter par l'authentification OAuth de Google. Tout ce que je reçois en retour est l'information de base de l'utilisateur et le courrier électronique.

70
demandé sur Miguel Andres 2012-06-02 04:16:05

4 réponses

Donc j'ai une réponse pour vous. Dans la requête oauth vous pouvez ajouter "hd=domain.com" et il va restreindre l'authentification aux utilisateurs de ce domaine (je ne sais pas si vous pouvez faire plusieurs domaines). Vous pouvez trouver le paramètre hd documenté ici

j'utilise les bibliothèques api google d'ici: http://code.google.com/p/google-api-php-client/wiki/OAuth2 donc j'ai dû éditer manuellement le /auth/apiOAuth2.fichier php à ce:

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";
}

Edit: Je travaille toujours sur cette application et j'ai trouvé ceci, qui pourrait être la réponse la plus correcte à cette question. https://developers.google.com/google-apps/profiles /

37
répondu Aaron Bruce 2014-08-18 12:35:15

lors de la définition de votre fournisseur, passez dans un hachage à la fin avec le paramètre 'hd'. Vous pouvez lire ici. https://developers.google.com/accounts/docs/OpenIDConnect#hd-param

par exemple, pour config/initializers / devise.rb

config.omniauth :google_oauth2, 'identifier', 'key', {hd: 'yourdomain.com'}
8
répondu Kosmonaut 2014-12-13 02:59:20

voilà ce que j'ai fait en utilisant passport in node.js. profile est l'utilisateur qui tente de se connecter.

//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);

alors créez juste de la logique pour chercher plusieurs domaines au lieu d'un seul. Je crois que cette méthode est sûre parce que 1. le symbole " @ " n'est pas un caractère valide dans la première ou la deuxième partie d'une adresse courriel. Je ne pouvais pas tromper la fonction en créant une adresse email comme mike@fake@google.com 2. Dans un système de connexion traditionnel je pourrais, mais cette adresse e-mail ne pourrait jamais exister dans Google. Si ce n'est pas un compte Google valide, Vous ne pouvez pas vous connecter.

2
répondu mjoyce91 2016-01-09 16:58:59

Côté Client:

en utilisant la fonction init auth2 , vous pouvez passer le paramètre hosted_domain pour restreindre les comptes énumérés dans le popup de connexion à ceux correspondant à votre hosted_domain . Vous pouvez le voir dans la documentation ici: https://developers.google.com/identity/sign-in/web/reference

Côté Serveur:

même avec une liste restreinte côté client, vous aurez besoin de vérifier que le id_token correspond au domaine hébergé que vous avez spécifié. Pour certaines implémentations, cela signifie vérifier l'attribut hd que vous recevez de google après avoir vérifié le token.

Full Stack Example:

Code Web:

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(); });
                });
        }
    });
});

Code du Serveur (à l'aide de lunettes de Nœud.bibliothèque js):

si vous n'utilisez pas Node.vous pouvez voir d'autres exemples ici: 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();
        });
    });
};
2
répondu Jordon Biondo 2016-11-02 18:19:35