Giter Club home page Giter Club logo

java-jwt's Introduction

Note As part of our ongoing commitment to best security practices, we have rotated the signing keys used to sign previous releases of this SDK. As a result, new patch builds have been released using the new signing key. Please upgrade at your earliest convenience.

While this change won't affect most developers, if you have implemented a dependency signature validation step in your build process, you may notice a warning that past releases can't be verified. This is expected, and a result of the key rotation process. Updating to the latest version will resolve this for you.

A Java implementation of JSON Web Token (JWT) - RFC 7519.

Build Status Coverage Status License Maven Central javadoc

๐Ÿ“š Documentation - ๐Ÿš€ Getting Started - ๐Ÿ’ป API Reference ๐Ÿ’ฌ Feedback

Documentation

  • Examples - code samples for common java-jwt scenarios.
  • Docs site - explore our docs site and learn more about Auth0.

Getting Started

Requirements

This library is supported for Java LTS versions 8, 11, and 17. For issues on non-LTS versions above 8, consideration will be given on a case-by-case basis.

java-jwt is intended for server-side JVM applications. Android applications should use JWTDecode.Android.

java-jwt supports the following algorithms for both signing and verification:

JWS Algorithm Description
HS256 HMAC256 HMAC with SHA-256
HS384 HMAC384 HMAC with SHA-384
HS512 HMAC512 HMAC with SHA-512
RS256 RSA256 RSASSA-PKCS1-v1_5 with SHA-256
RS384 RSA384 RSASSA-PKCS1-v1_5 with SHA-384
RS512 RSA512 RSASSA-PKCS1-v1_5 with SHA-512
ES256 ECDSA256 ECDSA with curve P-256 and SHA-256
ES384 ECDSA384 ECDSA with curve P-384 and SHA-384
ES512 ECDSA512 ECDSA with curve P-521 and SHA-512

Note - Support for ECDSA with curve secp256k1 and SHA-256 (ES256K) has been dropped since it has been disabled in Java 15

โš ๏ธ Important security note: JVM has a critical vulnerability for ECDSA Algorithms - CVE-2022-21449. Please review the details of the vulnerability and update your environment.

Installation

Add the dependency via Maven:

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

or Gradle:

implementation 'com.auth0:java-jwt:4.4.0'

Create a JWT

Use JWT.create(), configure the claims, and then call sign(algorithm) to sign the JWT.

The example below demonstrates this using the RS256 signing algorithm:

try {
    Algorithm algorithm = Algorithm.RSA256(rsaPublicKey, rsaPrivateKey);
    String token = JWT.create()
        .withIssuer("auth0")
        .sign(algorithm);
} catch (JWTCreationException exception){
    // Invalid Signing configuration / Couldn't convert Claims.
}

Verify a JWT

Create a JWTVerifier passing the Algorithm, and specify any required claim values.

The following example uses RS256 to verify the JWT.

String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE";
DecodedJWT decodedJWT;
try {
    Algorithm algorithm = Algorithm.RSA256(rsaPublicKey, rsaPrivateKey);
    JWTVerifier verifier = JWT.require(algorithm)
        // specify any specific claim validations
        .withIssuer("auth0")
        // reusable verifier instance
        .build();
        
    decodedJWT = verifier.verify(token);
} catch (JWTVerificationException exception){
    // Invalid signature/claims
}

If the token has an invalid signature or the Claim requirement is not met, a JWTVerificationException will be thrown.

See the examples and JavaDocs for additional documentation.

API Reference

Feedback

Contributing

We appreciate feedback and contribution to this repo! Before you get started, please see the following:

Raise an issue

To provide feedback or report a bug, please raise an issue on our issue tracker.

Vulnerability Reporting

Please do not report security vulnerabilities on the public Github issue tracker. The Responsible Disclosure Program details the procedure for disclosing security issues.


Auth0 Logo

Auth0 is an easy to implement, adaptable authentication and authorization platform. To learn more checkout Why Auth0?

This project is licensed under the MIT license. See the LICENSE file for more info.

java-jwt's People

Contributors

aaguiarz avatar chaosex avatar damieng avatar danbrodsky avatar danilavaratyntsev avatar darveshsingh avatar evansims avatar fml2 avatar frederikprijck avatar hzalaz avatar jimmyjames avatar joshcanhelp avatar jsalinaspolo avatar lbalmaceda avatar lorenzospinelli avatar marcono1234 avatar maxbalan avatar noetro avatar overheadhunter avatar poovamraj avatar qaemma avatar rkondratowicz avatar robwin avatar sgc109 avatar skjolber avatar snago avatar vrancic avatar widcket avatar wilson-emmanuel avatar xakepsdk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

java-jwt's Issues

Why am I getting "signature verification failed"?

Hi, it seems I am missing something. I have copied example from the README, but when I do the following:

 final String secret = "secret";

 final long iat = System.currentTimeMillis() / 1000l; // issued at claim
 final long exp = iat + 172800L; // +48 hours

 final JWTSigner signer = new JWTSigner(secret);
 final HashMap<String, Object> claims = new HashMap<String, Object>();
 claims.put("exp", exp);
 claims.put("iat", iat);

 final String jwt = signer.sign(claims);
 final JWTVerifier verifier = new JWTVerifier(secret);
 final Map<String,Object> zz = verifier.verify(jwt);

I get java.security.SignatureException: signature verification failed. What am I missing? Thank you for you help!

EDIT: I checked my version, and it seems I am using an older one (1.0.0), is it safe to upgrade to 2.2.0?
EDIT2: I am getting same error on v2.2.0

EDIT3: It seems that JWTVerifier needs Base64 encoded secret, can anyone confirm this?

Name or Email in decodedPayload

In your README your example has output of the logged in user's name:

System.out.println(decodedPayload.get("name"));

However, the "name" key is not present in the decodedPayload. I can get user id with decodedPayload.get("sub") but then I have to make an additional call to the Auth0 API to retrieve the user's email / name. Is there any way you could include email and name in the decodedPayload so I don't have to make another call?

Implement JWT sign

  • Implement sign of JWT: I think the right approach would be using a builder because there are many arguments to handle.
  • Write some tests that assert both sign and verify.

Exception handling

There is as bit of inconsistency with the exception handling

JWTSigner.sign throws a RuntimeException and has no Exceptions in the method.
JWTVerifier.verify throws 6 types of caught exception

I think that JWTVerifier.verify should throw GeneralSecurityException and JWTSigner.sign should throw a checked exception

Why this test fails?

public class AppTests{

private Algorithm algorithm=Algorithm.HS256;
private JwtProxy proxy = new JwtProxyImpl();
private ClaimSet claimSet=new ClaimSet();
private User user =new User();
private String secret="secret";

@Test
public testTokens throws Exception{
  proxy.setPayloadHandler(new BasicPayloadHandler());
  claimSet.setExp(24*60*60);
  token=proxy.encode(algorithm,user,secret,claimSet);
  new JWTVerifier(secret).verify(token);
  }
}

This test throws SignatureException. What is wrong? Maybe I generate token wrong? In this case what is correct way to generate token?

Grant Access to original decoded JSON string (bypass jackson)

I am using the java-jwt library in the Scala/Play Framework, which has JSON parsing baked in.

Is there a way to return the decoded token as the raw (JSON) string instead of the jackson Map[String,AnyRef]?

current implementation is:
val decoded: util.Map[String, AnyRef] = new jwt.JWTVerifier(secret, config.clientId).verify(token)

perhaps something like:

val decoded: String = new jwt.JWTVerifierJson(secret, config.clientId).verify(token)

[3.0.2]When verifying token, java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.JsonNode.asText(Ljava/lang/String;)Ljava/lang/String;

I tried to learn how to use jwt with auth0's library, and my code is below:

public class JWTTest {

    @Test
    public void test() {
        String token = null;
        try {
            long now = System.currentTimeMillis();
            token = JWT.create()
                    .withClaim("uid","123")
                    .withClaim("mob","123")
                    .withExpiresAt( new Date( now + 7200 ))
                    .sign(Algorithm.HMAC256("secret"));
            System.out.print( token );


        } catch (Exception e) {
            e.printStackTrace();
        }

        try{
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256("secret")).build(); //Reusable verifier instance
            DecodedJWT jwt = verifier.verify(token);
            System.out.print( "uid: " + jwt.getClaim("uid" ) );
            System.out.println( "mob: "+ jwt.getClaim( "mob") );
            System.out.println( "exp: " + jwt.getExpiresAt() + ", algorithm: " + jwt.getAlgorithm() );
        }catch ( Exception e ){
            e.printStackTrace();
        }
    }
}

then i got error at the line: DecodedJWT jwt = verifier.verify( token ). The exception is below(the first line of output is token):

eyJhbGciOiJIUzI1NiJ9.eyJ1aWQiOiIxMjMiLCJleHAiOjE0ODE4MDQ2NDIsIm1vYiI6IjEyMyJ9.67IX_XSDLH8apJAYryDUDOZWEQ5BSN74kxUKtz_4c44
java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.JsonNode.asText(Ljava/lang/String;)Ljava/lang/String;

	at com.auth0.jwt.impl.HeaderDeserializer.getString(HeaderDeserializer.java:43)
	at com.auth0.jwt.impl.HeaderDeserializer.deserialize(HeaderDeserializer.java:31)
	at com.auth0.jwt.impl.HeaderDeserializer.deserialize(HeaderDeserializer.java:13)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2993)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2098)
	at com.auth0.jwt.impl.JWTParser.convertFromJSON(JWTParser.java:57)
	at com.auth0.jwt.impl.JWTParser.parseHeader(JWTParser.java:33)
	at com.auth0.jwt.JWTDecoder.parseToken(JWTDecoder.java:42)
	at com.auth0.jwt.JWTDecoder.<init>(JWTDecoder.java:28)
	at com.auth0.jwt.JWT.decode(JWT.java:24)
	at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:241)
	at tes.dao.user.JWTTest.test(JWTTest.java:37)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

Fine-grained verification exception handling

I'm using this JWT library in my API authentication. I don't see many examples in the README. And I wanted to handle the verification exceptions in a fine-grained level. Based on the documented example, instead of just telling API consumers "Invalid Token", I wanted to verify the issuer and expiration time separately.

try {
    final JWTVerifier verifier = new JWTVerifier("{{secret used for signing}}", "{{my-audience}}", "{{my-issuer}}");
    final Map<String, Object> claims= verifier.verify(jwt);
} catch (JWTVerifyException e) {
    // Invalid Token
}

Can anyone provide any examples? Thanks!

Vulnerability fix

Addressing the serious vulnerability well described here:
https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
All that is needed is a way to force the use of the intended algorithm.

In the verification code, just replace this
String algorithm = getAlgorithm(jwtHeader);
With this:
String algorithm = givenAlgorithm != null ? givenAlgorithm : getAlgorithm(jwtHeader);
and add a parameter to the method (... String givenAlgorithm )

You could even clone the old method to call this new method to preserver backward compatibility.

Enhancement - any way to make the parameter of class Algorithm instead of String?

Works like a charm.

Sorry, not familiar enough with github to make the changes myself (:

Great library!

Is JWTVerifier thread-safe?

We want to cache and use the same instance instead of creating one for every request.
Is it thread-safe and does it use locking such that it'll cause performance issues?

Automated unit tests including code coverage report

The README says:

We think that current JWT implementations are either too complex or not tested enough.

Please add automated tests (Travis CI maybe?) and code coverage report (+ nice batches in README) to proof that your library is "tested enough" ๐Ÿ˜

Support for custom values in the header

https://tools.ietf.org/html/rfc7519#section-5.3

5.3. Replicating Claims as Header Parameters

In some applications using encrypted JWTs, it is useful to have an
unencrypted representation of some claims. This might be used, for
instance, in application processing rules to determine whether and
how to process the JWT before it is decrypted.

This specification allows claims present in the JWT Claims Set to be
replicated as Header Parameters in a JWT that is a JWE, as needed by
the application. If such replicated claims are present, the
application receiving them SHOULD verify that their values are
identical, unless the application defines other specific processing
rules for these claims. It is the responsibility of the application
to ensure that only claims that are safe to be transmitted in an
unencrypted manner are replicated as Header Parameter values in the
JWT.

Can support be added for this?

is expired supported?

I am quite new in JWT ....

I wonder if this java implementation considers expired filed while validating JWT ?!

Read claims before verify

Would it be possible to add the functionality to read claims from a token before we verify the token.

For example a claim may be the users id which we use to look up the secret which was used to sign the token.

Without this ability we must sign every token with the same secret.

Can't use with JDK 1.7 throw java.lang.UnsupportedClassVersionError

Trying to use 3.0.1 library, downloaded from Maven repository at Websphere 8.5 in project which build with JDK 1.7 but it throws the following error:

java.lang.UnsupportedClassVersionError: JVMCFRE003 bad major version; class=com/auth0/jwt/algorithms/Algorithm, offset=6

I've tried to recompile from source but it didn't help, maybe I've done something wrong because it's first time I using gradle.

Can somebody help me with this issue?

Array claim [3.0.1]

I'm trying to update from 2.1.0 to 3.0.1, but it seems like it's illegal to add a claim which consists of an array of values. Is this intentionally restricted, and is that restriction present in the RFC?

A minor error in README.md, apparently

The example given is slightly off:

            Base64 decoder = new Base64(true);
            byte[] secret = decoder.decodeBase64(CLIENT_SECRET);

decodeBase64() is a static function, but it's being called in the context of a java instance variable - this might be legal (i've been copying and altering for scala myself) but it doesn't really make sense, so I would suggest

            //Base64 decoder = new Base64(true);
            byte[] secret = Base64.decodeBase64(CLIENT_SECRET);

or

            byte[] secret = decoder.decode(CLIENT_SECRET);

Allow creation and verification for a specified time

Unit testing classes with expiring tokens with this library is difficult because it is tied to System.currentTimeMillis() in multiple places. I use JodaTime, which has a number of features which make unit testing easier, including freezing the joda clock at a specified time. I would like to inject the time for iat/exp on creation, and for verifying exp, such that it can be made to work with this Joda functionality.

I am already setting iat/exp manually to leverage this feature, but it doesn't seem possible to do so for verification at this time.

Repackaging Jackson package breaks Jackson annotations

Repackaging Jackson package breaks Jackson annotations :(

When I serialize user claim using JwtSigner the following code is not working.

public class UserAuthority  {
    @NotNull
    @ManyToOne
    @com.fasterxml.jackson.annotation.JsonIgnore
    private User user;
}

Annotation JsonIgnore is ignored and this field is serialized (causing infinite loop).
When I switch to annotations from com.auth0.jwt.internal.com.fasterxml.jackson everything works perfectly.

public class UserAuthority  {
    @NotNull
    @ManyToOne
    @com.auth0.jwt.internal.com.fasterxml.jackson.annotation.JsonIgnore
    private User user;
}

Is repackaging com.fasterxml.jackson and org.apache.commons.codec absolutely necessary.
Can't You add them as standard dependencies?

Clock is package private [3.0.1]

Should the Clock class, and JWTVerifier#build method be public instead of package private? Making these package private doesn't do me any good if I want to use a custom clock for unit testing.

verify should not through InvalidStateException

It's quite confusing to let the verifier API throw IllegalStateException.

It is documented. But for those case, a new JWTVerifyException extending Exception could be used to catch them without having to read the javadoc.

And maybe more specialized exceptions, like JWTExpiredException (extending JWTVerifyException) too, because it's not possible today to know if the JWT verify failed because of an expiration.

Android build issue

When doing a gradle build for my android app, I get pair of errors:

Error:Error converting bytecode to dex:
Cause: com.android.dex.DexException: Multiple dex files define Lorg/apache/commons/io/CopyUtils;
Error:Execution failed for task ':app:transformClassesWithDexForDebug'.
> com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/bin/java'' finished with non-zero exit value 2

These go away when I use a different jwt library. I'm not sure if it's this library, or if it's clashing with another library I have imported that's doing things wrong.

My gradle dependencies:

    compile 'com.android.support:appcompat-v7:22.2.1'
    compile 'com.android.support:support-v4:22.2.1'
    compile 'com.squareup.okhttp3:okhttp:3.3.0'
    compile 'com.auth0:java-jwt:2.2.0'

Payload (claims) architecture review

Hi,

The signer and the verifier are currently only working with claims as Map<String, Object>.
That means that if I represent a claim as a plain Java object, I have to implement methods which:

  • convert my Java object to a Map,
  • convert a Map to my Java object.

Since internally Jackson is used for the Json serialization/deserialization, it would be great if the signer and the verifier could work with any Java object that Jackson can serialize/deserialize.
That can be achieve if:

  • JWTSigner.encodedPayload would take as arguments: (Object claims, Options options)
  • Options would contains all the currently implicit parameters: iss, sub, aud, exp, nbf, iat and jti (this way the parameters would also be type-safe)
  • The payload object passed to ObjectMapper.writeValueAsString is an object defined as { claims: claimsArg, options: optionsArgsValidated }
  • the method Map JWTVerifier.verify(String token) signature would be unchanged, but the variant T JWTVerifier.verify(String token, Class<T> deserializeClass) would enable to directly convert the Json object to a custom Java object.

What are your thought about that ?

Using private/public key example

Hi, can you please provide an example of how to sign/verify using private/public key pair?

I got it working in node with node-jsonwebtoken:

var key = fs.readFileSync('private.key');
var pem = fs.readFileSync('public.pem');

var header = {...};
var payload = {...};

header.algorithm = "RS256";
var message = jsonwebtoken.sign(payload, key, header);
var decoded = jsonwebtoken.verify(message, pem, {algorithm: "RS256"});

And it works like a charm.

I would like to do the same in Java.

I looked in the test src, but I couln't figure it out.

Does not validate not before

it looks like nbf is added as a claim to the token but JWTVerifier.verify never validates it. This is part of JWT spec and should really be verified.

Get all claims [3.0.1]

I was just upgrading from 2.2.1 and I can no longer find a way to get all claims... I see a signature to get a claim by name, but not one to get either the keyset or entire entryset... Did I miss something?

Base64 and Jackson/Gson

I made a fork where I replaced the common-codecs dependency by using the base 64 encoder/decoder from the Java 1.8 standard library. I also replaced the Jackson dependency with a Gson dependency. I don't expect this to be pulled in for obvious reasons, though wanted to share just in case.

See: https://github.com/pietern/java-jwt/commits/gson

Make jackson dependency optional.

Im developing android application. And in android dev we have problem with method count . The jackson lib have a huge codebase (6725 metods) against Gson which is provided. Of cause Proguard or multydex help to avoid 64k methods limit, but but still it have strong affect on build time.

Is it possible to replace jackson with gson? In your case their functionality is almost equal.

getting RunTimeException when signing with RS256

This is how i am generating the token but i am getting RuntimeException . Please help.
I am generating this token for firebase custom auth. Custom token claims are given here
I am doing this in android studio 2.1.3 and testing on a phone with android 4.1.2.

   `final String issuer = "[email protected]";
    final String sub = "[email protected]";
    final String aud =      "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit";
    final String secret = "ajksdfhfdasihdfasiudufashuifdhsuidfa";

    final long iat = System.currentTimeMillis() / 1000L; // issued at claim
    final long exp = iat + 60L; // expires claim. In this case the token expires in 60 seconds


    final JWTSigner signer = new JWTSigner(secret );
    final HashMap<String, Object> claims = new HashMap<String, Object>();
    claims.put("alg","RS256");
    claims.put("iss", issuer);
    claims.put("sub",sub);
    claims.put("aud",aud);
    claims.put("iat", iat);
    claims.put("exp", exp);
    claims.put("uid",number);

    JWTSigner.Options options = new JWTSigner.Options();
    options.setAlgorithm(Algorithm.RS256);


    final String jwtString = signer.sign(claims ,options );`

Support hash salt

Hi,
This looks like a great tool, and the code it easy to read, so thanks!

I wander if there is a built in support for salt - a bunch of characters that are added to each entry in the claims object ?

If there is no option like that, what do you think about the right way to add it?
As I see it - this can be done with the existing code - I can generate the salt, add it to each entry in the claims object and add it as an entry as well.

So instead of:

{ username: david1,
  lastLogin: 10-10-2015:00:00:00
}

I pass the following object:

{ username: david1xyz,
  lastLogin: 10-10-2015:00:00:00xyz,
  salt: xyz
}

This can be done but it feels wrong.

I think that the right way would be to use the salt when signing, and put it in the header.
This way when verifying you can user the salt again without asking from the client to save it.

What do you think?

How do I achieve this with java-jwt

I got Node.js implementation here

var email = '[email protected]'; //user email
var uuid  = '928227216216261';  //user uuid
var jwtSecret = 'XAXAXAXA';
var ClaimSet = {

        algorithm : JWT_Algorithm,
        audience: 'https://api.mysite.com',
        issuer: 'Package.mysite.com',
        subject: 'Getting Profile'

    }
 var user_credentials = {uuid:uuid, email:email}
 var token = jwt.sign(user_credentials, jwtSecret,ClaimSet);

Thanks

Race condition in repackaged Base64 breaks auths at random

After updating our auth0 libs to pull in some important fixes, we started having random authentication failures that would not reproduce.

Turns out that JWTVerifier.decodeAndParse() was failing with IOException from time to time.

Diagnosis: the base64 decoder used is not thread safe. For some reason you repackaged a buggy commons-codec.

PS: This took me almost a whole day to nail down and it's a blocker for us.

Proof of concept:

import com.auth0.jwt.internal.org.apache.commons.codec.binary.Base64;

public class Poc {

  public static void main(String... args) throws Exception {

    final int threads = 2;

    String[] tokens = new String[] {
        "eyJyb2xlcyI6WyIqIiwiY29tcGFueS4wMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDAiXSwiY29tcGFueUlkIjoiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAwIiwidXNlcklkIjoiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtNzU3MzY1NzIwMDAwIiwidXNlcm5hbWUiOiJyb290IiwiZW1haWwiOiJyb290LWRldkB0aWVycmEuaW8iLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInVzZXJfaWQiOiJhdXRoMHw1NzkwYTcyNTYzMjkyYjY5NmZlMjEwZWUiLCJpc3MiOiJodHRwczovL3RpZXJyYS1pb3QuYXV0aDAuY29tLyIsInN1YiI6ImF1dGgwfDU3OTBhNzI1NjMyOTJiNjk2ZmUyMTBlZSIsImF1ZCI6Im9SdkJHVFRQV0JFekVDNTU5aUFXRGt6M3MyMWNVNkJ3IiwiZXhwIjoxNDcxNjI5MDc0LCJpYXQiOjE0NzE1OTMwNzR9",
        "eyJyb2xlcyI6WyIqIiwiY29tcGFueS4wMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDAiXSwiY29tcGFueUlkIjoiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAwIiwidXNlcklkIjoiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtNzU3MzY1NzIwMDAwIiwidXNlcm5hbWUiOiJyb290IiwiZW1haWwiOiJ4QHRpZXJyYS5pbyIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwidXNlcl9pZCI6ImF1dGgwfDU3OTBhNzI1NjMyOTJiNjk2ZmUyMTBlZiIsImlzcyI6Imh0dHBzOi8vdGllcnJhLWlvdC5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NTc5MGE3MjU2MzI5MmI2OTZmZTIxMGVlIiwiYXVkIjoib1J2QkdUVFBXQkV6RUM1NTlpQVdEa3ozczIxY1U2QnciLCJleHAiOjE0NzE2MjkwNzQsImlhdCI6MTQ3MTU5MzA3NH0="
    };

    final Base64 decoder = new Base64(true);

    for (int i = 0; i < threads; i++) {

      final String b64String = tokens[i % tokens.length];
      final String expected = new String(decoder.decode(b64String), "UTF-8"); // no concurrency here

      (new Thread() {

        @Override
        public void run() {
          System.err.println("Starting thread");
          try {
            while (true) {
              final String jsonString = new String(decoder.decode(b64String), "UTF-8");
              if (!expected.equals(jsonString)) {
                System.err.println("BUG: got <" +  jsonString + ">, expected + <" + expected + ">");
                break;
              }
            }
          } catch (Exception e) {
            e.printStackTrace();
          }
          System.exit(1);
        }

      }).start();

    }
  }
}

Token generated using JWTSigner.sign() saying invalid signature in jwt.io debugger

Hi,
We had written small API using java-jwt 2.2.1. It works fine when i create a token and verify the token in Java code.

  1. Created RSA Private and Public keys. (Referred to one of the test case)
  2. Created a token using Algorithm.RS256 with the private key.
  3. Verified the same token and got output as expected.

Then provided the public key to client and we started invoking their REST services using generated tokens. Client side using https://www.npmjs.com/package/jsonwebtoken to verify the tokens. They came back saying that the token and public key provided saying Invalid Signature in jwt.io debugger. They requested to make it work in jwt.io debugger first. I don't understand when it is working in Java code with the same public why is it saying that way in jwt.io. Am i missing something?

Generating Keys

public void createPemFiles(String absoluteFilePath) throws Exception {
    logger.log(Level.INFO, "Received request to create Key pair : " + absoluteFilePath);
    PemWriter pemWriter = new PemWriter();
    // create key pair
    final KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
    generator.initialize(KEY_SIZE);
    final KeyPair keyPair = generator.generateKeyPair();

    // write private key
    final RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    privateKeyPem = new File(absoluteFilePath);
    pemWriter.writePrivateKey(privateKey, "RSA PRIVATE KEY", privateKeyPem.getAbsolutePath());
    logger.log(Level.INFO, "Created private key  : " + privateKeyPem.getAbsolutePath());

    // write public key
    publicKeyPem = new File(absoluteFilePath+".pub");
    final RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    pemWriter.writePublicKey(publicKey, "RSA PUBLIC KEY", publicKeyPem.getAbsolutePath());
    logger.log(Level.INFO, "Created public key  : " + publicKeyPem.getAbsolutePath());
}

Create Token

public String createJWTToken(String [] keyValues) {
    logger.log(Level.DEBUG, "Received request for create JWT token");
    final HashMap<String, Object> claims = new HashMap<String, Object>();
    String [] nameValue;

    for(String keyValue : keyValues) {
        nameValue = keyValue.split("##");
        claims.put(nameValue[0],nameValue[1]);
    }
    String claimString = JWTSIGNER.sign(claims, OPTIONS);
    logger.log(Level.DEBUG, "Successfully signed : "+claimString);
    return claimString;
}

Verifying Token

 public String verifyJWTToken(String token) throws  Exception{
    logger.log(Level.DEBUG, "Received request for verify JWT token");
    Map<String, Object> claims = JWTVERIFIER.verify(token);
    String claimString = "";

    String key = "";
    String value = "";

    for(Map.Entry<String, Object> entry : claims.entrySet()) {
        key = entry.getKey();
        value = (String) entry.getValue().toString();
        claimString = claimString + key +":"+ value + "##";
    }
    claimString = replaceLast(claimString, "##", "");
    logger.log(Level.DEBUG, "Successfully verified : "+claimString);
    return claimString;
}

Input iccid:4454788545885968585##nonce:5e452610c9f9decd:-404fb717:157fd6fc54e:-7ffe##timestamp:2016-10-25T16:16:36.036Z

Create Token Output eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpY2NpZCI6IjQ0NTQ3ODg1NDU4ODU5Njg1ODUiLCJub25jZSI6IjVlNDUyNjEwYzlmOWRlY2Q6LTQwNGZiNzE3OjE1N2ZkNmZjNTRlOi03ZmZlIiwidGltZXN0YW1wIjoiMjAxNi0xMC0yNVQxNjoxNjozNi4wMzZaIn0.PlWVn1jlkvjRpw34-fsjJGQVVd74sFdg7SS2UgA4HUx4vBMYMA4b-Zzg5VxyzYkhzSsQqjKn7UBw04fXIwsmaP9A7Pc3-MjHjbmYT3Yv52qvH4yNy6X_M0z41UHuuLaWVQN3eck5BKIoO2cy4ihb8OOISkzF1Cf-Udx1GB-bVY4C4JtIvGpMflVW4hS9ZpWzKz26qlva7Y9KMEmvW24tviNcy8aVNyC55MS_KS_Ab7YWQ-MERRiNTCDIqUG7YVSN2Ap_SsNMab687GknQh78ibAowUdpLbGRU4N5EHZyG2lg-u-oL594fRA2anr-JunSxtpkI8-tKzR9NG5dt4F79Q

Verify Token Output iccid:4454788545885968585##nonce:5e452610c9f9decd:-404fb717:157fd6fc54e:-7ffe##timestamp:2016-10-25T16:16:36.036Z

Public Key
-----BEGIN RSA PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx58WGD/wRFnwe64sl/9V KuNOQChYUy8GfhQU66M2XSnx/UpjPCqhGYRmpUXT+rQAamUDsarGt8Kbw1DtlvLT p2UTvSWiCJNQzi53CRa6iDbk213Ps7zuAFhuXB7s0ZqdOZbeJnXFFM/wMJbM6kdB yAdCwj8/kCKCjSt3Q0CLdxaToTucRJuO7/V4wbJIDMfLt3LPlry/PsHQAx0RKXco TO1JsSGWg99dHBEqpxLMBtZyhyd8++PrMrtQ4pPVAmXoJODKY2NZkiLl3h4Ai48z FhBNHsWQDTJKA8skb2JQER9i1a1/ip/cgkR6FG6G65DbhrMElcL0mgdst49PF26p pwIDAQAB -----END RSA PUBLIC KEY-----

Set targetCompatibility to 1.7

I try with JDK 1.7 but raise can't load class Unsupported major.minor version 52.0 (Java 1.8)

Downloading source and setting targetCompatibility = 1.7 resolved this problem.

Fail if audience is specified but absent in the token.

Hi there,

reading through the source, why does the following not throw an exception?

new JWTVerifier(secret, "audience").verify("my-token-without-aud");

If I explicitly require an audience in the verifier, this check should not be skipped if there's no audience specified in the token? Similarly, the same behaviour applies to the issuer attribute.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.