Spring에서 JWT을 좀 더 자세히 알아보자!

Rookedsysc·2023년 10월 27일
0

사건의 발단☣️

현재 내 프로젝트의 구조는 다음과 같이 생겼다.

원래 api 모듈에 로그인, 토큰 발급, 토큰 검증 로직이 있었는데 apigw를 도입하면서 account에 따로 JWT Token 검증 API를 생성해서

apigw -> accout 모듈에서 Token 검증 후 라우팅 -> 목적지 서버

로 변경을 해줄려고 하다가 에러가 발생했다.

에러내용 : io.jsonwebtoken.UnsupportedJwtException: Signed Claims JWSs are not supported.

해결🎉

아마 많은 분들이 익숙한 코드일거라고 생각한다. 내 Validation 로직에서 parseClaimJwt 부분을 parseClaimJws로 변경해주면 이 문제는 해결된다.

	override fun validationTokenWithThrow(token: String?): Map<String, Any>? {
		val key = Keys.hmacShaKeyFor(secretKey?.toByteArray())
		
		val parser = Jwts
			.parserBuilder()
			.setSigningKey(key)
			.build()
		
		return try {
			val result = token?.let { parser.parseClaimsJwt(it) }
			HashMap(result?.body)
		} catch (e: Exception) {
			when (e) {
				is SignatureException -> {
					throw ApiException(TokenError.INVALID_TOKEN)
				}
				
				is ExpiredJwtException -> {
					throw ApiException(TokenError.EXPIRED_TOKEN)
				}
				
				else -> {
					throw ApiException(TokenError.TOEKN_EXCEPTION, e)
				}
			}
		}
	}

JWT Parse 분석 (실패)

Intellij에서 shift + shift를 누르고

Include non-project items 체크박스를 체크하고 DefaultJwtParser를 검색하면 다음과 같은 코드가 나온다.

이는 JwtParser를 구현해놓은 구현부이고 위에서 사용하는 parseClaimJwtparseClaimJws 함수가 여기에 구현되어 있다.

  • 위에서 진입하는 public <T> T parse(String compact, JwtHandler<T> handler) 함수 👇

만약 이 코드에서 body가 instanceof Claims면 return handler.onClaimsJws((Jws<Claims>) jws); 구문에 의해서 Exception 발생

parseClaimJwt에서는 parse() 함수를 통해서 claimJwt를 파싱하고 안되면 Signed JWSs are not supported에러를 발생시키게 된다.

동적 분석을 하면서 분석을 해본 결과

parseClainJwt() -> parse() -> parse() - (Jws<Claims>) jws 리턴 -> Exception 발생

문제는 parse 함수가 200줄이 넘어서 왜 (Jws<Claims>) jws이 return 되는지 분석할 수 없었다..

지선생님의견

parseClaimsJws(it) : 이 메서드는 주어진 JWT(토큰)를 파싱하고, JWT가 서명된 JWT (JWS)임을 가정합니다. 즉, JWT가 서명되어 데이터 무결성이 확인되어야 합니다. JWS는 JSON Web Signature의 약어로, 데이터가 안전하게 전달되었음을 보장합니다.
parseClaimsJwt(it) : 이 메서드는 주어진 JWT를 파싱하며, JWT에 서명 여부에 대한 가정을 하지 않습니다. 즉, JWT가 서명되었는지 여부를 확인하지 않고 데이터를 파싱합니다. 이 메서드는 서명이 없는 JWT (JWS가 아닌 경우) 또한 파싱할 수 있습니다.

0개의 댓글