Backend/JAVA

JAVA JWT payload 가져오는 방법 / 만료시간 체크

keepbang 2021. 6. 9. 17:26

java에서 jwt payload를 가져오는 방법에대해 정리하보고자 한다.

 

JWT 개념
JWT(Json Web Token)란 Json 포맷을 이용하여 사용자에 대한 속성을 저장하는 Claim 기반의 Web Token 이다.
JWT는 토큰 자체를 정보로 사용하는 Self-Contained 방식 으로 정보를 안전하게 전달한다.
주로 회원 인증이나 정보 전달에 사용된다

intelliJ
maven
java 8

 

지금까지 JWT안에 payload를 가져올려면 public key나 private key가 있어야하는줄 알았는데

아래 사이트에서 바로 내용을 확인 할 수 있는것을 보고 key가 필요없다는걸 알게 되었다....

 

 

JWT.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io

 


 

maven 프로젝트에서 사용한 dependency는 아래와 같다.

...
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.16.0</version>
        </dependency>

        <dependency>
            <groupId>com.nimbusds</groupId>
            <artifactId>nimbus-jose-jwt</artifactId>
            <version>9.10</version>
        </dependency>
...

 

간단하게 java-jwt를 사용하여 JWT의 내용을 확인 할 수 있다.

 

DecodedJWT decodedJWT = JWT.decode({jwt_token});

System.out.println(decodedJWT.getClaims().toString());

 

여기서 Token헤더, 페이로드, 서명을 점으로 구분하는 구조로 되어있다.

 

DecodedJWT인터페이스에는 PayloadHeader가 상속되어있어

getAlgorithm 로 알고리즘을 확인 할 수 있고 getExpiresAtToken의 만료시간을 체크 할 수 있다.

 

...
        try{
            if(decodedJWT.getExpiresAt().before(new Date())){
                throw new JWTVerificationException("The Token has expired on "+decodedJWT.getExpiresAt());
            }
        }catch(JWTVerificationException e){
            System.out.println(e.getMessage());
        }
...

 


 

JWT가 넘어오기전에 payload가 암호화되어 넘어오는 경우가 있다.

 

이렇게 암호화된 데이터는 4개의 점으로 구분되어 있고 당연히 암호화를 풀려면 복호화를 할 수 있는 private key가 필요하다.

 

암호화된 JWT는 nimbus-jose-jwt를 사용하여 payload를 복호화 해준다.

...
    PrivateKey privateKey = getPrivateKey(filePath);

    EncryptedJWT jwt = EncryptedJWT.parse({token});

    //null 출력됨, decrypt를 해줘야 payload가 보임
    System.out.println(jwt.getPayload()); 

    //privateKey를 가지고 RSADecrypter객체 생성
    RSADecrypter decrypter = new RSADecrypter(privateKey);

    //jwt 복호화
    jwt.decrypt(decrypter);

    //payload에 데이터 출력
    System.out.println(jwt.getPayload());
...

public static String decrypt(String cipherText, PrivateKey privateKey)
            throws IOException, GeneralSecurityException {
        byte[] decodedCipherText = cipherText.getBytes();
        System.out.println("Decoded Cipher text == " + decodedCipherText.toString());
        OAEPParameterSpec oaepParams = new OAEPParameterSpec(
                "SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), PSource.PSpecified.DEFAULT);
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        // cipher.init(Cipher.DECRYPT_MODE, privateKey);
        System.out.println("algo " + cipher.getAlgorithm());
        System.out.println("cipherText == " + cipherText);
        return new String(cipher.doFinal(decodedCipherText), "UTF-8");
}

public static RSAPrivateKey getPrivateKeyFromString(String key) throws IOException, GeneralSecurityException {
    String privateKeyPEM = key;
    // Remove the first and last lines
    privateKeyPEM = privateKeyPEM.replace("-----BEGIN RSA PRIVATE KEY-----", "");
    privateKeyPEM = privateKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");
    privateKeyPEM = privateKeyPEM.replace("-----BEGIN PRIVATE KEY-----", "");
    privateKeyPEM = privateKeyPEM.replace("-----END PRIVATE KEY-----", "");
    System.out.println("privatekey pem after removal == " + privateKeyPEM);
    byte[] encoded = java.util.Base64.getDecoder().decode(privateKeyPEM); // for util base64
    KeyFactory kf = KeyFactory.getInstance("RSA");
    RSAPrivateKey privKey = (RSAPrivateKey) kf.generatePrivate(new PKCS8EncodedKeySpec(encoded));
    System.out.println("RSA Private Key after encoded: " + privKey);
    return privKey;
}

public static RSAPrivateKey getPrivateKey(String filename) throws IOException, GeneralSecurityException {
    String privateKeyPEM = getKey(filename);
    System.out.println("PrivateKeyPem == " + privateKeyPEM);
    return getPrivateKeyFromString(privateKeyPEM);
}

 

static 메서드들은 privateKey file을 PrivateKey객체로 만들어주는 메서드다.

 

[참고]

 

[Server] JWT(Json Web Token)란?

현대 웹서비스에서는 토큰을 사용하여 사용자들의 인증 작업을 처리하는 것이 가장 좋은 방법이다. 이번에는 토큰 기반의 인증 시스템에서 주로 사용하는 JWT(Json Web Token)에 대해 알아보도록 하

mangkyu.tistory.com