Skip to content

Commit

Permalink
Merge pull request #114 from auth0/force-bytes-charset
Browse files Browse the repository at this point in the history
Make getBytes use UTF-8 charset
  • Loading branch information
hzalaz authored Dec 5, 2016
2 parents 8d70e3b + fea96e8 commit 3135718
Show file tree
Hide file tree
Showing 16 changed files with 78 additions and 69 deletions.
21 changes: 11 additions & 10 deletions lib/src/main/java/com/auth0/jwt/JWTCreator.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.apache.commons.codec.binary.Base64;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
* The JWTCreator class holds the sign method to generate a complete DecodedJWT (with Signature) from a given Header and Payload content.
* The JWTCreator class holds the sign method to generate a complete JWT (with Signature) from a given Header and Payload content.
*/
@SuppressWarnings("WeakerAccess")
public final class JWTCreator {
Expand Down Expand Up @@ -50,7 +51,7 @@ static JWTCreator.Builder init() {
}

/**
* The Builder class holds the Claims that defines the DecodedJWT to be created.
* The Builder class holds the Claims that defines the JWT to be created.
*/
public static class Builder {
private final Map<String, Object> payloadClaims;
Expand Down Expand Up @@ -139,7 +140,7 @@ public Builder withIssuedAt(Date issuedAt) {
}

/**
* Add a specific DecodedJWT Id ("jti") claim.
* Add a specific JWT Id ("jti") claim.
*
* @param jwtId the Token Id value.
* @return this same Builder instance.
Expand Down Expand Up @@ -172,12 +173,12 @@ public Builder withClaim(String name, Object value) throws IllegalArgumentExcept
}

/**
* Creates a new instance of the DecodedJWT with the specified payloadClaims.
* Creates a new JWT and signs is with the given algorithm
*
* @param algorithm the Algorithm to use on the DecodedJWT signing.
* @return a new DecodedJWT instance.
* @param algorithm used to sign the JWT
* @return a new JWT token
* @throws IllegalArgumentException if the provided algorithm is null.
* @throws JWTCreationException if the Claims coudln't be converted to a valid JSON or there was a problem with the signing key.
* @throws JWTCreationException if the claims could not be converted to a valid JSON or there was a problem with the signing key.
*/
public String sign(Algorithm algorithm) throws IllegalArgumentException, JWTCreationException {
if (algorithm == null) {
Expand All @@ -197,11 +198,11 @@ private void addClaim(String name, Object value) {
}

private String sign() throws SignatureGenerationException {
String header = Base64.encodeBase64URLSafeString((headerJson.getBytes()));
String payload = Base64.encodeBase64URLSafeString((payloadJson.getBytes()));
String header = Base64.encodeBase64URLSafeString((headerJson.getBytes(StandardCharsets.UTF_8)));
String payload = Base64.encodeBase64URLSafeString((payloadJson.getBytes(StandardCharsets.UTF_8)));
String content = String.format("%s.%s", header, payload);

byte[] signatureBytes = algorithm.sign(content.getBytes());
byte[] signatureBytes = algorithm.sign(content.getBytes(StandardCharsets.UTF_8));
String signature = Base64.encodeBase64URLSafeString((signatureBytes));

return String.format("%s.%s", content, signature);
Expand Down
2 changes: 1 addition & 1 deletion lib/src/main/java/com/auth0/jwt/JWTDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import java.util.List;

/**
* The JWTDecoder class holds the decode method to parse a given Token into it's DecodedJWT representation.
* The JWTDecoder class holds the decode method to parse a given JWT token into it's JWT representation.
*/
@SuppressWarnings("WeakerAccess")
final class JWTDecoder extends JWT {
Expand Down
19 changes: 10 additions & 9 deletions lib/src/main/java/com/auth0/jwt/JWTVerifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@
import com.auth0.jwt.interfaces.DecodedJWT;
import org.apache.commons.codec.binary.Base64;

import java.nio.charset.StandardCharsets;
import java.util.*;

/**
* The JWTVerifier class holds the verify method to assert that a given Token has not only a proper DecodedJWT format, but also it's signature matches.
* The JWTVerifier class holds the verify method to assert that a given Token has not only a proper JWT format, but also it's signature matches.
*/
@SuppressWarnings("WeakerAccess")
public final class JWTVerifier {
Expand All @@ -30,7 +31,7 @@ public final class JWTVerifier {
/**
* Initialize a JWTVerifier instance using the given Algorithm.
*
* @param algorithm the Algorithm to use on the DecodedJWT verification.
* @param algorithm the Algorithm to use on the JWT verification.
* @return a JWTVerifier.Verification instance to configure.
* @throws IllegalArgumentException if the provided algorithm is null.
*/
Expand All @@ -39,7 +40,7 @@ static JWTVerifier.Verification init(Algorithm algorithm) throws IllegalArgument
}

/**
* The Verification class holds the Claims required by a DecodedJWT to be valid.
* The Verification class holds the Claims required by a JWT to be valid.
*/
public static class Verification {
private final Algorithm algorithm;
Expand Down Expand Up @@ -154,7 +155,7 @@ public Verification acceptIssuedAt(long leeway) throws IllegalArgumentException
}

/**
* Require a specific DecodedJWT Id ("jti") claim.
* Require a specific JWT Id ("jti") claim.
*
* @param jwtId the required Id value
* @return this same Verification instance.
Expand Down Expand Up @@ -232,9 +233,9 @@ private void requireClaim(String name, Object value) {
/**
* Perform the verification against the given Token, using any previous configured options.
*
* @param token the String representation of the DecodedJWT.
* @return a verified DecodedJWT.
* @throws JWTVerificationException if any of the required contents inside the DecodedJWT is invalid.
* @param token to verify.
* @return a verified and decoded JWT.
* @throws JWTVerificationException if any of the required contents inside the JWT is invalid.
*/
public DecodedJWT verify(String token) throws JWTVerificationException {
DecodedJWT jwt = JWTDecoder.decode(token);
Expand All @@ -245,14 +246,14 @@ public DecodedJWT verify(String token) throws JWTVerificationException {
}

private void verifySignature(String[] parts) throws SignatureVerificationException {
byte[] content = String.format("%s.%s", parts[0], parts[1]).getBytes();
byte[] content = String.format("%s.%s", parts[0], parts[1]).getBytes(StandardCharsets.UTF_8);
byte[] signature = Base64.decodeBase64(parts[2]);
algorithm.verify(content, signature);
}

private void verifyAlgorithm(DecodedJWT jwt, Algorithm expectedAlgorithm) throws AlgorithmMismatchException {
if (!expectedAlgorithm.getName().equals(jwt.getAlgorithm())) {
throw new AlgorithmMismatchException("The provided Algorithm doesn't match the one defined in the DecodedJWT's Header.");
throw new AlgorithmMismatchException("The provided Algorithm doesn't match the one defined in the JWT's Header.");
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/src/main/java/com/auth0/jwt/algorithms/Algorithm.java
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ protected Algorithm(String name, String description) {
}

/**
* Getter for the name of this Algorithm, as defined in the DecodedJWT Standard. i.e. "HS256"
* Getter for the name of this Algorithm, as defined in the JWT Standard. i.e. "HS256"
*
* @return the algorithm name.
*/
Expand Down
2 changes: 1 addition & 1 deletion lib/src/main/java/com/auth0/jwt/interfaces/DecodedJWT.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.auth0.jwt.interfaces;

/**
* The DecodedJWT class represents a Json Web Token.
* Class that represents a Json Web Token that was decoded from it's string representation.
*/
public interface DecodedJWT extends Payload, Header, Signature {
String getToken();
Expand Down
8 changes: 4 additions & 4 deletions lib/src/main/java/com/auth0/jwt/interfaces/Header.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
package com.auth0.jwt.interfaces;

/**
* The Header class represents the 1st part of the DecodedJWT, where the Header value is hold.
* The Header class represents the 1st part of the JWT, where the Header value is hold.
*/
public interface Header {

/**
* Getter for the Algorithm "alg" claim defined in the DecodedJWT's Header. If the claim is missing it will return null.
* Getter for the Algorithm "alg" claim defined in the JWT's Header. If the claim is missing it will return null.
*
* @return the Algorithm defined or null.
*/
String getAlgorithm();

/**
* Getter for the Type "typ" claim defined in the DecodedJWT's Header. If the claim is missing it will return null.
* Getter for the Type "typ" claim defined in the JWT's Header. If the claim is missing it will return null.
*
* @return the Type defined or null.
*/
String getType();

/**
* Getter for the Content Type "cty" claim defined in the DecodedJWT's Header. If the claim is missing it will return null.
* Getter for the Content Type "cty" claim defined in the JWT's Header. If the claim is missing it will return null.
*
* @return the Content Type defined or null.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.auth0.jwt.exceptions.JWTDecodeException;

/**
* The JWTPartsParser class defines which parts of the DecodedJWT should be converted to it's specific Object representation instance.
* The JWTPartsParser class defines which parts of the JWT should be converted to it's specific Object representation instance.
*/
public interface JWTPartsParser {

Expand Down
4 changes: 2 additions & 2 deletions lib/src/main/java/com/auth0/jwt/interfaces/Payload.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import java.util.List;

/**
* The Payload class represents the 2nd part of the DecodedJWT, where the Payload value is hold.
* The Payload class represents the 2nd part of the JWT, where the Payload value is hold.
*/
public interface Payload {

Expand Down Expand Up @@ -53,7 +53,7 @@ public interface Payload {
/**
* Get the value of the "jti" claim, or null if it's not available.
*
* @return the DecodedJWT ID value or null.
* @return the JWT ID value or null.
*/
String getId();

Expand Down
6 changes: 3 additions & 3 deletions lib/src/main/java/com/auth0/jwt/interfaces/Signature.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.auth0.jwt.interfaces;

/**
* The Signature class represents the 3rd part of the DecodedJWT, where the Signature value is hold.
* The Signature class represents the 3rd part of the JWT, where the Signature value is hold.
*/
public interface Signature {

/**
* Getter for the Signature contained in the DecodedJWT as a Base64 encoded String.
* Getter for the Signature contained in the JWT as a Base64 encoded String.
*
* @return the Signature of the DecodedJWT.
* @return the Signature of the JWT.
*/
String getSignature();
}
5 changes: 3 additions & 2 deletions lib/src/test/java/com/auth0/jwt/JWTDecoderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.junit.Test;
import org.junit.rules.ExpectedException;

import java.nio.charset.StandardCharsets;
import java.util.Date;

import static org.hamcrest.MatcherAssert.assertThat;
Expand Down Expand Up @@ -200,8 +201,8 @@ public void shouldGetNullClaimIfClaimValueIsNull() throws Exception {
//Helper Methods

private DecodedJWT customJWT(String jsonHeader, String jsonPayload, String signature) {
String header = Base64.encodeBase64URLSafeString(jsonHeader.getBytes());
String body = Base64.encodeBase64URLSafeString(jsonPayload.getBytes());
String header = Base64.encodeBase64URLSafeString(jsonHeader.getBytes(StandardCharsets.UTF_8));
String body = Base64.encodeBase64URLSafeString(jsonPayload.getBytes(StandardCharsets.UTF_8));
return JWTDecoder.decode(String.format("%s.%s.%s", header, body, signature));
}

Expand Down
2 changes: 1 addition & 1 deletion lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public void shouldThrowWhenInitializedWithoutAlgorithm() throws Exception {
@Test
public void shouldThrowWhenAlgorithmDoesntMatchTheTokensAlgorithm() throws Exception {
exception.expect(AlgorithmMismatchException.class);
exception.expectMessage("The provided Algorithm doesn't match the one defined in the DecodedJWT's Header.");
exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header.");
JWTVerifier verifier = JWTVerifier.init(Algorithm.HMAC512("secret")).build();
verifier.verify("eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.s69x7Mmu4JqwmdxiK6sesALO7tcedbFsKEEITUxw9ho");
}
Expand Down
19 changes: 10 additions & 9 deletions lib/src/test/java/com/auth0/jwt/algorithms/AlgorithmTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.junit.Test;
import org.junit.rules.ExpectedException;

import java.nio.charset.StandardCharsets;
import java.security.interfaces.ECKey;
import java.security.interfaces.RSAKey;

Expand Down Expand Up @@ -109,35 +110,35 @@ public void shouldThrowECDSA512VerificationWithNullPublicKey() throws Exception

@Test
public void shouldCreateHMAC256AlgorithmWithBytes() throws Exception {
Algorithm algorithm = Algorithm.HMAC256("secret".getBytes());
Algorithm algorithm = Algorithm.HMAC256("secret".getBytes(StandardCharsets.UTF_8));

assertThat(algorithm, is(notNullValue()));
assertThat(algorithm, is(instanceOf(HMACAlgorithm.class)));
assertThat(algorithm.getDescription(), is("HmacSHA256"));
assertThat(algorithm.getName(), is("HS256"));
assertThat(((HMACAlgorithm) algorithm).getSecret(), is("secret".getBytes()));
assertThat(((HMACAlgorithm) algorithm).getSecret(), is("secret".getBytes(StandardCharsets.UTF_8)));
}

@Test
public void shouldCreateHMAC384AlgorithmWithBytes() throws Exception {
Algorithm algorithm = Algorithm.HMAC384("secret".getBytes());
Algorithm algorithm = Algorithm.HMAC384("secret".getBytes(StandardCharsets.UTF_8));

assertThat(algorithm, is(notNullValue()));
assertThat(algorithm, is(instanceOf(HMACAlgorithm.class)));
assertThat(algorithm.getDescription(), is("HmacSHA384"));
assertThat(algorithm.getName(), is("HS384"));
assertThat(((HMACAlgorithm) algorithm).getSecret(), is("secret".getBytes()));
assertThat(((HMACAlgorithm) algorithm).getSecret(), is("secret".getBytes(StandardCharsets.UTF_8)));
}

@Test
public void shouldCreateHMAC512AlgorithmWithBytes() throws Exception {
Algorithm algorithm = Algorithm.HMAC512("secret".getBytes());
Algorithm algorithm = Algorithm.HMAC512("secret".getBytes(StandardCharsets.UTF_8));

assertThat(algorithm, is(notNullValue()));
assertThat(algorithm, is(instanceOf(HMACAlgorithm.class)));
assertThat(algorithm.getDescription(), is("HmacSHA512"));
assertThat(algorithm.getName(), is("HS512"));
assertThat(((HMACAlgorithm) algorithm).getSecret(), is("secret".getBytes()));
assertThat(((HMACAlgorithm) algorithm).getSecret(), is("secret".getBytes(StandardCharsets.UTF_8)));
}

@Test
Expand All @@ -148,7 +149,7 @@ public void shouldCreateHMAC256AlgorithmWithString() throws Exception {
assertThat(algorithm, is(instanceOf(HMACAlgorithm.class)));
assertThat(algorithm.getDescription(), is("HmacSHA256"));
assertThat(algorithm.getName(), is("HS256"));
assertThat(((HMACAlgorithm) algorithm).getSecret(), is("secret".getBytes()));
assertThat(((HMACAlgorithm) algorithm).getSecret(), is("secret".getBytes(StandardCharsets.UTF_8)));
}

@Test
Expand All @@ -159,7 +160,7 @@ public void shouldCreateHMAC384AlgorithmWithString() throws Exception {
assertThat(algorithm, is(instanceOf(HMACAlgorithm.class)));
assertThat(algorithm.getDescription(), is("HmacSHA384"));
assertThat(algorithm.getName(), is("HS384"));
assertThat(((HMACAlgorithm) algorithm).getSecret(), is("secret".getBytes()));
assertThat(((HMACAlgorithm) algorithm).getSecret(), is("secret".getBytes(StandardCharsets.UTF_8)));
}

@Test
Expand All @@ -170,7 +171,7 @@ public void shouldCreateHMAC512AlgorithmWithString() throws Exception {
assertThat(algorithm, is(instanceOf(HMACAlgorithm.class)));
assertThat(algorithm.getDescription(), is("HmacSHA512"));
assertThat(algorithm.getName(), is("HS512"));
assertThat(((HMACAlgorithm) algorithm).getSecret(), is("secret".getBytes()));
assertThat(((HMACAlgorithm) algorithm).getSecret(), is("secret".getBytes(StandardCharsets.UTF_8)));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

import org.apache.commons.codec.binary.Base64;

import java.nio.charset.StandardCharsets;

public class AlgorithmUtils {

public static void verify(Algorithm algorithm, String jwt) {
String[] parts = jwt.split("\\.");
byte[] content = String.format("%s.%s", parts[0], parts[1]).getBytes();
byte[] content = String.format("%s.%s", parts[0], parts[1]).getBytes(StandardCharsets.UTF_8);
byte[] signature = new byte[0];
if (parts.length == 3) {
signature = Base64.decodeBase64(parts[2]);
Expand Down
Loading

0 comments on commit 3135718

Please sign in to comment.