Ограничить адрес электронной почты для входа с Google OAuth2.0 определенным доменным именем

Кажется, я не могу найти никакой документации о том, как ограничить вход в мое веб-приложение (которое использует OAuth2.0 и API Google), чтобы принимать запросы аутентификации только от пользователей с электронной почтой на определенном доменном имени или наборе доменных имен. Я хотел бы внести в белый список, а не в черный список.

Есть ли у кого-нибудь предложения о том, как это сделать, есть документация по официально принятому методу или простой и безопасный способ решения проблемы?

Для записи, я не знаю никакой информации о пользователе, пока он не попытается войти в систему через аутентификацию Google OAuth. Все, что я получаю в ответ, - это основная информация о пользователе и электронная почта.


person paradox870    schedule 02.06.2012    source источник
comment
Я тоже исследую это. У меня есть приложение, к которому я хочу, чтобы к нему могли обращаться только люди, у которых есть учетная запись в наших приложениях Google для бизнеса. Реализация Google OpenID может быть более подходящей для нас обоих ...   -  person Aaron Bruce    schedule 09.06.2012
comment
Как я могу реализовать вход пользователя домена с помощью google sdk и c #?   -  person user1021583    schedule 23.07.2015
comment
Кто-нибудь может взглянуть на этот вопрос stackoverflow.com/questions/34220051/   -  person    schedule 15.12.2015
comment
Пожалуйста, у меня есть награда за этот вопрос, так может ли кто-нибудь мне помочь?   -  person    schedule 15.12.2015


Ответы (5)


Итак, у меня есть для вас ответ. В запросе oauth вы можете добавить «hd = domain.com», и это ограничит аутентификацию для пользователей из этого домена (я не знаю, можете ли вы использовать несколько доменов). Вы можете найти задокументированный параметр hd здесь

Я использую библиотеки API Google отсюда: 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/

person Aaron Bruce    schedule 12.06.2012
comment
Мне не было известно об этом параметре, можете ли вы дать ссылку на то, где вы узнали об этом? - person Jason Hall; 12.06.2012
comment
К сожалению, мне пришлось получить информацию от моего коллеги, я не нашел ее нигде в документации Google. Мой коллега думает, что он нашел ссылку в спецификации OpenID, опробовал ее здесь, в спецификации OpenAuth, и, похоже, это сработало. Я полагаю, используйте с осторожностью, поскольку это, похоже, недокументированная функция. - person Aaron Bruce; 14.06.2012
comment
Важное примечание: даже если вы указываете параметр hd в функции createAuthUrl, вам все равно нужно будет убедиться, что пользователь входит в систему с адресом электронной почты вашего домена. Изменить параметр ссылки очень просто, чтобы разрешить все адреса электронной почты и впоследствии получить доступ к вашему приложению. - person VictorKilo; 08.02.2013
comment
Я сделал аналогичный взлом, чтобы установить loginHint (адрес электронной почты пользователя), который также, если он содержит размещенный домен, будет перенаправлять на вход SAML. К сожалению, я сначала не нашел эту ветку и не знал о параметре hd. stackoverflow.com/questions/19653680/ - person HdN8; 12.05.2014
comment
Параметр hd для меня абсолютно ничего не делает. - person Tyguy7; 26.11.2015
comment
HD работал некоторое время, но внезапно остановился, так что есть другое решение - person ; 12.12.2015
comment
Хм, я не знаю об этом. Я больше не работаю над приложениями, которые используют эту функцию, поэтому мне не пришлось вникать в нее. Это может потребовать нового вопроса о SO, поскольку этот ответ кажется устаревшим и неправильным. - person Aaron Bruce; 14.12.2015
comment
Документацию Google по использованию параметра hd см. На странице developers.google.com/identity/work/ it-apps И ссылку на параметр hd URI можно найти разработчиками. google.com/identity/protocols/ В кратком изложении параметр hd следует рассматривать как фильтр отображения на основе домена для стороны Google Auth, но он все равно должен проверяться на вашей стороне. - person Will B.; 06.04.2016
comment
Отлично! В настоящее время в параметре hd я могу ограничить только один домен. Что делать, если я хочу ограничить два или три домена? - person Jay Patel; 18.10.2018
comment
Ответ @JBithell также работает хорошо ... если вы используете библиотеку PHP, просто используйте $ client- ›setHostedDomain ('yourdomain.com') - person cwd; 08.05.2020

Сторона клиента:

Используя функцию auth2 init, вы можете передать параметр hosted_domain, чтобы ограничить учетные записи, перечисленные во всплывающем окне входа, теми, которые соответствуют вашему hosted_domain. Вы можете увидеть это в документации здесь: https://developers.google.com/identity/sign-in/web/reference

На стороне сервера:

Даже с ограниченным списком на стороне клиента вам нужно будет убедиться, что id_token соответствует указанному размещенному домену. Для некоторых реализаций это означает проверку атрибута hd, который вы получаете от Google после проверки токена.

Пример полного стека:

Веб-код:

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

Код сервера (с использованием библиотеки googles 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();
        });
    });
};
person Jordon Biondo    schedule 02.11.2016

При определении вашего провайдера передайте хэш в конце с параметром hd. Вы можете прочитать об этом здесь. https://developers.google.com/accounts/docs/OpenIDConnect#hd-param

Например, для config / initializers / devise.rb

config.omniauth :google_oauth2, 'identifier', 'key', {hd: 'yourdomain.com'}
person Kosmonaut    schedule 13.12.2014
comment
Это можно легко обойти, предоставив доступ для входа в систему с другими доменами. Это будет работать только для ограничения доступных учетных записей, отображаемых пользователю. - person homaxto; 14.01.2016

Вот что я сделал с помощью паспорта в node.js. profile - это пользователь, пытающийся войти в систему.

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

Затем просто создайте логику для поиска нескольких доменов вместо одного. Я считаю, что этот метод безопасен, потому что 1. символ «@» не является допустимым символом в первой или второй части адреса электронной почты. Я не мог обмануть эту функцию, создав адрес электронной почты типа mike@[email protected] 2. В традиционной системе входа я мог бы, но этот адрес электронной почты никогда не мог существовать в Google. Если это недействительная учетная запись Google, вы не сможете войти в систему.

person mjoyce91    schedule 09.01.2016

С 2015 года существует noreferrer в библиотеке, чтобы установить это без необходимости редактировать источник библиотеки, как в обходном пути от aaron -брюс

Перед созданием URL просто позвоните setHostedDomain своему клиенту Google.

$client->setHostedDomain("HOSTED DOMAIN")
person JBithell    schedule 03.01.2019