본문 바로가기
Express, Next.js/Express

[express] jsonwebtoken 로그인 구현하기

by 방배킹 2024. 4. 17.

jsonwebtoken

express에서 jwt를 사용하려면 jsonwebtoken 모듈이 필요하다.

https://www.npmjs.com/package/jsonwebtoken

 

jsonwebtoken

JSON Web Token implementation (symmetric and asymmetric). Latest version: 9.0.2, last published: 8 months ago. Start using jsonwebtoken in your project by running `npm i jsonwebtoken`. There are 27478 other projects in the npm registry using jsonwebtoken.

www.npmjs.com

 

npm install jsonwebtoken

npm install @types/jsonwebtoken # typescript 사용시

 

jwt.sign(payload, secretOrPrivateKey, [options, callback])

 

payload 는 객체, 리터럴, 버퍼, string 모두 가능하다. payload가 버퍼나 string이 아닐경우 string으로 변환된다.

 

secretOrPrivateKey 는 jwt를 서명할때 사용하는 비밀키이다. 

 

callback 함수를 사용하면 비동기 형식으로 사용할 수 있다.

 

const token = jwt.sign({
  data: 'foobar'
}, 'secret', { expiresIn: '1h' });

 

 

 

jwt.verify(token, secretOrPublicKey, [options, callback])

 

token 은 확인하고자 하는 jwt 토큰이다.

 

secretOrPrivateKey  는 jwt를 서명할때 사용했던 비밀키이다. 

 

var decoded = jwt.verify(token, 'secret');

 

secretOrPrivateKey 가 일치하면 payload를 반환한다.

 

// invalid token - synchronous
try {
  var decoded = jwt.verify(token, 'wrong-secret');
} catch(err) {
  // err
}

// invalid token
jwt.verify(token, 'wrong-secret', function(err, decoded) {
  // err
  // decoded undefined
});

 

 try-catch, callback 함수를 통해 에러 처리를 할 수 있다.

 

JWT 로그인 구현

// jwt 로그인
router.post('/jwt/login',async(req:Request,res:Response)=>{
    try{
        const {userEmail,password} = req.body;
        const userdata:User|null = await UserModel.findByUserEmail(userEmail);

        //존재하지 않는 사용자
        if (!userdata) {
            return res.status(400).json({ message: '이메일을 다시 확인해주세요.' });
        }
        const passwordMatch = await bcrypt.compare(password,userdata.password);
        if(passwordMatch){
            const token = jwt.sign({
                userEmail: userdata.userEmail,
                nickname: userdata.nickname,
                loginTime: new Date().toISOString()                
            }, 'secret', { expiresIn: '30m' });
            console.log(userEmail,' 로그인');
            res.status(200).json({
                message: `${userEmail}`+'로그인',
                token: token
            });
        }else{
            res.status(400).json({ message: '비밀번호를 다시 확인해주세요.' });
        }
    }catch(error){
        console.error('jwt login error :', error);
        res.status(500).json({ message: '로그인 오류' });
    }
})

 

 

jwt 토큰이 잘 생성된다.

 

jwt.verify

// jwt check
router.get("/jwt/payload", verifyToken, (req:CustomRequest,res:Response) => {
    const decode = req.decode
    return res.status(200).json({
      code: 200,
      message: "토큰이 정상입니다.",
      data: {
        userEmail: decode.userEmail,
        nickname: decode.nickname,
        loginTime: decode.loginTime
      },
    });
});

// 미들웨어
const verifyToken = (req:CustomRequest,res:Response, next:NextFunction)=>{
    const token = req.headers.authorization;
    if(!token){
        return res.status(400).json({message:'토큰이 존재하지 않습니다.'});
    }
    jwt.verify(token, 'secret', function(err:Error, decode:TokenPayload) {
        if(err){
            return res.status(400).json({message:'토큰 오류'});
        }
        req.decode = decode;
        next();
    });
}

// 타입 지정
export interface TokenPayload {
    userEmail: string;
    nickname: string;
    loginTime:string;
}
export interface CustomRequest extends Request {
    decode?: TokenPayload;
}

 

 

Header의 Authorization에 생성된 토큰을 넣고 요청을 보내자.

 

 

잘못된 토큰을 넣으면 오류가 발생한다.

 

댓글