[uber-eats] user authentication - 1

한재창·2023년 5월 31일
0
post-thumbnail

JWT(Json Web Token)

JWT는 일반적으로 클라이언트와 서버 사이에서 통신할 때 권한을 위해 사용하는 토큰이다. 웹 상에서 정보를 Json형태로 주고 받기 위해 표준규약에 따라 생성한 암호화된 토큰으로 복잡하고 읽을 수 없는 string 형태로 저장되어있다.

JWT 구성요소

JWT는 헤더(header), 페이로드(payload), 서명(signature) 세 파트로 나눠져 있으며, 아래와 같은 형태로 구성되어 있다.

1) 헤더 (Header)
어떠한 알고리즘으로 암호화 할 것인지, 어떠한 토큰을 사용할 것 인지에 대한 정보가 들어있다.

2) 정보 (Payload)
전달하려는 정보(사용자 id나 다른 데이터들, 이것들을 클레임이라고 부른다)가 들어있다.
payload에 있는 내용은 수정이 가능하여 더 많은 정보를 추가할 수 있다. 그러나 노출과 수정이 가능한 지점이기 때문에 인증이 필요한 최소한의 정보(아이디, 비밀번호 등 개인정보가 아닌 이 토큰을 가졌을 때 권한의 범위나 토큰의 발급일과 만료일자 등)만을 담아야한다.

3) 서명 (Signature)
가장 중요한 부분으로 헤더와 정보를 합친 후 발급해준 서버가 지정한 secret key로 암호화 시켜 토큰을 변조하기 어렵게 만들어준다.
한가지 예를 들어보자면 토큰이 발급된 후 누군가가 Payload의 정보를 수정하면 Payload에는 다른 누군가가 조작된 정보가 들어가 있지만 Signatute에는 수정되기 전의 Payload 내용을 기반으로 이미 암호화 되어있는 결과가 저장되어 있기 때문에 조작되어있는 Payload와는 다른 결과값이 나오게 된다.
이러한 방식으로 비교하면 서버는 토큰이 조작되었는지 아닌지를 쉽게 알 수 있고, 다른 누군가는 조작된 토큰을 악용하기가 어려워진다.

JWT 동작원리

1) 사용자가 ID, PW를 입력하여 서버에 로그인 인증을 요청한다.
2) 서버에서 클라이언트로부터 인증 요청을 받으면, Header, PayLoad, Signature를 정의한다.
3) Hedaer, PayLoad, Signature를 각각 Base64로 한 번 더 암호화하여 JWT를 생성하고 이를 쿠키에 담아 클라이언트에게 발급한다.
4) 클라이언트는 서버로부터 받은 JWT를 로컬 스토리지에 저장한다. (쿠키나 다른 곳에 저장할 수도 있음) API를 서버에 요청할때 Authorization header에 Access Token을 담아서 보낸다.
5) 서버가 할 일은 클라이언트가 Header에 담아서 보낸 JWT가 내 서버에서 발행한 토큰인지 일치 여부를 확인하여 일치한다면 인증을 통과시켜주고 아니라면 통과시키지 않으면 된다.
6) 인증이 통과되면 PayLoad에 들어있는 유저의 정보들을 select해서 클라이언트에 돌려준다.
7) 클라이언트가 서버에 요청을 했는데, 만일 액세스 토큰의 시간이 만료되면 클라이언트는 리프래시 토큰을 이용해서 서버로부터 새로운 엑세스 토큰을 발급 받는다.

Generating JWT

  1. jsonwebtoken 라이브러리를 설치합니다. npm i jsonwebtoken,
    npm i @types/jsonwebtoken --only-dev

  2. .env.dev 파일에 SECRET_KEY를 설정합니다.

  3. app.module.ts 파일에서 ConfigModule.forRoot에 토큰을 지정하기 위해 사용 하는 PrivateKey인 SECRET_KEY를 설정합니다.

  4. users.service.ts 파일에서 ConfigModule.forRoot에 SECRET_KEY를 가져오기 위해 users.module.ts 파일에서 providers란에 ConfigService를 추가합니다.

  5. users.service.ts 파일에서 constructor에서 ConfigService를 불러옵니다.

  6. login() 함수에서 jsonwebtoken 라이브러리를 사용하여 token을 생성합니다.

ConfigService 적용 가능 이유

ConfigService 적용 가능한 이유는 'dependency injection' 때문이다. nest.js는 우리가 원하는 것의 class만 적어주면 그 정보를 가져다준다.
app.module.ts 파일에서 ConfigModule을 만들어줬고 여러 옵션들을 설정해줬다. 이 말은 ConfigModule이 정보가 살아있고 어딘가에 존재한다는 뜻이다. nest.js의 강점은 ConfigModule을 만들고 설정해주었을 때 configService를 가질 수 있게 된다는 것이다. 즉, users.module.ts 파일에서 providers란에 ConfigService를 요청하는 것만으로도 우리가 원하는 것을 불러올 수 있다.

출처1 : https://easyhomputer.tistory.com/41
출처2 : https://velog.io/@hahan/JWT%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80

profile
취준 개발자

0개의 댓글