인프런 커뮤니티 질문&답변

Mountain님의 프로필 이미지
Mountain

작성한 질문수

Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)

Users Microservice - AuthorizationHeaderFilter 추가

secretkey의 용도, 토큰의 위,변조 검증, userId검증로직 질문드립니다.

작성

·

1K

1

강사님 안녕하세요. 좋은 강의 잘 듣고 있습니다. 강의 중 궁금점이 생겨 질문드립니다.

 

1. secret key의 용도

 

강의 중 언급해주신 jwt.io 사이트에서는 secret key값 없이 token을 복호화 할 수 있음을 확인했습니다.

즉, 데이터(payload)의 검증 과정에서는 secret key가 필요하지 않아도 가능하다.로 받아들여지는데요.. 

그렇다면 secret key의 용도는 token에 내포된 데이터(payload)를 보호하기 위함이 아니라, "application내에서 복호화가 가능한 token인지 확인하는 용도" 가 맞을까요 ??

 

 

2. 토큰의 위변조 검증

 

다른 질문을 참조하였을 때, 토큰의 위변조 확인 위해 request header의 userId와 token에서 얻은 userId를 비교하는 방법을 취했다고 이해하였습니다.

하지만 jwt.io에서 sercret key 없이도 userId를 얻을 수 있기 때문에 위,변조에 있어 취약하지 않을까? 라는 생각이 듭니다..

실제 상용되는 서비스라면, token의 위,변조를 일반적으로 어떻게 검증하는지 궁금합니다.. !

 

3. userId의 검증

 

강의에서 요구하신 userId를 검증하는 로직을 추가한다고 하면. 아래와 같이 작성하면 될까요 ?

 

위,변조 검증을 위한 조건을 "request header에 userId 필드가 존재해야 한다"로 가정하고 코드를 작성해보았습니다.

 

1. header에서 userId 필드를 검증하고, userId를 추출하여 isJwtValid를 호출할 때 인자로 함께 전달.

 

2. expire date를 검증

3. token에서 추출한 userId와 header의 userId를 비교

 

이런 식으로 진행하는게 강의에서 구현하라고 의도하신 바가 맞을까요 ??

답변 3

0

Dowon Lee님의 프로필 이미지
Dowon Lee
지식공유자

안녕하세요, 이도원입니다. 

secret key는 토큰을 생성하기 위한 키워드로 사용되고 있고, 간단하게나 복잡하게 작성할수 있습니다. 따라서 얼마든지 유추해 낼수 있습니다. 실제로 (나쁜의미에서의 )해킹을 시도하는 사람들은 정말 단순한 방법을 통해 ㅋ키나 암호를 유추해 내는 과정부터 시작합니다. 따라서 얼마든지 노출될 위험은 있습니다. 말씀하신 것처럼 노출되지 않았다면 문제될 일은 없겠지요. 추가로 header에 userId를 저장한 이유는 토큰에 저장된 userId와 비교하는 용도라고 보시면 될 것 같습니다. 웹 사이트에서 어떤 파일을 다운로드 받을 때 해당 파일에 대한 checksum을 제공하는 이유가 원래 파일의 사이즈와 다운받은 파일의 사이즈 등을 비교해서 문제가 있는 파일인지의 여부를 1차적으로 확인할 수 있는 것처럼, 사용자에게 전달된 토큰과 userId를 비교함으로써, userId가 안전하는 것을 확인해 볼 수도 있을 겁니다. 불필요한 작업이라 판단되시면 삭제해도 무방합니다. 

감사합니다. 

0

저도 강의를 보면서 이 부분이 이해가 안가서 댓글 남깁니다.

반복적으로 들어오는 질문인 것 같은데.

다른 질문들의 답변을 읽어도 와닿지가 않네요.

강사님이 아니더라도 이해하신분은 답글 남겨주세요 🙏

 

애초에 secret key 가 노출되지 않았으면 토큰을 위조(토큰을 새로 만듬) 하거나 변조(토큰을 수정) 할 수 있나요?

secret 값을 모르는 상황에서 토큰을 위변조해봤자. 서버에서 토큰을 parse 과정에서 에러가 발생하겠죠.

만약 secret key가 노출되어서 위변조 할 수 있다고 가정하면. 위변조 하는 사람이 토큰을 만들 때 사용한 userId 를 userId header에 담아주면 userId를 비교하는 로직은 의미가 없는 게 아닌가요?

 

강사님의 위의 답변 중 일부 내용입니다. 

apigateway-service의 header 값에 token과 userId를 직접 전달하고, 복호화 된 token의 정보(userId를 저장하였습니다)와 userId를 비교하여 token의 위변조가 없었는지 확인할 수도 있고

token의 userId는 payload 부분에 들어있고 payload는 암호화가 아닌 base64로 인코딩 되어있기 때문에 secret key 가 없어도 누구나 decode 할 수 있죠. 누구나 얻어낼 수 있는 userId를 따로 헤더에 담고 비교하는 게 위변조를 어떻게 알 수 있는지 궁금합니다.

0

Dowon Lee님의 프로필 이미지
Dowon Lee
지식공유자

안녕하세요, 이도원입니다. 

token에 userId를 저장하였기 때문에, 해당 토큰이 정상적으로 복호화 되었다면, 취득하게 되는 userId의 정상유무 및 권한유무 등을 확인해 보실 수 있습니다. 말씀하신 내용에서 secret key 값이 없이 token을 복호화 할 수 있다는 것은 어떤 의미인지 알려주실 수 있을까요? apigateway-service에 있는 AuthorizationHeaderFilter.java의 isJwtValid메소드에서 다음과 같이 signing key를 이용하여 복호화를 하고 있으며, 

try {
subject = Jwts
.parser()
.setSigningKey(env.getProperty("token.secret"))
.parseClaimsJws(jwt).getBody()
.getSubject();
} catch (Exception ex) {
returnValue = false;
}

해당 키가 틀릴 경우에는 다음과 같이 오류가 발생하고 있습니다. 

"JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted."

apigateway-service에서 1차적으로 token의 유무 및 사용가능 여부를 확인 후에 user-service로 요청을 넘기고 있어서, 특정 API의 접근을 제어하고 있습니다. 물론 user-service에서도 인증에 관련된 부분이 추가되면 더 안전할 것입니다. apigateway-service의 header 값에 token과 userId를 직접 전달하고, 복호화 된 token의 정보(userId를 저장하였습니다)와 userId를 비교하여 token의 위변조가 없었는지 확인할 수도 있고, DB에서 확인하거나, 별도위 인증 서비스를 추가하여 해당 token이 정상인지 확인하도록 할수도 있습니다. 

 

추가 질문사항 있으시면 글 남겨주세요.

 

감사합니다. 

 

 

JOSE에 대해서 찾아보시면 좋을 것 같습니다.

JSON Object Signing and Encryption(JOSE) specfications에 의하면 JWT는 JWE와 JWS로 구분됩니다.

JWT(JSON Web Token)

  • JWS(JSON Web Signature)
    • 서버에서 인증을 증거로 인증 정보를 서버의 private key로 서명한 것을 토큰화한 것
  • JWE(JSON Web Encryption)
    • 서버와 클라이언트 사이의 암호화된 데이터를 토큰화한 것

JWK( JSON Web Key)

jwt.io에서 발급받은 토큰은 단순히 JWS로 Encode, Decode 되는 과정을 보여주기 위함일 뿐, 실제로는 인증 정보에 해당하는 Payload에 대해 서버측에서의 암호화 과정이 필요합니다.

클라이언트가 인증 요청을 하게되면 서버 측에서 Payload에 담길 인증 정보를 encrypt 한 후에 base64로 encode 해야 합니다. 따라서, 서버에서 Payload를 제대로 암호화 했다면 JWT의 Payload를 decode하더라도 암호화된 값이 나와야 합니다.

Mountain님의 프로필 이미지
Mountain
질문자

와! 감사합니다 !!

Mountain님의 프로필 이미지
Mountain

작성한 질문수

질문하기