Социальная аутентификация в GraphQL - PullRequest
0 голосов
/ 02 мая 2019

Я создаю серверную часть, основанную на Express и GraphQL, которая будет обслуживать клиентские приложения (android и реагировать).

Я следил за этой статьей о том, как использовать социальную аутентификацию в GraphQL, используя passport.js .

В статье используется стратегия passport-google-token , основанная на Apollo-сервере, но лично я предпочитаю использовать express-graphql .

После настройки моего приложения для Android на использование Google Auth и попытки отправить мутацию на сервер я получаю эту ошибку

Google info:  { InternalOAuthError: failed to fetch user profile
    at E:\_Projects\myProject\myProject-backend\node_modules\passport-google-token\lib\passport-google-token\strategy.js:114:28
    at passBackControl (E:\_Projects\myProject\myProject-backend\node_modules\oauth\lib\oauth2.js:132:9)
    at IncomingMessage.<anonymous> (E:\_Projects\myProject\myProject-backend\node_modules\oauth\lib\oauth2.js:157:7)
    at IncomingMessage.emit (events.js:194:15)
    at endReadableNT (_stream_readable.js:1125:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)
    name: 'InternalOAuthError',
        message: 'failed to fetch user profile',
        oauthError:
    { statusCode: 401,
        data:
        '{\n  "error": {\n    "code": 401,\n    "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",\n    "status": "UNAUTHENTICATED"\n  }\n}\n' } }

Я полагаю, что токен, который я передаю, может не достигнуть того, что предполагалось, но я не могу понять, как решить.

Я протестировал токен здесь https://oauth2.googleapis.com/tokeninfo?id_token=MyToken, и они работают правильно.

Вот конфигурация graphQL в app.js

app.use('/graphql', graphqlHTTP((req, res) => ({
    schema,
    graphiql: true,
    context: {req, res}
})));

Вот мутация Google Auth

        googleAuth: {
            type: authPayLoad,
            args: {token: {type: new GraphQLNonNull(GraphQLString)}},
            async resolve(_, {token}, {req, res}) {
                req.body = {
                    ...req.body,
                    access_token: token,
                };

                try {
                    const {data, info} = await authenticateGoogle(req, res);
                    console.log("Google data: ", data);

                    if (data) {
                        const user = await User.upsertGoogleUser(data);

                        if (user) {
                            return ({
                                name: user.name,
                                username: user.username,
                                token: user.generateJWT(),
                            });
                        }
                    }

                    if (info) {
                        console.log("Google info: ", info);

                        switch (info.code) {
                            case 'ETIMEDOUT':
                                return (new Error('Failed to reach Google: Try Again'));
                            default:
                                return (new Error('something went wrong'));
                        }
                    }
                    return (Error('server error'));

                } catch (e) {
                    console.log("Error: ", e);
                    return e
                }
            },
        },

А вот и мой контроллер авторизации

const passport = require('passport');
const {Strategy: GoogleTokenStrategy} = require('passport-google-token');

// GOOGLE STRATEGY
const GoogleTokenStrategyCallback = (accessToken, refreshToken, profile, done) => done(null, {
    accessToken,
    refreshToken,
    profile,
});

passport.use(new GoogleTokenStrategy({
    clientID: 'MY_CLIET_ID',
    clientSecret: 'SERVER-SECRET'
}, GoogleTokenStrategyCallback));

module.exports.authenticateGoogle = (req, res) => new Promise((resolve, reject) => {
    passport.authenticate('google-token', {session: false}, (err, data, info) => {
        if (err) reject(err);
        resolve({data, info});
    })(req, res);
});

Я ожидал, когда клиентское приложение отправит мутацию с токеном в виде аргумента. Запрос будет отправлен в Google и вернет данные пользователя. Как мне это решить.

1 Ответ

1 голос
/ 05 мая 2019

passport-google-token заархивирован и кажется мне устаревшим. Почему бы вам не попробовать passport-token-google . Может использоваться аналогичным образом.

passport.use(new GoogleStrategy({
        clientID: keys.google.oauthClientID,
        clientSecret: keys.google.oauthClientSecret
    },
    function (accessToken, refreshToken, profile, done) {
        return done(null, {
            accessToken,
            refreshToken,
            profile,
        });
    }
));

module.exports.authenticate = (req, res) => new Promise((resolve, reject) => {
    passport.authenticate('google-token', {session: false}, (err, data, info) => {
        if (err) reject(err);
        resolve({data, info});
    })(req, res);
});

Надеюсь, это поможет.

...