질문을 삭제하지 말아주세요.!
 
1
0
-1

안녕하세요 초보개발자입니다..

어플 개발은 크고 작은 것을 해봤지만,

로그인 쪽관련해서, 그리고 막 이렇게 전체적으로 총괄해서 개발해본적은 없습니다.


최근 laravel jwt-auth + ionic 개발하며 공부하고 있습니다.

jwt-auth 개념은 이제 좀 알겠습니다 (정말 잘아는것인가.. ㄷㄷ?)

근데 궁금한것이


jwt로 얻은 토큰으로 그것을 헤더에 박아서,

현재 로그인이 누구인지, 이 사람이 정상적인 접근인지 파악한다고 치면,

유효기간이 지났을 때는 어떻게 되는것인지 이해가 안됩니다..


추측으로는 혹시나 하는데 그렇게 하는것인지 모르겠네요..

질문의 예상시나리오는 ..


  1. 로그인 한다.
  2. 토큰을 헤더에 박고 항상 통신한다.
  3. 토큰이 유효기간이 지난다
  4. 토큰에러로 인해 접근 거부 당한다 


리플레쉬를 하려면 서버랑 앱쪽에서 어떻게 처리해야하나요 ?

예상 플랜은

  1. 항상 토큰뿐만 아니라 아이디도 같이 보내서 유효기간이 지난 것은 다시 재 갱신한다. ( 말도 안되는 것같고..)
  2. 유효가 끝나면 다시 로그인하게 한다 ( 이것도 좀 이상하고..)
  3. 정상적인 사용자라면 토큰 끝나기전에 계속 갱신한다. ( 이것도 이상하고..)


너무 당연한 질문인지 다들 아시는지 검색을 해도 잘모르겠네요.

조언 및 팁 부탁드립니다. 선배님들..


ps ..

로그인할 때마다 갱신되면 괜찮지만,

자동 로그인 기능이 있을 경우는 어떻게 되는 것인가도 궁금합니다.

    CommentAdd your comment...

    1 answer

    1.  
      3
      2
      1

      제가 쓴 책 [라라벨로 배우는 실전 PHP 웹 프로그래밍] "33.2 JWT 인증 (p.392)" 부분을 참고하시면 좋겠습니다. 책에서는 \Tymon\JWTAuth\Middleware\GetUserFromToken이란 미들웨어를 이용하고, 이 미들웨어를 통과하지 못해서 오류 응답을 받았을 때, 오류 응답의 "error" 필드 값으로 받은 Enum 메시지를 통해서 클라이언트가 토큰 갱신 또는 토큰 재발급을 제어할 수 있도록 하고 있습니다.

      설명을 위해 TTL=60분, REFRESH_TTL=2주라 가정하겠습니다.

       ① 최초 발급             ② 토큰 갱신                                  ③ 최초 발급
       t           t+60분                                     t+2주
      -|-----------|---------|---------------...--------------|---------|------------>

      ① 최초 발급

      - 클라이언트는 로그인 UI를 통해 ID와 PW를 제공하고, 서버로 부터 JWT를 발급받습니다
      - 클라이언트는 발급받은 토큰을 자신의 저장소에 보관해둡니다.
      - 이후 클라이언트는 API를 호출할 때마다 요청 헤더에 JWT를 달아서 보냅니다. 서버는 미들웨어를 이용해서 토큰이 유효한지 검사합니다.

      ② 토큰 갱신

      - 클라이언트는 평상시처럼 요청 헤더에 JWT를 달아서 API를 사용합니다.
      - JWT가 만료됐으므로, 서버의 미들웨어에서 토큰이 만료됐다는 응답을 클라이언트에게 줍니다.
      - 클라이언트는 예외 응답을 캐치하고, 만료된 JWT를 토큰 갱신 엔드포인트로 제출합니다.
      - 서버는 클라이언트가 제출한 JWT를 확인하여, 갱신 가능한 토큰이라면, 새 JWT를 발급해 줍니다.
      - 클라이언트는 발급받은 토큰을 자신의 저장소에 보관해두고, 다음 토큰 만료시각까지 API를 계속 사용합니다.

      ③ 최초 발급

      - 클라이언트는 평상시처럼 요청 헤더에 JWT를 달아서 API를 사용합니다.
      - JWT가 만료됐으므로, 서버의 미들웨어에서 토큰이 만료됐다는 응답을 클라이언트에게 줍니다.
      - 클라이언트는 예외 응답을 캐치하고, 만료된 JWT를 토큰 갱신 엔드포인트로 제출합니다.
      - 서버는 클라이언트가 제출한 JWT를 확인해보니, 갱신 가능 기간이 지났습니다. 클라이언트에게 더 이상 갱신할 수 없다고 알려줍니다.
      - 클라이언트는 예외 응답을 캐치하고, 로그인 UI를 띄웁니다. 그 다음은 ①~③ 과정의 반복인거죠.


      이상의 내용은 하나의 구현 예일뿐입니다. 구현 디테일이라 JWT 스펙에서는 다루지 않습니다. 즉, 구현 방법에 정답이 없으며, 서버와 클라이언트가 약속하기 나름입니다. 매번 리프레시하는 것도 틀린 방법이라 할 수 없습니다.


      최근에 JWT를 적용했던 예제 프로젝트의 PR 링크도 참고하시면 좋겠습니다.

      https://github.com/appkr/db-lock-poc/pull/3/files

      1. 안유성

        감사합니다 ^^

      2. 김영우

        ② 토큰 갱신

        - 클라이언트는 평상시처럼 요청 헤더에 JWT를 달아서 API를 사용합니다.
        - JWT가 만료됐으므로, 서버의 미들웨어에서 토큰이 만료됐다는 응답을 클라이언트에게 줍니다.
        - 클라이언트는 예외 응답을 캐치하고, 만료된 JWT를 토큰 갱신 엔드포인트로 제출합니다.
        - 서버는 클라이언트가 제출한 JWT를 확인하여, 갱신 가능한 토큰이라면, 새 JWT를 발급해 줍니다.
        - 클라이언트는 발급받은 토큰을 자신의 저장소에 보관해두고, 다음 토큰 만료시각까지 API를 계속 사용합니다.


        게시물 작성시 '등록' 버튼을 눌렀을 때, 토큰이 만료된 경우라면 위 과정을 거친 후 게시물 등록 완료까지 가야할까요?


        애매하네요. 비동기적으로 게시물 등록을 전송했을 경우...

        1. 클라이언트 → 서버 : 게시물 등록 요청

        2. 서버 → 클라이언트 : 만료

        3. 클라이언트 → 서버 : 갱신 요청

        4. 서버 → 클라이언트 : 갱신

        5. 클라이언트는 갱신 후 다시 게시물 등록 버튼을 누른다?


        이게 맞을 것인지...


        1. 클라이언트 → 서버 : 게시물 등록 요청

        2. 서버 : 만료된 토큰을 갱신 후 헤더에 포함, 요청한 게시물 등록을 완료


        이 경우가 맞을지 애매하네요.


        그리고.. 궁금한 것은.. JWT의 장점 중 하나가 "TTL을 짧게하여 토큰이 유출됐을 경우 오남용을 줄인다." 이지 않습니까?

        근데, 서버에서 토큰 갱신을 자동으로 하던, 클라이언트에서 서버에 갱신 요청을 하던, 둘 다 충분히 누구도 가능한 일이지요.

        그렇다면 누군가 토큰을 가로채고 갱신하면 그 장점은 없어지지 않나 싶습니다.

        반론으로, "갱신한 토큰의 이전 토큰을 인증해버리면 갱신한 토큰은 사용할 수 없도록하는 블랙리스트를 사용하면 된다"라고 말씀하신다면, 또 의문이 드는 것은... 토큰을 가로챌 수 있단 것은, TTL이 긴 갱신된 토큰도 가로챌 수 있단 것이지 않습니까? 그래서 과연 JWT가 특별한 장점을 갖고있는지 모르겠습니다...


        다른 곳들은 어떤가 궁금해서 페이스북을 봤더니, 토큰을 쿠키에 저장하더라구요.

        이 때 토큰의 수명이 얼마나될지 모르겠지만 쿠키의 수명은 3개월을 주더라구요.

        3개월이면 일반적인 서비스에선 충분할 것 같아서 드는 생각인데, 그냥 갱신 토큰을 사용하지 않고, 기본 토큰 자체를 그 정도로 설정하고 쭉 사용해도 될 지 궁금하네요.


        그리고 추가적으로 쿠키의 수명과 토큰의 수명이 같다면 (혹은 쿠키의 수명이 더 짧다면), 실제로 토큰이 만료됐다는 메시지를 받을 일이 없을 것 같은데... 페이스북처럼 쿠키에 토큰을 저장할 때, 쿠키의 수명은 토큰의 수명보다 길게 해줘야할까요? (만약 그렇다면, 굳이 일부러 갱신 토큰을 위해 그래야하는가, 그것도 궁금합니다...)

      3. 김주원

        질문을 두번 읽어 봤는데요. 클라이언트는 구현하기 나름이며, 정답은 없는 듯 합니다.
        제 짧은 경험에 비추어 봤을 때, 일반적으로 토큰 갱신하는데 사용자와의 상호작용이 들어가지는 않았습니다 (사용자가 그 복잡한 만료/갱신을 알고, 버튼을 두 번 눌러야할 이유가 없지요).

        예 말씀하신대로 변조가 어렵다는 것이 JWT의 장점중의 하나이긴한데요. 그 보다 더 큰 장점은 토큰 안에 커스텀 클레임을 담을 수 있다는 점입니다. 가령, Oauth에서도 accessToken으로 JWT를 사용할 수 있고, 헤더에 달린 accessToken을 파싱하는 것 만으로도 필요한 정보를 얻을 수 있다는 장점이 있습니다. exp, iss, nbf 등의 클레임은 안쓰면 그만입니다. 갱신도 안쓰면 그만입니다.

        클라이언트(curl, Android, iOS, Web Browser, ...)가 서버로 부터 발급 받은 토큰(JWT or any)을 어디에 저장할 지는 클라이언트 로직입니다. xml에 저장할 수도 있고, SQLite에 저장할 수도 있겠지요. 추측컨대, 페북은 HTML5를 지원하지 않는 클라이언트를 위해 localStorage가 아니라 범용적인 Cookie Storage를 택한것이 아닐까 싶습니다.

      4. 김영우

        항상 의문을 갖고 사용해왔는데, 결론은 내려주시니 마음이 편안해지네요.

        JWT측이나, 외국인분들도 어떻게 사용하란 명확한 답은 주시지 않더라구요.

        덕분에 잘 배우고 갑니다! ^^

      CommentAdd your comment...