강백호같은개발자

구글 로그인 본문

카테고리 없음

구글 로그인

쨜리 2020. 9. 17. 11:27

클라이언트 - 회원가입

// signup.js

/* eslint-disable react/prop-types */
/* eslint-disable no-unused-vars */
import React from "react";
import { withRouter, Link, useHistory } from "react-router-dom";
import axios from "axios";

axios.defaults.withCredentials = true;
class Signup extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            email: '',
            password: '',
            username: '',
            mobile: ''
        };
        this.handleInputValue = this.handleInputValue.bind(this);
    }
    handleInputValue = key => e => {
        this.setState({ [key]: e.target.value });
    };

    handleOnConfirmPasswordInput(confirmPasswordInput) {
        this.setState({ confirmPassword: confirmPasswordInput });
    }

    doesPasswordMatch() {
        const { password, confirmPassword } = this.state;
        return password === confirmPassword;
    }

    confirmPasswordClassName() {
        const { confirmPassword } = this.state;

        if (confirmPassword) {
            return this.doesPasswordMatch() ? 'is-valid' : 'is-invalid';
        }
    }

    renderFeedbackMessage() {
        const { confirmPassword } = this.state;

        if (confirmPassword) {
            if (!this.doesPasswordMatch()) {
                return (
                    <div className="invalid-feedback">The password does not match</div>
                );
            }
        }
    }

    render() {
        const { email, password, mobile, username } = this.state;
        return (
            <div>
                <center className="loginBox">
                    <h1>Sign Up</h1>
                    <form
                        onSubmit={e => {
                            e.preventDefault();
                            axios
                                .post('/user/signup', this.state)
                                .then(res => {
                                    if (res.status === 409) {
                                        alert('계정이 이미 존재합니다')
                                        this.props.history.push('/')
                                    }
                                    else if (res.status === 200) {
                                        alert('가 입이 완료되었습니다^^')
                                        this.props.history.push('/login')
                                    }
                                })
                                .catch(err =>
                                    console.log(err)
                                );
                        }}
                    >
                        <link href="https://fonts.googleapis.com/css2?family=Courgette&family=Gloria+Hallelujah&display=swap" rel="stylesheet"></link>
                        <div>
                            <input className="inputForm"
                                placeholder="User Name"
                                onChange={this.handleInputValue('username')}
                            >
                            </input>
                        </div>

                        <div>
                            <input className="inputForm" type="email"
                                placeholder="Email"
                                onChange={this.handleInputValue('email')}>
                            </input>
                        </div>

                        <div>
                            <input className="inputForm"
                                type="password"
                                placeholder="Password"
                                onChange={this.handleInputValue('password')}>
                            </input>
                        </div>

                        <div >
                            <input
                                type="password"
                                className="inputForm"
                                id="confirmPasswordInput"
                                placeholder="Password Confirm"
                                onChange={e =>
                                    this.handleOnConfirmPasswordInput(e.target.value)
                                }
                            />
                            {this.renderFeedbackMessage()}
                        </div>
                        <button className="signupBtn" type="submit">
                            Signup
                        </button>
                    </form>
                </center>
            </div >
        );
    }
}

export default withRouter(Signup);

 

클라이언트 - 로그인

// login.js
/* eslint-disable react/prop-types */
import React from "react";
import { withRouter } from "react-router-dom";
import axios from "axios";
import Facebook from "./Facebook";

axios.defaults.withCredentials = true;

class Login extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      email: '',
      password: ''
    };

    this.handleInputValue = this.handleInputValue.bind(this);
  }

  handleInputValue = key => e => {
    this.setState({ [key]: e.target.value });
  };


  render() {
    const { email, password } = this.state;
    const { handleIsLoginChange } = this.props;

    return (
      <div className="loginBack">
        <center className="loginBox" >
          <link href="https://fonts.googleapis.com/css2?family=Courgette&display=swap" rel="stylesheet"></link>
          <h1>Login</h1>

          <form
            onSubmit={e => {
              e.preventDefault();
              return axios
                .post('/user/login', {
                  email: email,
                  password: password
                })
                .then((res) => {
                  localStorage.setItem('user', JSON.stringify(res.data.token));
                  handleIsLoginChange();
                  this.props.history.push('/mypage');
                })
                .catch(err => console.log(err));
            }}
          >

            <div>
              <input className="inputForm"
                type="email"
                placeholder="Eamil"
                onChange={this.handleInputValue('email')}>
              </input>
            </div>

            <div>
              <input className="inputForm"
                type="password"
                placeholder="Password"
                onChange={this.handleInputValue('password')}>
              </input>
            </div>
            <div>
              <button className="loginBtn" type="submit">
                Login
            </button>
            </div>
            <div id="snsLogin">
              <span className="fbLogin">
                <Facebook />
              </span>

              {/* 밑의 구글로그인 부분은 a태그로 무조건 감싸져야 합니다. -현진- */}
              <a href="http://3.34.193.46.xip.io:5000/auth/google" className="googleBtn">
                <img src="https://img.icons8.com/color/48/000000/google-logo.png" />Google with Login</a>
            </div>
          </form>
        </center>
      </div>
    );
  }
}

export default withRouter(Login);

 

 

백엔드-passport/

// google.js
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;

const { User } = require('../models');

module.exports = () => {
  console.log('여기');
  passport.use(new GoogleStrategy({
    clientID: process.env.GOOGLE_ID,
    clientSecret: process.env.GOOGLE_SECRET,
    callbackURL: '/auth/google/callback',
  }, async (accessToken, refreshToken, profile, done) => {
    console.log('kakao profile', profile);
    try {
      const exUser = await User.findOne({
        where: { email: profile._json.email, provider: 'google' },
      });
      if (exUser) {
        done(null, exUser);
      } else {
        console.log(profile._json.email,'=============')
        const newUser = await User.create({
          email: profile._json && profile._json.email,
          snsId: profile.id,
          provider: 'google',
          username: profile._json.name,
        });
        done(null, newUser);
      }
    } catch (error) {
      console.error(error);
      done(error);
    }
  }));
};
// index.js
const passport = require('passport');
const google = require('./google');
const { User } = require('../models');

module.exports = () => {
  passport.serializeUser((user, done) => { // 서버쪽에 [{ id: 1, cookie: 'clhxy' }]
    done(null, user.id);
  });

  passport.deserializeUser(async (id, done) => {
    try {
      const user = await User.findOne({ where: { id }});
      done(null, user); // req.user
    } catch (error) {
      console.error(error);
      done(error);
    }
  });

  google();
};

 

백엔드 - routes/auth.js

// auth.js
const express = require('express');
const router = express.Router();
const passport = require('passport');

router.get('/google',
  passport.authenticate('google', { scope: ['https://www.googleapis.com/auth/plus.login', 'email'], prompt: 'select_account' }));

router.get('/google/callback', (req, res, next) => {
  passport.authenticate('google', (authError, user,) => {
    
    req.session.userid = user.dataValues.email
    res.cookie('user', user.dataValues.username);
    res.redirect(`http://localhost:3000?data=${user.dataValues.email}`);
    req.login(user,(err) => {
      if(err) {
        res.status(404).send('구글로그인 에러');
      }
    })
  })(req, res, next)
})

module.exports = router;

백엔드 - package.json

{
  "name": "k-food-dictionary-server",
  "version": "1.0.0",
  "description": "<a href=\"https://gitmoji.carloscuesta.me\"> <img src=\"https://img.shields.io/badge/gitmoji-%20😜%20😍-FFDD67.svg?style=flat-square\" alt=\"Gitmoji?style=flat-square&logo=appveyor\"> </a> <a href=\"https://github.com/codestates/Saekgalpi-ColorPalette\"><img src =\"https://img.shields.io/badge/github-kFood-lightgrey?style=flat-square&logo=appveyor\"></a> <img src=\"https://img.shields.io/badge/npm-v6.14.4-important?style=flat-square&logo=appveyor\"> <img src=\"https://img.shields.io/badge/node.js-v12.16.11-important?style=flat-square&logo=appveyor\">",
  "main": "index.js",
  "scripts": {
    "dev": "nodemon app.js",
    "hjtest": "nodemon mytest.js"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/wmc15156/K-Food-Dictionary-server.git"
  },
  "author": "kfood",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/wmc15156/K-Food-Dictionary-server/issues"
  },
  "homepage": "https://github.com/wmc15156/K-Food-Dictionary-server#readme",
  "dependencies": {
    "aws-sdk": "^2.734.0",
    "connect-redis": "^5.0.0",
    "cookie-parser": "^1.4.5",
    "cors": "^2.8.5",
    "crypto-js": "^4.0.0",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "express-session": "^1.17.1",
    "jsonwebtoken": "^8.5.1",
    "morgan": "^1.10.0",
    "multer": "^1.4.2",
    "multer-s3": "^2.9.0",
    "mysql2": "^2.1.0",
    "node-localStorage": "0.0.1",
    "passport": "^0.4.1", //<===
    
    "passport-google-oauth": "^2.0.0", // <=== 구글 OAUTH
    
    "passport-kakao": "^1.0.0",
    "redis": "^3.0.2",
    "sequelize": "^6.3.4",
    "utf8": "^3.0.0"
  },
  "devDependencies": {
    "babel-eslint": "^10.1.0",
    "eslint": "^7.6.0",
    "eslint-config-airbnb": "^18.2.0",
    "eslint-plugin-import": "^2.22.0",
    "eslint-plugin-jsx-a11y": "^6.3.1",
    "eslint-plugin-react": "^7.20.5",
    "nodemon": "^2.0.4",
    "sequelize-cli": "^6.2.0"
  }
}
Comments