Далее вы узнаете, как использовать библиотеку gapi для настройки аутентификации, как произвести вход пользователя, а также я покажу несколько сниппетов для обработки распространённых пользовательских сценариев. Поехали.

Создаём кнопку sign in

  1. Загружаем библиотеку api.js, а не platform.js (не знаю почему, но они разные)

Измените https://apis.google.com/js/platform.js на https://apis.google.com/js/api.js?onload=onLibraryLoaded

Здесь мы настраиваем Sign-In клиент после загрузки библиотеки с помощью обратного вызова ?onload=onLibraryLoaded, который можно будет передать через URL. api.js добавляет глобальную переменную gapi.

2. Добавьте кнопку в index.html с обработчиком нажатия кнопки

<button onclick="onSignInClicked()">Sign in with button onClick</button>

3. Добавьте этот код в тег script в index.html для обработки нажатия кнопки.

function onLibraryLoaded() {
    gapi.load('auth2', function() {
        gapi.auth2.init({
            client_id: 'YOUR_CLIENT_ID.apps.googleusercontent.com',
            scope: 'profile'
        })
    })
}

function onSignInClicked() {
    gapi.load('auth2', function() {
        gapi.auth2.signIn().then(function(googleUser) {
          console.log('user signed in')
        }, function(error) {
            console.log('user failed to sign in')
        })
    })
}

Теперь у нас есть доступ к библиотеке gapi.auth2, и мы можем инициализировать её из консоли, используя client_id.

Распространённые пользовательские сценарии

  • Ожидание, когда пользователь войдёт в систему;
  • проверка, вошёл ли пользователь в систему;
  • получение информации о пользователе;
  • разрешение на вход только из определенного домена;
  • разрешение на вход только определенным пользователям;
  • скрыть контент до тех пор, пока пользователь не войдёт в систему;
  • отправка ID-токена на сервер (если он у вас есть).

В приведённом выше примере мы можем запустить код только после инициализации и входа пользователя. Но что, если разные части страницы находятся в разных файлах, каждый из которых генерирует разный контент для разных пользователей? (так бывает, когда используют компоненты)

class UserAvatarComponent extends React.Component {
    ...
    componentDidMount() {
        gapi.load('auth2', function() {
            gapi.auth2.isSignedIn.listen(function(isSignedIn) {
                console.log('user signed in ', isSignedIn)
                this.setState({status: isSignedIn})
            })
        })
    }    
}

Проверяем, вошёл ли пользователь

function isUserSignedIn() {
  gapi.load('auth2', function() {
      var isSignedIn = auth2.isSignedIn.get();
      console.log('is signed in? ', isSigned In)
  })
}

Несколько моментов об использовании этой функции:

  • Библиотека Sign-In по умолчанию будет автоматически выполнять вход, если вы уже проходили аутентификацию.
  • Если вы обновите страницу даже после того, как пользователь войдет в систему, то при загрузке сначала вы получите сообщение auth2.isSignedIn.get() === false.
  • После того, как пользователь войдет в систему автоматически (обычно занимает секунды): auth2.isSignedIn.get() === true.
  • В зависимости от способа обработки пользовательского интерфейса, пользователь на мгновение может увидеть, что он не вошёл. Если хотите знать точный момент, когда это происходит, то используйте обратный вызов isSignedIn.listen().

Получаем информацию о пользователе

function showCurrentUserInfo() {
  gapi.load('auth2', function() {
      var googleUser = auth2.currentUser.get()
      console.log('users info ', googleUser)
  })
}

Разрешаем вход только из определенного домена

Можно использовать метод getHostedDomain(), чтобы получить G-Suite домен, из которого пришёл пользователь, хотя это легко обойти. Если домена G-Suite нет, то он будет пустым.

function onSignIn(googleUser) {
    if(googleUser.getHostedDomain() !== 'mysite.com') {
        // show a Not Authorized message
    } else {
        // show the users dashboard
    }
}

Разрешить вход только определенным пользователям

Ещё более грубый метод, но, по-моему, только это и можно сделать с javascript. Вообще так делать не стоит, включил это на всякий случай.

function onSignIn(googleUser) {
    var profile = googleUser.getBasicProfile()
    if(profile.getEmail() === '[email protected]' ||
       profile.getEmail() === '[email protected]') {
           // show the user dashboard
    } else {
        // show a Not Authorized message
    }
}

Скрыть контент до тех пор, пока пользователь не войдёт в систему

Это тоже легко обойти, если покопаться в CSS через браузер, но в некоторых случаях этого может хватить. Причина, по которой это не лучший вариант, заключается в том, что на статическом сайте вся информация, которая есть в HTML файле, доступна пользователю. Не используйте этот способ, если у вас хранится конфиденциальная информация. Этот способ хорош для галереи фотографий ваших любимых кошечек.

<body>
...
  <div id="greeting">
    You are not authorized to view this content
  </div>
  <div id="dashboard">
    ...
  </div>
  <script>
    // hide initially
    $('#dashboard').hide()
    
    function onSignIn(googleUser) {
      setTimeout(function() {
        // show the content
        $('#greeting').hide()
        $('#dashboard').show()
      }, 1000);
    }
  </script>
</body>

Отправка токена для идентификации пользователя (не его ID)

Если вы делаете бэкэнд запрос, то нужно отправить ID токен пользователя на свой сервер в качестве заголовка авторизации. На сервере вы сможете проверить и декодировать ID токен (примеры).

Преимущество этого подхода заключается в том, что этот ID токен (JWT токен) подписан Google, поэтому вы знаете, что информация не была подделана.

$.ajax({
  url: 'myapi/example',
  headers: {'Authorization': googleUser.getAuthResponse().id_token)},
})

Заключение

Мы разобрались с тем, как настроить Google библиотеку для аутентификации с помощью javascript. Можете использовать её для получения информации о пользователях и проверки входа в систему.

Демо доступно на Github intricatecloud/google-sign-in-demo. Замените YOUR_CLIENT_ID на свой client ID, и кнопка готова к использованию.

Читайте также:


Перевод статьи Danny Perez: Adding google sign-in to your webapp — using the js library

Предыдущая статьяJavaScript Symbols. Новый тип примитивов
Следующая статьяЛёгкое пополнение баз данных в приложениях платформы .NET