iT邦幫忙

2023 iThome 鐵人賽

DAY 19
0
Security

從自建漏洞中學習 - 一起填坑吧系列 第 19

Auth 應用程式 - Login API 實踐篇

  • 分享至 

  • xImage
  •  

Auth 應用程式 - Login API 實踐篇

延續上次的 "signup 篇",接下來我要介紹 login 篇啦 ~

還記得我們當初介紹的 JWT token 嗎 ?
JWT token 是屬於 token-authentication 的一種實作。而根據憑證驗證的概念,我們在登入的時候會攜帶一組 token,所以我也會將 JWT token 融入實作中。

Login API 實踐篇

以下範例我暫時先忽略非預期的 Error Handling 的問題,這個部分會在之後的文章中講解。

第一步 - 定義輸入錯誤帳密 & 其他錯誤訊息

exports.login = async(req, res, next) => {
    const { email, password } = req.body;
    
    // 針對使用者沒有輸入 email or password 的部分
    if (!email || !password){
        // 備註: 
        // 此處的 AppError 是我們做的一個 Class 他 extends Error Class
        return next(new AppError('Please provide your email and pawwsord', 400));
    }
    
    // 找尋是否有 user,並選取他的 password
    const user = await User.findOne({ email }).select('+password');
    
    // 接著來比對已經加密的密碼 : 我們需要使用一個 function 在 model 中幫我們 compare password (有關此 function 請看下段程式碼區塊 - function passwordIsMatched
    const isMatched = await user.passwordIsMatched(password, user.password);
    
    // 注意! 以下為主要的錯誤示範
    if(!user)){
        return next(new AppError('Incorrect email'), 401);
    }
     
    
}

function passwordIsMatched:

userSchema.methods.passwordIsMatched = async function(inputPassword, userPassword) {
    return await bcrypt.compare(inputPassword, userPassword);
}

Good Practice

// 其他 code 省略
// 比較好的方式是把上述 error 換成比較模糊的 error message
if(!user || !(await user.passwordIsMatched(password, user.password))){
    return next(new AppError('Incorrect email or password'), 401);
}

第二步 - 加入 sign token

此處就沒有多加說明 Bad Practice,因為差不多需要注意的有在前面提到。

Good Practice

// 把 signtoken 拆出來,拆成一個 function
const signToken = id => {
    return jwt.sign({ id }, process.env.JWT_SECRET, { expiresIn: process.new.JWT_EXPIREIN});
}

exports.login = async(req, res, next) => {
    // 中間省略
    const token = signToken(user._id);
    
    res.status(200).json({
        status: 'success',
        token,
    });
    
}

最後若 login 成功,就會回傳 status & token 啦~

附上完整程式碼:

const signToken = id => {
    return jwt.sign({ id }, process.env.JWT_SECRET, { expiresIn: process.new.JWT_EXPIREIN});
}

exports.login = async(req, res, next) => {
    const { email, password } = req.body;
    
    // 針對使用者沒有輸入 email or password 的部分
    if (!email || !password){

        return next(new AppError('Please provide your email and pawwsord', 400));
    }
    
    // 找尋是否有 user,並選取他的 password
    const user = await User.findOne({ email }).select('+password');
    

    if(!user || !(await user.passwordIsMatched(password, user.password))){
        return next(new AppError('Incorrect email or password'), 401);
    }
     
    // 加入 sign token 後
    const token = signToken(user._id);
    
    res.status(200).json({
        status: 'success',
        token,
    });
    
}

今日小心得

今天簡單介紹了 Login api,不得不說實踐安全的程式有很多需要注意的,很感謝 Udemy 課程跟線上文章讓我獲益良多!


Reference:


上一篇
Auth 應用程式 - Signup API 實踐篇
下一篇
Auth 應用程式 - Authentication 認證篇
系列文
從自建漏洞中學習 - 一起填坑吧30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言