프리온보딩 챌린지

프리온보딩 FE 챌린지, Ouath(4)

노엠디엔 2023. 10. 16. 15:16

이번 시간은 챌린지 마지막 시간으로 실습시간을 많이 가졌다. 마지막에 OAuth에 조금 다루고 끝이 났다.

 

서버와 클라이언트에서의 역할은 무엇인가? 로 강의를 시작을 하였는데

만약 서버에서 벨리데이션? 유저를 검증하는 검사를 하지않고
클라이언트에서만 로그인 시 유효성 검사, 특수문자나 유저를 확인하는 절차를 진행한다면

분명히 문제가 생길 것이기 때문에 클라이언트뿐만 아니라 서버에서도 벨리데이션, 검증 절차를

꼭 실행시켜야 한다고 말씀해주셨다.또한 권한 따른 본인 자원에만 접근 가능하도록 하며

권한에 따른 페이지 이동이나 적절한 자원에 접근하도록 해야한다.

(저번 시간에 다루었던 일반 유저가 관리페이지 접근시 404, 403을 뱉도록?)

 

실습 시간에는 저번시간과 비슷하게 진행되었다. 클라이언트와 서버를 동시에 실행시키면서

서버에서 일어나는일에 대해서도 많이 알아보는 시간이였다.(실습 코드는 블로그에 올리면 안되서 아쉽..)

 

실습하는 중간에 타입스크립트에 관한 질문이 있었는데

 

interface RouterBase {
  id: number // 페이지 아이디 (반복문용 고유값)
  path: string // 페이지 경로
  label: string // 사이드바에 표시할 페이지 이름
  element: React.ReactNode // 페이지 엘리먼트
}

interface UserAccessibleRouterElement extends RouterBase {
  withAuth?: boolean // 인증이 필요한 페이지 여부
}

interface AdminAccessibleRouterElement extends RouterBase {
  withAuth: true // 인증이 필요한 페이지 여부
  isAdminPage?: boolean // 어드민 페이지 여부
}
 
type RouterElement = UserAccessibleRouterElement | AdminAccessibleRouterElement

다음과 같은 코드에서 RouterElement 타입을 통해 isAdminPage 속성에 접근할려고 하면
isAdminPage타입이 없다는 에러가 발생했다?

  1. 'isAdminPage'라는 속성이 'RouterElement' 타입에 존재하지 않습니다.
  2. 'isAdminPage'라는 속성이 'UserAccessibleRouterElement' 타입에도 존재하지 않습니다.

그래서 그이유는

Router Element가 or 묶인 타입이기 때문에 UserAccessibleRouterElement에
isAdminPage가 존재하지 않기 때문에isAdminPage를 호출하는 구문 자체를 문제로 판정하고 있어서
실제 자바스크립트의 동작을 생각한다면
없는 프로퍼티를 찍었으니 undefined가 나오고
이 값의 유효성으로 truthy한지 판정하면 될 것 같지만?!

타입스크립트에서는 없는 프로퍼티를 찍는 동작 자체를 문제로 취급하기 때문이다.

 

element: <GeneralLayout isAdminPage={'isAdminPage' in router && router.isAdminPage}>{ router.element }</GeneralLayout>

그레서 강의에서는 해당과같이 타입에러를 해결하였다!

 

또 추가로 route와 관련하여 useRouter 훅을 만들어서 useNavigate객체를 한번만 만들어서 사용하도록 하며

많이 사용되는 route 경로를 여기에서 작성하여 사용하도록 하는 팁이 있었다

예시: home으로 가는 homeTo: ()=> router(' / ') 를 생성

import { useNavigate } from 'react-router-dom'

export const useRouter = () => {
  const router = useNavigate()

  return {
    currentPath: window.location.pathname,
    routeTo: (path: string) => router(path)
  }
}

기타로 서버로 post데이터를 보낼때 credentials:include 로  설정해서 보내줌!

Refresh 토큰을 사용하여 로그인 구현?

로그인을 통해 AccessToken은 로컬에 발급 받고 (짧은 시간동안만 유효하게 끔!)

RefreshToken은 HttpOnly Cookie로 발급받아서 js 코드로 접근 불가능하게 한다!

해커가 CSRF (Cross-Site Request Forgery)  스팸, 이상한 사이트로 방문하게끔 하여

토큰 재발급을 시도할려고 한다면 서비스에서는 여러가지 방어 체계를 설계 가능하다

AccesToken이 유효한 경우 refreshToken 재발급 불가능!

  1. Refresh 토큰 단순 재사용 방지: Refresh 토큰이 재사용되지 않도록 서버에서 감지하는 방법 중 하나는
    각 Refresh 토큰을 사용한 후 무효화하는 것입니다. 즉, 한 번 사용된 Refresh 토큰은 더 이상 유효하지 않게 만드는 것이며, 해커가 이를 다시 사용하려고 시도하면 실패하게 됩니다.
  2. 유효 기간 제한: Refresh 토큰의 유효 기간을 제한하는 것이 도움이 될 수 있습니다. 매번 Refresh 토큰을 사용할 때마다 새로운 토큰을 발급하고, 이러한 토큰은 짧은 유효 기간을 가지도록 설정하면, 해커가 오랜 시간에 걸쳐 토큰을 재사용할 가능성을 줄일 수 있습니다.
  3. 사용자 인증 요구: 민감한 작업을 수행할 때마다 사용자를 다시 인증하도록 요구하는 것이 추가 보호를 제공합니다. 예를 들어, 사용자가 비밀번호를 변경하거나 결제를 수행할 때 Refresh 토큰을 사용하여 새로운 Access 토큰을 얻을 수 있지만, 이러한 작업을 수행할 때 사용자에게 다시 로그인하도록 요구하면 보안을 더 강화할 수 있습니다.
  4. 로그 모니터링 및 경고: 서비스에서 로그 모니터링 시스템을 구현하여 Refresh 토큰의 사용을 모니터링하고, 이상한 활동을 감지하는 경우 경고를 생성하도록 설정할 수 있습니다. 이를 통해 비정상적인 토큰 사용을 빠르게 식별하고 조치를 취할 수 있습니다.
  5. API 요청 검증: 모든 API 요청에 대해 정상적인 Refresh 토큰을 검증하는 절차를 구현하세요. 토큰이 서명되었는지, 만료되지 않았는지 및 서버에서 발급한 유효한 토큰인지 확인하는 것이 중요합니다.

 OAuth란(open aouthorization)!?

허가된 서비스를 통해 기존 서비스(카카오, 구글, 네이버) 등의 권한을 '위임' 하는 것!

  1. 내가 만든 서비스에서 카카오나, 네이버 등  OAuth 인증 요청
  2. 해당 카카오, 네이버 서비스에 OAuth 로그인용 링크 전달 (
  3. 리디렉션을 통해 인증요청 및 카카오,네이버 서비스로 정보 전달
    이때 타 서비스에서 받은 값을 가지고 특정 주소로 이동하게 됨
  4. 다시 나의 서비스에서 카카오, 네이버 토큰을 전달 받음
  5. 나의 서비스에서 서버에 카카오, 네이버 용 토큰과 동작을 요청?
  6. 이후에 유저가 카카오, 네이버 서비스에 의존하는 동작시 받은 토큰과 시크릿 키를 이용해 동작 요청
  7. 카카오, 네이버에서 전달된 토큰과 시크릿 키 확인 후 동작을 승인

권한에 따라 OAuth 원본 서버(예제에서의 구글)의 유저 정보를 가져와 사용하거나 권한을 위임받은 동작을 할 수 있으며(ex. Calendly - 캘린더에 일정 등록) 인증 자체만을 사용할 수도 있다.

 

이렇게 2주가 지나가서 프리온보딩 FE 챌린지도 끝이났다 처음에는 무료이기도 하다보니 기대안하고
들었는데 요즘 정말 많이 헤이해졌다는 느낌을 받은 시간이였다. 생각보다 유료강의보다도
내용이 너무 좋아서 별 5점짜리 강의였다. 또한 실습을 통해서 다른 사람의 코드를 통해
어떻게 코드를 짜야할지에 대해서 다시 생각해보는 시간이기도 했다.
이번에 배운 OAuth 를 통해 개인 프로젝트에도 한 번 도입해보고 다른 시스템도 가져와 사용해봐야겠다.