헬창 개발자

passport 구현 본문

공부방

passport 구현

찬배 2022. 10. 25. 19:53

passport란?

  • 내부적으로 쿠키와 세션을 사용해서 Node.js에서 인증을 쉽게 적용할 수 있는 미들웨어이다.
  • passport는 strategy(전략)라는 인증 전략을 사용하는데, 하나의 플로그인이라고 생각하면 쉽다. 여기서 strategy라고 하는 것은 어떤 것을 이용해, 어떻게 인증을 구현할 것인가에 대한 전략을 말한다.
  • 예를 들어 passport-facebook이라는 전략을 사용한다고 하면 사용자가 이미 가지고 있는 페이스북 아이디와 연동해서 인증을 수행할 수 있게 된다. 이외도 OpenID, Heroku, HTTP Bearer를 사용해서 인증하는 방법 등 다양한 방법이 존재한다.
  • 서비스의 목적에 맞게 사용하면 되는데 보통의 웹 서비스는 주로 local에서 구현하는 passport-local, passport-kakao, passport-facebook 등의 소셜 인증을 사용한다.
  • 인증과 권한 관리에 쓰이는 프로토콜에는 여러 가지가 있지만 가장 널리 쓰이는 방법으로 OAuth와 OpenID Connect라는 것이 있다.

OAuth

회원가입을 할 때 ‘카카오로 로그인하기’, ‘구글로 로그인하기’ 등 본적이 있을것이다. 이렇게 서드 파티 앱에서 사용자의 데이터에 접근할 수 있도록 허락해 준 것을 ‘위임 권한 부여’라고 하며, OAuth는 위임권한 부여를 위한 표준 프로토콜이다.

OpenID connect

OpenID connect는 OAuth와 동일한 레이어에 있고 OAuth를 확장한 것이라고 생각하면 된다. OAuth는 주로 API 사용자의 권한 부여에 사용된다면 OpenID는 주로 사용자의 인증에 사용된다.

passport 사용하기

$ npm install passport passport-local

먼저 passport를 설치해 package.json에 반영합니다.

아이디와 비밀번호를 입력받아 회원가입과 인증을 구현해 볼텐데 이는 strategy 중 하나인 local 방법이다.

이를 위해 passport-local 모듈도 설치하자

  • 회원가입 화면 코드
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="/login" method="post">
        <div>
            <label>Username:</label>
            <input type="text" name="username"/>
        </div>
        <div>
            <label>Password:</label>
            <input type="password" name="password"/>
        </div>
        <div>
            <input type="submit" value="Log In"/>
        </div>
    </form>
</body>
</html>
  • passport를 이용한 회원 가입 서버 코드 1
const express = require('express');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;

const app = express();

/* 포트 설정 */
app.set('port', process.env.PORT || 8080);

/* 가상 데이터 */
let fakeUser = {
    username: 'test@test.com',
    password: 'test@1234'
}

/* 공통 미들웨어 */
app.use(morgan('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser('passportExample'));
app.use(session({
    resave: false,
    saveUninitialized: false,
    secret: 'passportExample',
    cookie: {
        httpOnly: true,
        secure: false
    }
}));
  • passport를 이용한 회원 가입 서버 코드 2
/* passport middleware */
app.use(passport.initialize()); // passport 초기화
app.use(passport.session()); // passport session 연동

// 세션 처리 - 로그인에 성공했을 경우 딱 한번 호출되어 사용자의 식별자를 session에 저장
passport.serializeUser(function (user, done) {
    console.log('serializeUser', user);
    done(null, user.username);
});

// 세션 처리 - 로그인 후 페이지 방문 마다 사용자의 실제 데이터 주입
passport.deserializeUser(function (id, done) {
    console.log('deserializeUser', id);
    done(null, fakeUser); // req.user에 전달
});

passport.use(new LocalStrategy(
    function (username, password, done) {
        if (username === fakeUser.username) { // username OK
            if (password === fakeUser.password) { // password OK
                return done(null, fakeUser);
            } else {
                return done(null, false, { message: "password incorrect" });
            }
        } else {
            return done(null, false, { message: "username incorrect" });
        }
    }
));
  • passport를 이용한 회원 가입 서버 코드 3
/* 라우터 설정 */
app.get('/', (req, res) => {
    if (!req.user) { // 로그인 아직 하지 않았을 때
        res.sendFile(__dirname + '/index.html');
    } else { // 로그인 성공시 세션에 req.user 저장
        const user = req.user.username;
        const html = `
        <!DOCTYPE html>
        <html lang="ko">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Document</title>
        </head>
        <body>
            <p>${user}님 안녕하세요!</p>
            <button type="button" onclick="location.href='/logout'">Log Out</button>
        </body>
        </html>
        `
        res.send(html);
    }
});

/* Passport Login : Strategy-Local */
/* Authenticate Requests */
app.post('/login',
    passport.authenticate('local', { failureRedirect: '/' }),
    function (req, res) {
        res.send('Login success..!')
    });

app.get('/logout', function (req, res) {
    req.logout();
    res.redirect('/');
});

/* 404 에러처리 */
app.use((req, res, next) => {
    const error = new Error(`${req.method} ${req.url} 해당 주소가 없습니다.`);
    error.status = 404;
    next(error);
});

/* 에러처리 미들웨어 */
app.use((err, req, res, next) => {
    res.locals.message = err.message;
    res.locals.error = process.env.NODE_ENV !== 'development' ? err : {};
    res.status(err.status || 500);
    res.send('error Occurred');
});

/* 서버와 포트 연결.. */
app.listen(app.get('port'), () => {
    console.log(app.get('port'), '번 포트에서 서버 실행 중 ..')
});

 

username과 password를 올바르게 입력해서 로그인에 성공했다면 “Login success!”메시지와 함께 세션 쿠키가 생성된것을 확인이 가능하다.

 

'공부방' 카테고리의 다른 글

prophet 설치 오류 해결 방법  (0) 2022.11.03
도커 맛만 보기  (0) 2022.10.29
실시간 소켓 통신 구현을 해보자  (2) 2022.10.05
Node.js 환경에서 NoSQL : MongoDB 사용하기  (0) 2022.09.22
Node.js와 데이터베이스  (0) 2022.09.04
Comments