Используйте токен, полученный от клиента JavaScript, для создания социальной связи на сервере.

У меня есть веб-страница, использующая PHP/JavaScript, которая может успешно выполнить процесс входа в Google на стороне клиента. Затем я хотел бы перенаправить полученный токен на серверную часть, которая использует Spring-Social для создания социальной связи и иметь возможность вызывать API-интерфейсы, для которых приложение было авторизовано. Мне удалось сделать именно это с Facebook (OAUTH2) и Twitter (OAUTH1), которые работают безупречно, но для Google я всегда получаю ответ 401 при попытке создать соединение. Код на сервере такой:

AccessGrant accessGrant = new AccessGrant(accessToken);
connection = ((OAuth2ConnectionFactory<?>) connectionFactory).createConnection(accessGrant);

Код в клиенте примерно такой:

    function onSignIn(googleUser) {
        var profile = googleUser.getBasicProfile();
        console.log('ID: ' + profile.getId());
        console.log('Name: ' + profile.getName());
        console.log('Email: ' + profile.getEmail());

        var access_token = googleUser.getAuthResponse().id_token;
        var xhr = new XMLHttpRequest();
        xhr.open('POST', 'http://localhost/signin/google');
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.onload = function() {
            console.log('Signed in as: ' + xhr.responseText);
            console.log('access_token=' + access_token);
        };
        xhr.send('access_token=' + access_token);

    }

Большая часть последнего скопирована из документации Google о том, как пройти аутентификацию на внутреннем сервере, которую можно найти здесь: https://developers.google.com/identity/sign-in/web/backend-auth

Я проследил вызовы внутри spring-social-google, и они привели к вызову REST к https://www.googleapis.com/oauth2/v2/userinfo, который отвечает 401 и следующий JSON:

{
    "error": {
        "errors": [{
            "domain": "global",
            "reason": "authError",
            "message": "Invalid Credentials",
            "locationType": "header",
            "location": "Authorization"
        }],
        "code": 401,
        "message": "Invalid Credentials"
    }
}

Я сам пытался вызвать этот же REST API, и я также получаю тот же ответ, так что это не похоже на то, что spring-social-google не отправляет токен должным образом, как я читал в некоторых других сообщениях.

Я считаю, что проблема как-то связана с тем фактом, что API JavaScript дает мне «id_token», а API REST ожидает «access_token». Однако я не нахожу способа получить токен доступа как нечто отдельное от id_token, и документация Google действительно отправляет id_token в серверную часть. Существует свойство «access_token» наряду с используемым свойством «id_token» в googleUser.getAuthResponse(), но оно возвращается неопределенным. Этот документ, конечно, не предназначен для весенних социальных сетей, поэтому я не говорю, что он неверен, мне просто интересно, как этого добиться.

Виноват ли spring-social в том, что не может справиться с id_token?

Я виноват, что не вижу ясного способа получить access_token?

Во всяком случае, я чувствую, что я как-то близок, но все же решение кажется далеким от понимания.

Благодарю вас!


person Julian Chennales    schedule 31.05.2018    source источник


Ответы (1)


Ну, я нашел это. Кажется, что запись всего этого действительно что-то отключило в моем мозгу...

Проблема в том, что id_token не может заменить access_token. На мой взгляд, документация Google могла бы быть немного более подробной об этом в примере, который они показывают, но в конечном итоге они объясняют это в реальной ссылке на клиента по адресу https://developers.google.com/identity/sign

Ключ является логическим параметром для getAuthResponse(), который является необязательным и по умолчанию равен false. Из документа:

includeAuthorizationData Необязательный: логическое значение, указывающее, следует ли всегда возвращать маркер доступа и области действия. По умолчанию маркер доступа и запрошенные области не возвращаются, если fetch_basic_profile имеет значение true (значение по умолчанию) и дополнительные области не запрашиваются.

Установив значение true в моем JS, поле access_token, которое ранее не было определено, было заполнено, и с помощью этого токена можно получить доступ к конечной точке /oauth2/v2/userinfo, а spring-social-google может правильно создать соединение, как и другие провайдеры.

Я надеюсь, что это поможет кому-то еще по крайней мере.

person Julian Chennales    schedule 01.06.2018