๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

[PROJECT] ๋‚ด์ผ์˜ ์ง‘

#6. ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ ๊ตฌํ˜„ (1์ฐจ)

#6-0 ๋“ค์–ด๊ฐ€๋Š” ๋ง


 ์ด์ „์— ํฌ์ŠคํŒ… ํ–ˆ๋˜๋Œ€๋กœ(https://white-salt.tistory.com/26) JWT ๋ฐฉ์‹์œผ๋กœ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด๋ณด์•˜๋‹ค. jwt ๊ฐœ๋…์„ ์ดํ•ดํ•˜๋Š” ๊ฒƒ๋„ ์กฐ๊ธˆ ์–ด๋ ค์› ๋Š”๋ฐ ์‹ค์ œ๋กœ ์ฝ”๋“œ ์งœ๋Š”๊ฑด ๋” ์–ด๋ ค์› ๋‹ค (^_^;;). ์ผ๋‹จ ์ง€๊ธˆ๊นŒ์ง€ ์ง  ์ฝ”๋“œ๋ฅผ ํ•œ๋ฒˆ ์ •๋ฆฌ ํ›„ ๋ฐฑ์—”๋“œ ์นœ๊ตฌ์™€ ํšŒ์˜๋ฅผ ์ง„ํ–‰ํ•ด๋ณด์ž.

 


#6-1 ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ ๋กœ์ง

์ด๋ฏธ์ง€ ์ถœ์ฒ˜: https://maruzzing.github.io

 

1. ์•„์ด๋””์™€ ํŒจ์Šค์›Œ๋“œ๋ฅผ ์„œ๋ฒ„๋กœ ์ „์†กํ•˜์—ฌ accessToken๊ณผ refreshToken ๋ฐ›๊ธฐ. 

์ž…๋ ฅ๋ฐ›์€ id์™€ password ๊ฐ’์„ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋ฉด, ์„œ๋ฒ„๋Š” ์œ ์ €ํ™•์ธ ํ›„ ๋“ฑ๋ก๋œ ์œ ์ €๊ฐ€ ๋งž๋‹ค๋ฉด accessToken, refreshToken์„ ๋ฐœ๊ธ‰ํ•ด์ค€๋‹ค.

(Q1. ์ด๋•Œ ๋ฐœ๊ธ‰ ๋ฐ›์€ refreshToken์„ httpOnly cookie๋กœ ์„œ๋ฒ„๋‹จ์—์„œ ๋ฐ”๋กœ ์ €์žฅํ•ด์ฃผ๊ณ , ์ดํ›„ ํด๋ผ์ด์–ธํŠธ์—์„  cookie์— ์ €์žฅ๋œ refreshToken์„ ํ•„์š”ํ•  ๋•Œ ๊ฐ€์ ธ๋‹ค ์“ฐ๋ฉด ๋˜๋Š”๊ฑด๊ฐ€?)


2. ์ดํ›„ accessToken์€ ๋งค Api ํ˜ธ์ถœ๋งˆ๋‹ค ํ—ค๋”์— ๋ถ™์—ฌ์„œ ์ „์†กํ•˜๊ณ , ์„œ๋ฒ„๋Š” accessToken์„ ๊ฒ€์ฆํ•œ ํ›„ ๋‹ค์‹œ accessToken๊ณผrefreshToken์„ ๋ฐœ๊ธ‰ํ•ด์ค€๋‹ค.

*HTTP ํ—ค๋”๋Š” ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ ๋˜๋Š” ์‘๋‹ต์œผ๋กœ ๋ถ€๊ฐ€์ ์ธ ์ •๋ณด๋ฅผ ์ „์†กํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค.
(Q2. ๋งค๋ฒˆ accessToken ๊ฒ€์ฆ ํ›„ ๋ฐ›์€ ๋‘ ํ† ํฐ์€ ๊ธฐ์กด๊ณผ ๋˜๋‹ค๋ฅธ ์ƒˆ๋กœ์šด ํ† ํฐ์ธ์ง€? ์•„๋‹˜ accessToken์ด ์ผ์น˜ํ•œ๋‹ค๋Š” status ๊ฐ’๋งŒ ์ „์†กํ•ด์ฃผ๋Š”์ง€?


// LoginPresenter.js
const handleSubmit = (e) => {
  e.preventDefault();
  const id = idData.current.value;
  const password = passwordData.current.value;
  props.onlogin(id, password);
}
  
// LoginController.js
const onlogin = (id, password) => {
    const data = {id, password};
    const headers = {
      'Content-Type': 'application/json'
    };

    axios.post("/login", data, {headers: headers})
    .then((res)=> {
      const {accessToken} = res.data;
      dispatch({type: 'LOGIN_SUCCESS', payload: {"accessToken": accessToken}});

      // API ์š”์ฒญํ•˜๋Š” ์ฝœ๋งˆ๋‹ค ํ—ค๋”์— accessToken ๋‹ด์•„ ๋ณด๋‚ด๋„๋ก ์„ค์ •
      axios.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`;

      history.push("/");
    })
    .catch((error)=>{
      dispatch({type: 'LOGIN_FAILURE'});
      // refreshTokenSaveCookie(id);
      history.push("/login");
      console.log('LOGIN FAILURE');
    })
}

 

3. ๋งŒ์•ฝ accessToken์ด ๋งŒ๋ฃŒ๋˜์—ˆ์œผ๋ฉด refreshTokenRequest ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜์–ด ์ฟ ํ‚ค์— ์ €์žฅ๋œ refreshToken์„ ์„œ๋ฒ„์— ๋ณด๋‚ด ๋‹ค์‹œ ์ƒˆ๋กœ์šด accessToken์„ ๋ฐœ๊ธ‰ ๋ฐ›๋Š”๋‹ค. 

์ƒˆ๋กœ์šด accessToken์€ ๋‹ค์‹œ ๋งค Api ํ˜ธ์ถœ๋งˆ๋‹ค ํ—ค๋”์— ๋ถ™์—ฌ์„œ ์ „์†กํ•œ๋‹ค.

(**accessToken์ด ๋งŒ๋ฃŒ๋˜์–ด ์„œ๋ฒ„์—์„œ 400 ์—๋Ÿฌ๋ฅผ ๋ณด๋‚ด์ฃผ๋ฉด ์ด๋ฅผ ๊ฐ์ง€ ํ›„ refreshTokenRequest ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ์ฝ”๋“œ๋ณด์•ˆ ํ•„์š”ํ•จ)
(Q3. ์ด๋•Œ refreshToken๋„ ์ƒˆ๋กœ์šด ๊ฐ’์ด๊ณ  ๋ฐ”๋กœ ๋˜ ์„œ๋ฒ„๋‹จ์—์„œ ์ฟ ํ‚ค์— ์ €์žฅํ•ด์ฃผ๋‚˜?)

// auth.js
export const refreshTokenRequest = () => {
  const refreshToken = Cookie.get("refreshToken");
  const data = {
    refreshToken
  };
  const headers = {
    'Content-Type': 'application/json'
  };

  axios.post('/token/refresh', data , {headers: headers})
  .then((res)=>{
    const { accessToken } = res.data;

    // accessToken ์„ค์ •
    axios.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`;
  })
  .catch(error => {
      console.log('refreshToken error')
  });
}