JWT와 그리고 2FA 대해

Updated:

기존 JWT기반에서 2FA (Factor Authentication) 추가 구현


  • 사내에서 기존에 적용했던 Spring Security가 적용된 JWT 기반의 Login 인증에 2FA를 추가로 구현해야 하는 상황이 생겼다
  • 그래서, 기존 비즈니스 로직을 살짝 수정 하는 방향으로 흐름을 잡았다
    • 상세 로직은 아래와 같다
      sequenceDiagram
      autonumber
          actor A as 관리자
          participant B as FrontEnd
          participant C as BackEnd
          participant D as 담당자
          A->>B: action 회원 가입
          B->>C: 회원 가입 API 실행
          C->>B: OTP 등록 위한 QRCode 제공
          A->>D: QRCode 제공해 Device에 OTP 등록하게 시킴
          D->>A: OTP 등록했다고 알려줌
          D->>B: action 로그인 
          B->>C: 로그인 API
          C->>B: 로그인 결과 반환 (only success or fail)
          B->>C: 2FA API
          C->>B: JWT Token 및 유효시간 반환
          B->>B: DashBoard redirect
          alt is 회원 가입 (email, password, role)
              B->>C: 회원 가입 API
              C->>B: QRCode 제공 (success, 2000, url)
          else is 회원 가입 실패
              B->>C: 회원 가입 API
              C->>B: 실패값 제공 (fail, 3000)
              activate B
              B->>B: 실패 UI 랜더링 및 실패 확인
              deactivate B
          end
      		alt is 로그인
              B->>C: 로그인 API (username, password)
              C->>B: 성공값 제공 (success, 2000)
          else is 회원 가입 실패
              B->>C: 로그인 API (위와 동일)
              C->>B: 실패값 제공 (fail, 3000)
              activate B
              B->>B: 실패 UI 랜더링 및 실패 확인
              deactivate B
          end
      		alt is 2FA
              B->>C: 2FA API (username, password, code (6 digit))
              C->>B: JWT 제공 (success, 2000, accessToken, refreshToken, accessTokenExpiredAt)
          else is 2FA 실패
              B->>C: 2FA API (위와 동일)
              C->>B: 실패값 제공 (fail, 3000)
              activate B
              B->>B: 실패 UI 랜더링 및 실패 확인
              deactivate B
          end
    
  • 그래서, 기존의 로그인 하던 방식에 추가로 code값을 받아서 2FA 인증을 구현하게 했으며
  • 원래 login 하던 부분을 단순하게 만들었다
    • ID와 PW가 일치하는지에 대한 검증만 체크
  • 상세 로직
    • AuthorizationFilter 에서 특정 URL을 허용하는 방향으로 먼저 잡았다
      • 회원가입, 로그인과 관련된 부분은 Spring Security를 타지 않고 바로 Controller로 가야 하기 때문
    • 실제 로그인 (여기서는 2FA 관련 URL)이 들어오면 이 때, AuthenticationFilter를 타게 만든다
      • 아이디, 패스워드, 6자리 digit number의 유효성을 체크
  • 아쉬운 점
    • AuthenticationFilter를 custom한 URL도 허용하게 만들고 싶은데, /login 밖에 안되는 것 같고 아직 좀 더 검색중이다
      • UsernamePasswordAuthenticationFilter 를 상속받아서 쓰고 있는데, custom한 UsernamePasswordAuthenticationFilter를 만들면 해결 된다
    • 이미 앞선 login에서 username, password를 입력받게 해서 이미 검증은 끝났는데, Spring Security 내부에서 다시 username, password를 체크하기 위해 추가로 입력받았던 경우
      • 이건 AuthenticationProvider를 custom하게 별도로 구현해서 username과 password를 입력받지 않고, 다른 방법의 Filter를 사용하던지 다른 방법을 찾아서 구현이 필요할 듯
      • 공수가 많이 들어갈거 같고, 아직 잘 몰라서 시도는 못해봄
  • 출처

Leave a comment