import java.io.*;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;
import java.util.Optional;
import javax.crypto.KeyGenerator;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.BearerToken;
public class JwtNoVerifier extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
// OK: first decode without signature verification
// and then verify with signature verification
String JwtToken1 = request.getParameter("JWT1");
String userName = decodeToken(JwtToken1);
verifyToken(JwtToken1, "A Securely generated Key");
if (Objects.equals(userName, "Admin")) {
out.println("
");
out.println("" + "heyyy Admin" + "
");
out.println("");
}
out.println("");
out.println("" + "heyyy Nobody" + "
");
out.println("");
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
// NOT OK: only decode, no verification
String JwtToken1 = request.getParameter("JWT2");
String userName = decodeToken(JwtToken1);
if (Objects.equals(userName, "Admin")) {
out.println("");
out.println("" + "heyyy Admin" + "
");
out.println("");
}
AuthenticationToken authToken = new BearerToken("admin", "admin");
// OK: no clue of the use of unsafe decoded JWT return value
String JwtToken2 = request.getParameter("JWT2");
JWT.decode(JwtToken2);
// NOT OK: only decode, no verification
String JwtToken3 = (String) authToken.getCredentials();
userName = decodeToken(JwtToken3);
if (Objects.equals(userName, "Admin")) {
out.println("");
out.println("" + "heyyy Admin" + "
");
out.println("");
}
// OK: no clue of the use of unsafe decoded JWT return value
String JwtToken4 = (String) authToken.getCredentials();
JWT.decode(JwtToken4);
out.println("");
out.println("" + "heyyy Nobody" + "
");
out.println("");
}
public static boolean verifyToken(final String token, final String key) {
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(key)).build();
verifier.verify(token);
return true;
} catch (JWTVerificationException e) {
System.out.printf("jwt decode fail, token: %s", e);
}
return false;
}
public static String decodeToken(final String token) {
DecodedJWT jwt = JWT.decode(token);
return Optional.of(jwt).map(item -> item.getClaim("userName").asString()).orElse("");
}
private static String getSecureRandomKey() throws NoSuchAlgorithmException {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256); // for example
return keyGen.generateKey().toString();
}
static final String JWT_KEY = "KEY";
public static void NoNeedForTest(HttpServletRequest request) {
// constant key
String JwtToken3 = request.getParameter("JWT3");
verifyToken(JwtToken3, JWT_KEY);
// none algorithm
String JwtToken4 = request.getParameter("JWT4");
try {
verifyTokenNoneAlg(JwtToken4, getSecureRandomKey());
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public static String generateToken(final String userName, final String key) {
try {
return JWT.create().withClaim("userName", userName).sign(Algorithm.HMAC256(key));
} catch (IllegalArgumentException e) {
System.out.printf("JWTToken generate fail %s", e);
}
return "";
}
public static boolean verifyTokenNoneAlg(final String token, final String key) {
try {
JWTVerifier verifier = JWT.require(Algorithm.none()).build();
verifier.verify(token);
return true;
} catch (JWTVerificationException e) {
System.out.printf("jwt decode fail, token: %s", e);
}
return false;
}
}