Node.js

[node.js] express + passport + 42 API 로그인 구현

hazel__ 2021. 10. 29. 14:58

이 글은 node.js의 express와 passport를 이용하여 42 OAuth 로그인을 구현한 것이다.

 

1. 42API 등록하기

https://api.intra.42.fr/apidoc

위의 사이트에서 42 API getStarted로 시작한다.

42's API getStared

위에 보이는 'here'을 클릭하여 application을 생성한다.

  • Name : 프로젝트 명
  • Image : 프로젝트 이미지
  • Website : 프로젝트 도메인
  • RedirectURI : 로그인 성공 시, 리다이렉트할 주소

 

API를 등록하면 아래와 같이 UID, SECRET 이 만들어진다.

 

API를 등록했다면, 이제 코드를 작성해보자!


2. 코드 작성하기

1. 서버 생성하기

www 파일

//www
#!/usr/bin/env node
require("dotenv").config();        //.env
const app = require("./app");    //app.js
const http = require("http");
const debug = require("debug")('test:server');

//port 설정
const port = normalizePort(process.env.PORT || '4242');
app.set('port', port);

//server 생성
const server = http.createServer(app);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

function normalizePort(value){
    const port = parseInt(value, 10);
    if (isNaN(port)) return value;
    if (port >= 0) return port; return false;
}
function onError(error){
    if (error.syscall !== 'listen'){
        throw error;
    }
    let bind = typeof port === 'string' ? `Pipe ${port}` : `Port ${port}`;
    switch(error.code){
        case 'EACCES':
            console.error(bind + ' requires elevated privileges');
            process.exit(1);
            break ;
        case 'EADDRINUSE':
            console.error(bind + " is already in use");
            process.exit(1);
            break ;
        default: throw error;
        }
}
function onListening(){
    const addr = server.address();
    const bind = typeof addr === 'string' ? `pipe ${addr}` : `port ${addr.port}`;
    debug('Listening on ' + bind);
}

 

app 파일

require("dotenv").config();
const express = require("express");
const path = require("path");
const cookieParser = require("cookie-parser");
const cookieSession = require("cookie-session");

const app = express();

app.use(
    cookieSession({
        maxAge: 60 * 60 * 1000,
        keys: [process.env.COOKIE_KEY],
    })
);

app.use(express.json());
app.use(express.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, "public")));

module.exports = app;

서버를 생성했으니, 이제 passport를 만들어보자!!


2. Passport 만들기

passport 모듈은 이름 그대로 여권과 같은 역할을 해준다.

인증 절차에 대한 로직을 도와주는 node.js 미들웨어로, 세션을 관리할 때 사용한다.

미들웨어 : 사용자가 특정한 요구대로 만들어 제공하는 프로그램으로 조정과 중개의 역할을 하는 소프트웨어를 말한다.

세션 : 브라우저가 종료되기 전까지 클라이언트의 요청을 유지하게 해주는 기술로, 로컬과 서버에 데이터가 저장되고, 브라우저가 종료되면 삭제된다.

42 passport에 대한 정보는 아래의 사이트에서 알 수 있다.

http://www.passportjs.org/packages/passport-42

 

passport-42

42 authentication strategy for Passport.

www.passportjs.org

 

passport.js

//passport.js
require("dotenv").config();
const passport = require('passport');
const FortyTwoStrategy = require('passport-42');
const env = process.env;

//session에 저장할 정보
passport.serializeUser(function(user, done){
    return done(null, user);
});
//session에 저장된 값을 이용하여 사용자 프로필을 찾은 뒤, HTTP Request를 반환한다.
passport.deserializeUser(function(user, done){
    done(null, user);
});

const FortyTwoOpt = {
    clientID: env.FORTYTWO_APP_ID,
    clientSecret: env.FORTYTWO_APP_SECRET,
    callbackURL: env.CALLBACK_URL,
    passReqToCallback: true,
};

FortyTwoVerify = (req, accessToken, refreshToken, profile, cb) =>{
    const user = {
        username: profile.username,
        displayname: profile.displayName,
        email: profile.emails[0].value,
        userid: profile.id
    };
    return cb(null, user);
}

module.exports = () => {
    passport.use(new FortyTwoStrategy(FortyTwoOpt, FortyTwoVerify));
}

passport 코드를 작성했다면, app.js 파일에서 실행해야 한다.

app.js

const passport = require("passport");
const passportConfig = require("./passport.js");

app.use(passport.initialize());
app.use(passport.session());
passportConfig();

위의 코드를 app.js 코드에 추가한다.


3. dotenv

dotenv 를 사용하여 환경 변수를 파일에 저장하여 관리할 수 있다.

process.env로 접근하여 사용할 수 있다.

.env

PORT = 4242

FORTYTWO_APP_ID = UID 값
FORTYTWO_APP_SECRET = SECRET 키 값
CALLBACK_URL = /auth/login/callback (redirection URI)

COOKIE_KEY = secret

 


4. 경로 설정

지금까지의 코드로 실행을 하면,

위와 같이 오류가 발생한다.

코드 실행은 'node www' 명령어로 실행하면 된다.

 

이제 경로를 설정하여 오류를 해결해보자!

 

route.js

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

//'/auth/login' 경로 설정
router.get('/auth/login', passport.authenticate('42'));
//'/' 경로 설정
router.get('/', authCheck, function(req, res, next){
    console.log('user', req.user);
    res.json({ test: req.user });
});
// login 성공 후의 redirect URI 경로
router.get(
    "/auth/login/callback",
    passport.authenticate("42", {
        successRedirect: "/login/success",
        failureRedirect: "/login/failure"
    })
);
//login 성공시
router.get("/login/success", authCheck, function(req, res, next){
    res.json({msg: "hi"});
});
//login 실패시
router.get("/login/failure", authCheck, function(req, res, err){
    res.json({msg: "TT"});
});

const authCheck = (req, res, next) => {
    console.log(req.user);
    if (req.user){
        console.log("success auth");
        next();
    }
    else{
        console.log("failed to auth");
        res.status(401).json({
            authenticated: false,
            message: "User has not been authenticated"
        });
    }
};

module.exports = router;

이제 route를 app.js 파일에 추가하여 적용한다.

 

app.js

const indexRouter = require("./route.js");

app.use("/", indexRouter);

코드를 실행하면,

아직 로그인을 실행하지 않은 상태이다.

 

경로를 변경하여, 로그인을 해보자.

localhost:4242/auth/login 으로 이동한다~!!

 

login

완성!!