Как отправить данные GitHub OAuth клиенту? - PullRequest
0 голосов
/ 07 февраля 2019

Мне нужно реализовать авторизацию на github, а затем отправлять полученные данные (JSON) клиенту.

Я нашел этот урок http://shiya.io/how-to-do-3-legged-oauth-with-github-a-general-guide-by-example-with-node-js/

В этом уроке разработчик показывает нам так: "/" -> "/ login" -> "/ redirect" -> "/ user" (данные здесь)

Но мне нужно: "/" -> "/ login" -> "/ redirect" -> "/" (данные здесь)

Поскольку клиент должен использовать простое SPA (реагировать).

Что у меня сейчас:


    require('dotenv').config();
    const express = require('express');
    const app = express();
    const session = require('express-session');
    const request = require('request');
    const qs = require('querystring');
    const url = require('url');
    const randomString = require('randomstring');
    const csrfString = randomString.generate();

    const port = process.env.PORT || 8080;
    const redirect_uri = process.env.HOST + '/redirect';

    app.use(express.static('views'));

    app.use(
      session({
        secret: randomString.generate(),
        cookie: { maxAge: 60000 },
        resave: false,
        saveUninitialized: false
      })
    );

    app.get('/', (req, res, next) => {
      res.sendFile(__dirname + '/index.html');
      if (req.session.access_token) {
        request.get(
          {
            url: 'https://api.github.com/user',
            headers: {
              Authorization: 'token ' + req.session.access_token,
              'User-Agent': 'Login-App'
            }
          },
          (error, response, body) => {
            res.send(body);
          }
        );
      }
    });

    app.listen(port, () => {
      console.log('Server listening at port ' + port);
    });

    app.get('/login', (req, res, next) => {
    req.session.csrf_string = randomString.generate();
    const githubAuthUrl =
      'https://github.com/login/oauth/authorize?' +
      qs.stringify({
        client_id: process.env.CLIENT_ID,
        redirect_uri: redirect_uri,
        state: req.session.csrf_string,
        scope: 'user:email'
      });
    res.redirect(githubAuthUrl);
    });

    app.all('/redirect', (req, res) => {
      console.log('Request sent by GitHub: ');
      console.log(req.query);

      const code = req.query.code;
      const returnedState = req.query.state;

      if (req.session.csrf_string === returnedState) {
        request.post(
          {
            url:
              'https://github.com/login/oauth/access_token?' +
              qs.stringify({
                client_id: process.env.CLIENT_ID,
                client_secret: process.env.CLIENT_SECRET,
                code: code,
                redirect_uri: redirect_uri,
                state: req.session.csrf_string
              })
          },
          (error, response, body) => {
            console.log('Your Access Token: ');
            console.log(qs.parse(body));
            req.session.access_token = qs.parse(body).access_token;

            res.redirect('/');
          }
        );
      } else {
        res.redirect('/');
      }
      console.log(redirect_uri);
    });

В этот момент res.send (body);выдает ошибку


    app.get('/', (req, res, next) => {
      res.sendFile(__dirname + '/index.html');
      if (req.session.access_token) {
        request.get(
          {
            url: 'https://api.github.com/user',
            headers: {
              Authorization: 'token ' + req.session.access_token,
              'User-Agent': 'Login-App'
            }
          },
          (error, response, body) => {
            res.send(body);
          }
        );
      }
    });

Ошибка:

    throw new ERR_HTTP_HEADERS_SENT('set');
    ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

Это происходит потому, что я пытаюсь установить данные для рендеринга после рендеринга.

Итак, мой вопрос:

Как я могу отправить данные клиенту и как получить их на стороне клиента?

1 Ответ

0 голосов
/ 08 февраля 2019

HTTP использует цикл, который требует один ответ на запрос.Когда клиент отправляет запрос, сервер должен отправить клиенту только один ответ.

Вы отправляете два ответа res.sendFile() & res.send() на один запрос, поэтому ваш код необходимо изменить следующим образом:

app.get('/', (req, res, next) => {
    if (req.session.access_token) {
        request.get({
            url: 'https://api.github.com/user',
            headers: { Authorization: 'token ' + req.session.access_token, 'User-Agent': 'Login-App' }
        }, (error, response, body) => { res.send(body); }
        );
    } else {
        res.sendFile(__dirname + '/index.html');
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...