220418 TIL

11855 단어 JWToAuthTILJWT

진짜 간단하게라도 TIL로 학습기록을 남겨보려고합니다. 하루동안의 학습이든 키워드이든 삽질이든 슥슥슥 적어서 메모로 남기는 식으로 적어보겠습니다. 틀린 내용이 많을 예정입니다 ㅎㅎ

학습 자료

https://opentutorials.org/course/3405
https://www.ietf.org/rfc/rfc6749.txt

서론

  • 지난 주 프로젝트에서 JWT (Json Web Token)에 대한 적용과 학습키워드가 있었다. 하지만 DB설계를 비롯한 드래그앤스왑에 따른 순서변경에 관한 로직, 그리고 배포에 시간을 많이 쏟으면서 적용하지 못했다.
  • 나중으로 넘기기에는 재밌어보이는 학습 주제였다. ㅎㅎ

JWT

  • 코드를 쳐보면서 flow를 익혀보려고 했다. flow는 사실 간단하다.

  • token은 server가 설정한 secret key와 암호화 알고리즘을 활용해서 encoding되고, decoding 하게되면 json data가 담겨있는 것을 확인할 수 있다.

  • client가 server로 부터 전달받은 token은 HTTP HEADER에 담기게 되며, client는 요청을 보낼 때 마다 token을 HEADER에 담아 보낼 수 있다.

  • 토큰을 활용할 때, 토큰이 탈취당한다면 어떻게 될까? 토큰을 탈취할 수 있다면, 아이디와 비밀번호를 모르고서도 탈취한 토큰의 유저에 로그인한 것과 같이 요청을 할 수 있다.

  • 이러한 문제 때문에, 토큰에는 expiration, 만료되는 시간이 포함되어있다. 토큰이 만료되는 시간은 서버가 각자의 기준을 정할 수 있지만, 토큰의 탈취에 대한 위험때문에 짧게 설정하는 것이 좋다.

  • 하지만 이렇게 토큰의 유효기간이 짧게 된다면, 토큰이 만료되었을 때마다 유저는 다시 로그인 요청해서 토큰을 새롭게 발급받아야 한다.

  • 그래서 필요한 것이 Refresh-token이다. 앞서 발급해주었던 토큰은 Access-Token으로 불린다.

  • 리프레쉬 토큰을 사용한다면 로그인 시 client에게 엑세스 토큰과 리프레쉬 토큰(엑세스 토큰보다 유효기간을 더 길게해서)을 같이 발급한다. 서버에서는 refresh-token을 DB에 저장해둔다. 그리고 엑세스 토큰이 만료되었다면, 클라이언트에게서 받은 리프레쉬 토큰을 확인해서 새롭게 엑세스 토큰을 발급해준다.

  • 구현마다 다르겠지만 리프레쉬 토큰도 탈취당할 위험이 있기 때문에, 새롭게 엑세스 토큰을 발급할 때, 리프레쉬 토큰도 새롭게 발급해준다.

  • 작성한 코드와 claim과 관련해서는 코드를 조금 더 정리하고 적용해본 뒤 더 자세히 정리해봐야겠다.

// gradle dependency
	runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.2'
    implementation 'io.jsonwebtoken:jjwt-api:0.11.2'
    runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.2'
public boolean isValidToken(String token) {
        try {
            Jws<Claims> claimsJws = Jwts.parserBuilder()
                                    .setSigningKey(secretKey)
                                    .build()
                                    .parseClaimsJws(token);
            String subject = claimsJws.getBody().getSubject();
            log.info("subject : {}", subject);
        } catch (ExpiredJwtException expiredJwtException) {
            log.info("token is expired");
            return false;
        } catch (MalformedJwtException malformedJwtException) {
            log.info("token is Malformed");
            return false;
        } catch (SignatureException signatureException) {
            log.info("token is wrong signature");
            return false;
        }

        return true;
    }
  • 일단 위의 코드는 토큰을 검증하는 코드이다. 검증하면서 터질수있는 예외를 try-catch를 통해서 확인해보려고 했다.
  • 전달받은 토큰을 임의로 수정해서 요청을 보냈을때 signatureException을 뱉어냈고, 토큰의 유효기간이 다되었다면 expiredJwtException을 뱉어냈다. malformedException은 아직 테스트해보지는 못했으나, 들어있어야할 calim, 즉 data를 가지고 있지 않은 상황에 발생할 것 같다??

OAuth

  • 생활코딩의 Oauth 강의를 들으면서 Oauth flow를 살펴봤다.
  • JWT의 flow와 굉장히 비슷하다. 토큰을 발급하고, 검증하는 기능이 직접 서비스하는 서버가 아닌 google, github과 같은 서버에서 처리해주는 것이라고 생각하면 될 것 같다.
  • 이번 프로젝트에서 github token을 적용해볼 것 같다. 적용 및 테스트해보고 코드를 간단하게 정리해봐야겠다.
  +--------+                                           +---------------+
  |        |--(A)------- Authorization Grant --------->|               |
  |        |                                           |               |
  |        |<-(B)----------- Access Token -------------|               |
  |        |               & Refresh Token             |               |
  |        |                                           |               |
  |        |                            +----------+   |               |
  |        |--(C)---- Access Token ---->|          |   |               |
  |        |                            |          |   |               |
  |        |<-(D)- Protected Resource --| Resource |   | Authorization |
  | Client |                            |  Server  |   |     Server    |
  |        |--(E)---- Access Token ---->|          |   |               |
  |        |                            |          |   |               |
  |        |<-(F)- Invalid Token Error -|          |   |               |
  |        |                            +----------+   |               |
  |        |                                           |               |
  |        |--(G)----------- Refresh Token ----------->|               |
  |        |                                           |               |
  |        |<-(H)----------- Access Token -------------|               |
  +--------+           & Optional Refresh Token        +---------------+

좋은 웹페이지 즐겨찾기