web-dev-qa-db-fra.com

Restreindre l'adresse e-mail de connexion avec Google OAuth2.0 à un nom de domaine spécifique

Je n'arrive pas à trouver de documentation sur la façon de restreindre la connexion à mon application Web (qui utilise OAuth2.0 et les API Google) pour n'accepter que les demandes d'authentification des utilisateurs avec un courrier électronique sur un nom de domaine spécifique ou un ensemble de noms de domaines. Je voudrais ajouter à la liste blanche plutôt qu’à la liste noire.

Quelqu'un a-t-il des suggestions sur la manière de procéder, une documentation sur la méthode officiellement acceptée, ou une solution de contournement simple et sécurisée?

Pour mémoire, je ne connais aucune information sur l'utilisateur jusqu'à ce qu'il tente de se connecter via l'authentification OAuth de Google. Tout ce que je reçois, ce sont les informations utilisateur de base et le courrier électronique.

78
paradox870

J'ai donc une réponse pour vous. Dans la requête oauth, vous pouvez ajouter "hd = domain.com" et limitera l'authentification aux utilisateurs de ce domaine (je ne sais pas si vous pouvez créer plusieurs domaines). Vous pouvez trouver le paramètre hd documenté ici

J'utilise les bibliothèques api de Google à partir d'ici: http://code.google.com/p/google-api-php-client/wiki/OAuth2 j'ai donc dû modifier manuellement le fichier/auth/apiOAuth2. fichier php à ceci:

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 a trouvé ceci, qui peut être la réponse la plus correcte à cette question. https://developers.google.com/google-apps/profiles/

40
Aaron Bruce

Lorsque vous définissez votre fournisseur, transmettez un hachage à la fin avec le paramètre 'hd'. Vous pouvez lire à ce sujet 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'}
9
Kosmonaut

Côté client:

À l'aide de la fonction auth2 init, vous pouvez passer le paramètre hosted_domain pour limiter les comptes répertoriés dans la fenêtre de connexion à ceux correspondant à votre hosted_domain. Vous pouvez le voir dans la documentation ici: https://developers.google.com/identity/sign-in/web/reference

Du côté serveur:

Même avec une liste restreinte côté client, vous devrez 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 jeton.

Exemple de pile complète:

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 serveur (utilisant la bibliothèque googles Node.js):

Si vous n'utilisez pas Node.js, 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();
        });
    });
};
3
Jordon Biondo

Voici ce que j'ai fait en utilisant passport dans 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);

Il suffit ensuite de créer une logique pour rechercher plusieurs domaines au lieu d’un seul. Je crois que cette méthode est sécurisée parce que 1. le symbole '@' n'est pas un caractère valide dans la première ou la deuxième partie d'une adresse email. Je ne pouvais pas tromper la fonction en créant une adresse e-mail telle que mike@[email protected] 2. Je pouvais utiliser un système de connexion traditionnel, mais cette adresse e-mail n'existerait jamais dans Google. Si ce n'est pas un compte Google valide, vous ne pouvez pas vous connecter.

2
mjoyce91

Depuis 2015, il y a une fonction dans la bibliothèque pour la définir sans avoir à modifier le source de la bibliothèque comme dans le workaround de aaron-bruce

Avant de générer l'URL, appelez simplement setHostedDomain contre votre client Google.

$client->setHostedDomain("HOSTED DOMAIN")
0
JBithell