Github OAuth с Express и на стороне клиента с React / Redux - PullRequest
0 голосов
/ 28 апреля 2020

Я внедряю систему, которая позволит войти через Github. Я уже реализовал часть входа без Github, только с регистрацией пользователя, используя redux. Однако, если пользователь хочет войти в систему с помощью Github, серверная часть вернет то же, что и при обычном входе, то есть данные пользователя и токен JWT.

Но мне не удается присоединиться ко всем этим частей. Когда я нажимаю на ссылку для входа в систему с использованием учетной записи Github, он вызывает API, регистрирует данные клиента в базе данных и возвращает JSON с токеном JWT. Но после этого я бы хотел, чтобы он зашел на главную страницу, которая разрешена только для аутентифицированных пользователей, которым я управлял только при обычном входе в систему.

Ниже, как я делал обычный вход в систему, без аутентификации через Github

Действия

export function logInRequest(email, password) {
  return {
    type: '@auth/LOG_IN_REQUEST',
    payload: { email, password },
  };
}

export function logInSuccess(token, dev) {
  return {
    type: '@auth/LOG_IN_SUCCESS',
    payload: { token, dev },
  };
}

Редуктор

import produce from 'immer';

const INITIAL_STATE = {
  token: null,
  signed: false,
  loading: false,
};

export default function auth(state = INITIAL_STATE, action) {
  return produce(state, (draft) => {
    switch (action.type) {
      case '@auth/LOG_IN_REQUEST': {
        draft.loading = true;
        break;
      }
      case '@auth/LOG_IN_SUCCESS': {
        draft.token = action.payload.token;
        draft.signed = true;
        draft.loading = false;
        break;
      }
      case '@auth/SIGN_FAILURE': {
        draft.loading = false;
        break;
      }
      default:
    }
  });
}

Sagas

import { takeLatest, call, put, all } from 'redux-saga/effects';
import { toast } from 'react-toastify';

import history from '~/services/history';
import api from '~/services/api';

import { logInSuccess, signFailure } from './actions';

export function* logIn({ payload }) {
  try {
    const { email, password } = payload;

    const response = yield call(api.post, 'sessions', {
      email,
      password,
    });

    const { token, dev } = response.data;

    api.defaults.headers.Authorization = `Bearer ${token}`;

    yield put(logInSuccess(token, dev));

    history.push('/home');
  } catch (err) {
    toast.error('Authentication failed, check your Email and Password');
    yield put(signFailure());
  }
}

export function setToken({ payload }) {
  if (!payload) return;

  const { token } = payload.auth;

  if (token) {
    api.defaults.headers.Authorization = `Bearer ${token}`;
  }
}

export default all([
  takeLatest('persist/REHYDRATE', setToken),
  takeLatest('@auth/LOG_IN_REQUEST', logIn)),
]);

А ниже кнопка входа в систему с помощью github и метод API, который выполняет вызов Github (URL-адрес обратного вызова авторизации):

// import request from 'superagent';
import jwt from 'jsonwebtoken';

import Dev from '../models/Dev';

import { githubOAuth, githubAPI } from '../services/api';
import authConfig from '../../config/auth';

class SessionGithubController {
  async store(req, res) {
    const requestToken = req.query.code;

    /**
     * Logging into Github with OAuth.
     */
    const oauthResponse = await githubOAuth({
      method: 'POST',
      headers: {
        accept: 'application/json',
      },
      data: {
        client_id: process.env.CLIENT_ID,
        client_secret: process.env.CLIENT_SECRET,
        code: requestToken,
      },
    });

    /**
     * Using the access token to access the API.
     */
    const apiResponse = await githubAPI.get('/user', {
      headers: {
        // Include the token in the Authorization header
        Authorization: `token ${oauthResponse.data.access_token}`,
      },
    });

    const {
      name,
      login,
      email,
      company,
      bio,
      avatar_url,
      html_url,
    } = apiResponse.data;

    const dev = await Dev.findOne().or([{ email }, { github_username: login }]);

    const socialMedia = {
      github_url: html_url,
    };

    let result = {};

    if (dev) {
      const { _id } = dev;

      result = {
        dev: {
          _id,
          name: dev.name,
          email,
        },
        token: jwt.sign({ _id }, authConfig.secret, {
          expiresIn: authConfig.expiresIn,
        }),
      };
    } else {
      const { _id } = await Dev.create({
        name,
        email,
        github_username: login,
        company,
        bio,
        avatar_url,
        socialMedia,
        login_with_github: true,
      });

      result = {
        dev: {
          _id,
          name,
          email,
        },
        token: jwt.sign({ _id }, authConfig.secret, {
          expiresIn: authConfig.expiresIn,
        }),
      };
    }

    return res.json(result);
  }
}

export default new SessionGithubController();

Ниже изображений, содержащих возврат после запуска аутентификации

Кнопка для входа в систему с помощью Github

Возврат JSON после нажатия кнопки

Работает почти так, как я ожидаю, но мне нужно было бы войти домашняя страница аутентифицирована как обычные пользователи, которые входят в систему, если Github может.

Я благодарю всех за помощь.

...