react&node.js 개발 - 로그인하면서 JWT 토큰 발급받고 유저 정보 알아내기

1. 비밀 키 생성

 

백엔드에 config.js 파일 작성

 

다음과 같이 secret key를 작성

 

JWT 토큰 검증시 해싱에서 사용할 키라고함

 

//backend//config.js
//jwt verification secret key

module.exports = {
    'secret':'대혁이다'
}

 

 

2. 서버에 secret key 세팅

 

서버에 작성한 config 파일을 불러오고 secret key를 다음과 같이 세팅

 

//backend/server.js
// set the secret key variable for jwt

const config = require('./config')
app.set('jwt-secret', config.secret)

 

3. 로그인 api 작성

 

$npm install jsonwebtoken으로 모듈 설치

 

//backend/server.js
//login api

const jwt = require('jsonwebtoken');

app.post('/api/login',(req,res) => {
    console.log(req.body)

    const key = req.app.get('jwt-secret')

    User.findAll({
        where: { [Op.and]: [{email:req.body.email, password:req.body.password}]}
    })
    .then(result => {

        if (result[0]){

        const user_id = String(result[0].id)

        let token = jwt.sign(
            {
                type:"JWT",
                username: result[0].username
            },
            key,
            {
                expiresIn: "1d",
                issuer: "IGoAT",
                jwtid: user_id,
            }
        
        )
    return res.send({
        result,
        jwt:token,
    })} else {
        return res.send({
            result,
            jwt:''})
    }
})
    .catch(err => {
        throw err;
    })
})

 

세팅한 key를 req.app.get('jwt-secret')로 받아오고

 

클라이언트에서 받아온 req에서 아이디, 비밀번호를 가져와 User 테이블에서 해당 정보가 존재하는지 검증

 

그러면 result가 객체가 1개 있는 배열로 들어오는데

 

result[0]가 존재한다면 해당하는 유저 데이터가 존재하는 것이고

 

 

존재하지 않는다면 해당하는 유저 데이터가 존재하지 않는다는 뜻이다

 

 

4. jwt 토큰 발급받는 함수

 

위 로그인 api에서 JWT 토큰 발급받는 부분이 아래와 같이 생긴듯

 

        if (result[0]){

        const user_id = String(result[0].id)

        let token = jwt.sign(
            {
                type:"JWT",
                username: result[0].username
            },
            key,
            {
                expiresIn: "1d",
                issuer: "IGoAT",
                jwtid: user_id,
            }
        
        )

 

 

깃허브 옵션 보면 jwt.sign(payload, secret, option,...)으로 구성된다

 

payload에는 토큰에 넣을 정보들을 포함하는데 여러가지가 있고 복잡하다..

 

여기서는 유저이름만 넣었고

 

secret에는 앞에서 세팅했던 해싱 알고리즘에 사용할 key

 

option에는 여러가지 설정할 수 있는데 

 

expireIn은 토큰 유효기한으로 1d는 하루겠지.. 10h하면 10시간일듯

 

issuer은 토큰 발급자

 

jwtid는 토큰을 발급받은 유저의 아이디를 나타낸다. 이거는 나중에 사용할려면 웬만하면 작성해줄 필요가 있다

 

아무튼 이렇게 토큰 발급받는 api작성하고 실제 로그인하면 jwt 토큰 발급받는 것을 확인할 수 있다

 

 

 

5. 로그인 비밀번호 암호화

 

로그인할때 비밀번호를 암호화해서 서버에 전달해줄 필요가 있다

 

리액트에서 crypto 모듈을 이용하면 가능한데, 내장된 모듈이라 설치할 필요는 없는 것 같다

 

유저가 입력한 비밀번호 password를 받아와 crypto.createHash().update().digest()로 암호화시킬 수 있다

 

createHash 안에는 암호화알고리즘이 들어가고 sha256, sha512 등이 있다.

 

update에는 유저가 입력한 비밀번호

 

digest에는 해쉬 표기법으로 인코딩 방식을 정하는 건데 base64, hex 등이 있나봄

 

digest는 어떤걸 쓰느냐에 따라 암호화 결과 길이가 달라지나봐

 

//hash password
//password: 유저가 입력한 비밀번호
//hashPassword: 암호화된 비밀번호

let hashPassword = ''

try {
  hashPassword = crypto
  .createHash('sha512')
  .update(password)
  .digest('hex')
} catch (e) {
  return;
}

 

6. crypto 사용중 에러

 

crypto 사용중에 에러가 난다면...

 

대충 아래와 같은 에러가 날 수가 있음

 

Module not found: Error: Can't resolve 'crypto' in '/home/borislav/Desktop/bobbyhadz-rest/bobbyhadz-react/node_modules/cookie-signature'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
    - add a fallback 'resolve.fallback: { "crypto": require.resolve("crypto-browserify") }'
    - install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
    resolve.fallback: { "crypto": false }

 

그러면 npm install crypto-browserify로 모듈 설치하고

 

frontend/config/webpack.config.js에서 resolve를 찾아본다

 

 

그리고 fallback을 찾아서 이렇게 써주면 되더라

 

물론 crypto-browserify를 작성하고, 다시 에러나서 stream-browserify, buffer도 설치하라고 나와서

 

그것도 아래와 같이 작성했음

 

 

7. jwt 토큰 해독하기

 

jwt 토큰을 해독해서 유저의 정보를 알아낼 수 있다

 

jwtDecode 함수를 이용하면 jwt 토큰을 해석해줌

 

import jwtDecode from "jwt-decode";

export class jwtUtils {
  // 토큰 유효성 검사
  static isAuth(token) {
    if (!token) {
      return false;
    }
    const decoded = jwtDecode(token);
    if (decoded.exp > new Date().getTime() / 1000) {
      return true;
    } else {
      return false;
    }
  }
  // 토큰에서 유저 id 가져오기
  static getId(token) {
    const decoded = jwtDecode(token)
    console.log(decoded)
    return decoded.jti;
  }

}

 

실제 사용해보면 이런식으로 나옴

 

 

 

jwt 토큰 발급하는 함수 작성할때 옵션에 넣었던 정보들이 들어가있다

 

옵션에 쓰지 않으면 나오지 않는다 

 

예를 들어 jwtid를 작성하지 않으면 jti 값이 나오지 않아

 

        if (result[0]){

        const user_id = String(result[0].id)

        let token = jwt.sign(
            {
                type:"JWT",
                username: result[0].username
            },
            key,
            {
                expiresIn: "1d",
                issuer: "IGoAT",
                jwtid: user_id,
            }
        
        )

 

 

iss는 토큰 발급자, iat는 토큰 발급시간, exp는 만기시간,

 

jti는 고유식별자, 여기서는 유저 id값을 넣어서 해독해서 유저 id를 알아낼 수 있도록 했음

 

참조

 

auth0/node-jsonwebtoken: JsonWebToken implementation for node.js http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html (github.com)

 

GitHub - auth0/node-jsonwebtoken: JsonWebToken implementation for node.js http://self-issued.info/docs/draft-ietf-oauth-json-web

JsonWebToken implementation for node.js http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html - GitHub - auth0/node-jsonwebtoken: JsonWebToken implementation for node.js http://self-iss...

github.com

 

[JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG

 

[JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG

지난 포스트에서는 토큰 기반 인증 시스템의 기본적인 개념에 대하여 알아보았습니다. 이 포스트를 읽기 전에, 토큰 기반 인증 시스템에 대해서 잘 모르시는 분들은 지난 포스트를 꼭 읽어주세

velopert.com

 

Node.js / crypto module(단방향 암호화) / 해시 생성 (tistory.com)

 

Node.js / crypto module(단방향 암호화) / 해시 생성

crypto? Node.js 내장 암호화 모듈입니다. 비밀번호를 데이터베이스에 저장하기 위해서는 암호화 과정을 필수로 거쳐야 합니다. 아래는 공식사이트에서의 crypto 설명란입니다. https://nodejs.org/api/crypto

fierycoding.tistory.com

[NodeJS] crypto를 이용한 단방향 암호화(해시 함수) 만들기 (tistory.com)

 

[NodeJS] crypto를 이용한 단방향 암호화(해시 함수) 만들기

비밀번호 같은 데이터는 보통 단방향 암호화 알고리즘을 사용해서 암호화한다. 단방향 암호화란 암호화된 문자열을 다시 원래 문자로 복호화를 할 수 없는 암호화다. 다시 복호화할 수 없어서

minu0807.tistory.com

 

Module not found: Error: Can't resolve 'crypto' [Solved] | bobbyhadz

 

Module not found: Error: Can't resolve 'crypto' [Solved] | bobbyhadz

To solve the Module not found: Error: Can't resolve 'crypto' error, set the `browser.crypto` property to `false` in your `package.json` file or include a polyfill to the `crypto-browserify` module in your `webpack.config.js` file.

bobbyhadz.com

 

 

TAGS.

Comments