jwtk / jjwt Goto Github PK
View Code? Open in Web Editor NEWJava JWT: JSON Web Token for Java and Android
License: Apache License 2.0
Java JWT: JSON Web Token for Java and Android
License: Apache License 2.0
Wanted to know if your libray takes care of security vulnerabilites https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
Please update
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary("8754487552");
Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
Map<String, Object> map = new HashMap<String, Object>();
map.put("service", "emailverification");
map.put(Claims.EXPIRATION, new Date(now.getTime() + 3600));
JwtBuilder builder = Jwts.builder()
.setClaims(map).signWith(signatureAlgorithm, signingKey);
String jwt = builder.compact();
Claims claims = Jwts.parser()
.setSigningKey(DatatypeConverter.parseBase64Binary("8754487552")).parseClaimsJws(jwt).getBody();
Claims claims1 = Jwts.parser()
.setSigningKey(DatatypeConverter.parseBase64Binary("875448755")).parseClaimsJws(jwt).getBody();
System.out.println("Expiration: " + claims.getExpiration());
System.out.println("Service: " + claims.get("service"));
System.out.println("Expiration: " + claims1.getExpiration());
System.out.println("Service: " + claims1.get("service"));
both claims and claims1 are created where in the provided key for claims1 is different from the one that is used to sign it
I have a question.
Is slf4j-api an optional dependency ?
exp
and nbf
are already asserted automatically. Also allow building a parser that expects values for the following:
iss
aud
sub
iat
jti
Ensure the parser method names use the more friendly names - e.g.
parserBuilder.setId("jtiValue").setSubject("sub value"). ...etc... .parse(compact);
Something minor but something you may want to fix throughout. I am using Android Studio with default settings, and the "HS256" does not resolve on this line:
String compact = Jwts.builder().setSubject("Joe").signWith(HS256, key).compact();
I'd suggest you change it to
String compact = Jwts.builder().setSubject("Joe").signWith(SignatureAlgorithm.HS256, key).compact();
and import SignatureAlgorithm instead.
I don't know if this is a default setting which came in from an alpha version of Android Studio or if this is still default, but my Android Studio (or the settings, haven't checked this) do not allow the direct import of a Constant. I'd change it as a precaution because other users may run into the same issue.
long now = System.currentTimeMillis() / 1000;
long expire = now + 300;
String jwt = Jwts.builder()
.setId("id")
.setIssuer("subject")
.setIssuedAt(new Date(now))
.setExpiration(new Date(expire))
.compact()
This renders a token in wich issueAt and expiration are the same.
Looks like some millisecond precision is lost when transforming to JSON
It would be nice to see a second signature overload for .setExpiration(long), setIssuedAt(long) etc. which takes a long value instead of a date.
For a newbie the random byte[] key may imply the key has to be random.
Also why having it in a byte[] instead of a String ?
I wonder how to have a constant private key.
Am I misusing your API ?
Sorry for being the newbie...
JwtBuilder
should have the ability to actually build a Jwt
object instead of only the compact String
representation.
I would
Jwt build();
to JwtBuilder
String compact();
to Jwt
String
) from DefaultJwtBuilder.compact()
to DefaultJwtBuilder.build()
DefaultJwt.compact()
and DefaultJws.compact()
to return the compact String
DefaultJwtBuilder.compact()
call return build().compact();
to not break api compatibilityIf a core contributor could tell me if that would be accepted as a PR, i would do it. Otherwise, i could also implement another solution to this if outlined.
Will it be possible to avoid dependency on slf4j logger? Looks like the only class using it is io.jsonwebtoken.lang.Classes?
I'm trying to use this in a WAS TAI which requires me to deploy jjwt and its dependent libraries so it is loaded as a WAS extension, which then affects any application specific class loaders trying to load their slf4j.
I like that jjwt has very few dependencies, seems like it might be possible to avoid slf4j also.
I would imagine that when most people are setting an expiration on a JWT, they will be using some configured timeout duration (e.g. 15 minutes). the ClaimsMutator has a basic setExpiration helper which takes the expiration date. It would be great if you added a convenience method which took the duration and did the math to compute the final exipration date, something like:
public T setExpirationAfter(long duration, TimeUnit timeUnit);
Where the impl is something like:
return setExpiration(new Date(System.currentTimeMillis() + timeUnit.toMillis(duration)));
By verifying the signature before asserting body claims, the Exceptions that are thrown when a token is expired or used before certain time can contain the claims, allowing the client to do clean up work related to verified but not valid jwt.
instead of Arrays.equals
Hello,
I understand that this may not be issue with the library but may is worth extending. Some changes were made by google in API 23 so the code below that worked on lower version is no longer valid.
PrivateKey privateKey = KeyChain.getPrivateKey(context, "Alias");
String jwtString = Jwts.builder().setHeaderParams(map)
.setPayload(payload)
.signWith(SignatureAlgorithm.RS256, privateKey)
.compact();
Before API 23 KeyChain.getPrivateKey had a return type of OpenSSLRSAPrivateKey and post 23 it is AndroidKeyStoreRSAPrivateKey which does not expose the bytes of the key.
Could the library be enhanced to use the new Android way of signing as described in this post:
https://code.google.com/p/android-developer-preview/issues/detail?id=2854
Thanks in advance,
Kalin
Hi, There is any known implementation of a retrofit[1] converter using jjwt?
It would be nice to have, for instance, a GSON converter[2] with the jjwt support.
[1] - https://github.com/square/retrofit
[2] - https://github.com/square/retrofit/tree/master/retrofit-converters/gson/src/main/java/retrofit
Thanks.
How can I implement Refresh Token if I want user's token to get refreshed after a certain amount of time?
Hi, I'm having issue with using this on android, the following fatal exception occurs:
java.lang.NoClassDefFoundError: javax.xml.bind.DatatypeConverter
at io.jsonwebtoken.impl.Base64Codec.encode(Base64Codec.java:24)
and found out Android doesn't support javax.xml.bind.DatatypeConverter.
Any possible fix for this? Thanks.
I ran across this project and tried taking for a spin, I tried adding the 0.5 version to my pom.xml and it Maven could not resolve it. A quick search on Maven Central showed that the artifact is not present there:
http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22io.jsonwebtoken%22%20AND%20a%3A%22jjwt%22
Are there plans to publish this release?
4.1.4. "exp" (Expiration Time) Claim
The "exp" (expiration time) claim identifies the expiration time on
or after which the JWT MUST NOT be accepted for processing. The
processing of the "exp" claim requires that the current date/time
MUST be before the expiration date/time listed in the "exp" claim.
Implementers MAY provide for some small leeway, usually no more than
a few minutes, to account for clock skew. Its value MUST be a number
containing a NumericDate value. Use of this claim is OPTIONAL.
4.1.5. "nbf" (Not Before) Claim
The "nbf" (not before) claim identifies the time before which the JWT
MUST NOT be accepted for processing. The processing of the "nbf"
claim requires that the current date/time MUST be after or equal to
the not-before date/time listed in the "nbf" claim. Implementers MAY
provide for some small leeway, usually no more than a few minutes, to
account for clock skew. Its value MUST be a number containing a
NumericDate value. Use of this claim is OPTIONAL.
Any chance you can add the ability to set a skew/drift parameter to the exp and nbf check?
The readme has the following line to parse the token.
Token token = Jwts.parser().setSigningKey(key).parse(jwt);
However, there is no Token class in the library. The parse method is defined to return a Jwt object.
Jwt parse(String jwt) throws MalformedJwtException, SignatureException;
The implementation returns a DefaultJwt, which does not allow for the syntactic sugar currently shown in the README.md
token.getClaims().getSubject().equals("Joe");
I'm curious how you'd like this fixed. I'll happily submit a pull request.
using Integer.parseInt is not working - seconds since epoch is greater than Integer.MAX_VALUE in some cases, causing rollover (negative) values. Changing to Long.parseLong will work.
I'm getting this error when trying to install your plugin
Could not transfer artifact io.jsonwebtoken:jjwt:zip:0.4 from/to m2repo_spockframework_org_ext_ (http://m2repo.spockframework.org/ext/): m2repo.spockframework.org (Use --stacktrace to see the full trace)
I've tried googling around and can't figure this out, and I'm new to the gradle game so any help would be awesome!
Establish a presence on jwt.io here, which I think you can do by submitting a PR somewhere around here
hello,
I have this exception using this java code (i am using last release).
Can you help me? Tnkx
String key = "Hello World!";
String token = Jwts.builder().setPayload(key).compact();
...
...
...
Jwts.parser().setSigningKey(key).parse(token);
Caused by: com.fasterxml.jackson.core.JsonParseException: Unrecognized token '?'
: was expecting ('true', 'false' or 'null')
at [Source: ?[โ?????H?; line: 1, column: 2]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java
:1419)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(Parser
MinimalBase.java:508)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidT
oken(ReaderBasedJsonParser.java:2300)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._handleOddValue
(ReaderBasedJsonParser.java:1459)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(Reade
rBasedJsonParser.java:683)
at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMap
per.java:3090)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMa
pper.java:3036)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.ja
va:2146)
at io.jsonwebtoken.impl.DefaultJwtParser.readValue(DefaultJwtParser.java
:376)
In just pulling project from GitHub and building (mvn clean verify), I receive the following compile error:
[ERROR] /F:/Code/jjwt/src/main/java/io/jsonwebtoken/impl/DefaultJwsHeader.java:[22,8] F:\Code\jjwt\src\main\java\io\jsonwebtoken\impl\DefaultJwsHeader.java:22: java.util.Map cannot be inherited with different arguments: <> and <java.lang.String,java.lang.Object>
Looking at the code, it does appear to be a consequence of DefaultJwsHeader being a raw type where it is using/inheriting from others which are parameterized.
mvn --version
Apache Maven 3.2.3 (33f8c3e1027c3ddde99d3cdebad2656a31e8fdf4; 2014-08-11T16:58:10-04:00) Maven home: C:\Programs\Apache\apache-maven-3.2.3\bin\.. Java version: 1.6.0_45, vendor: Sun Microsystems Inc. Java home: C:\Progra~1\Java\jdk1.6.0_45\jre Default locale: en_US, platform encoding: Cp1252 OS name: "windows server 2012", version: "6.2", arch: "amd64", family: "windows"
Ensure that if a public key is configured for the parser that it does not recognize non-RSA algorithms.
Hello, under normal load everything works just fine, but when server gets a lot of traffic I'm getting response time spikes. While I'm analyzing the thread dump I see a lot of blocked threads, which I don't see at all during no spike time, even under heavy load:
qtp1331498204-743" prio=10 tid=0x00007f68b02ca800 nid=0x324e waiting for monitor entry [0x00007f685f977000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.security.Provider.getService(Provider.java:680)
- waiting to lock <0x0000000787dd34c8> (a sun.security.provider.Sun)
at sun.security.jca.ProviderList$ServiceList.tryGet(ProviderList.java:436)
at sun.security.jca.ProviderList$ServiceList.access$200(ProviderList.java:375)
at sun.security.jca.ProviderList$ServiceList$1.hasNext(ProviderList.java:485)
at java.security.Signature.getInstance(Signature.java:223)
at io.jsonwebtoken.impl.crypto.RsaProvider.newSignatureInstance(RsaProvider.java:73)
at io.jsonwebtoken.impl.crypto.RsaProvider.createSignatureInstance(RsaProvider.java:38)
at io.jsonwebtoken.impl.crypto.RsaSignatureValidator.isValid(RsaSignatureValidator.java:40)
at io.jsonwebtoken.impl.crypto.DefaultJwtSignatureValidator.isValid(DefaultJwtSignatureValidator.java:47)
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:283)
at com.mycomp.JjwtServiceAccessTokenDeserializer.deserialize(JjwtServiceAccessTokenDeserializer.java:25)
at com.mycomp.ServiceAccessToken.deserialize(ServiceAccessToken.java:248)
at com.mycomp.SatFilter.doFilter(SatFilter.java:66)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1476)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:501)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:533)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:429)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:154)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.Server.handle(Server.java:370)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494)
at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:971)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:1033)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:644)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:696)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:53)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Thread.java:744)
I'm not sure what could cause the problem, but if you know, please fix it.
Thanks for the library anyway,
Eugene
Sometimes the signature key is embedded either in the JWT header or body, and therefore is useful to parse the JWT skipping the signature verification. Of course the verification must happen after getting the signature key.
If this is a valid approach the client is responsible of checking the signature after getting the values they need from the Jws.
A second approach would be to have a callback interface that if set will be called before the signature verification happens.
For example:
public interface JwsSignatureKeyResolver {
Key resolveSignatureKey(JwsHeader header, Claims claims);
}
Probably can be call it if key is null and a implementation of the interface is specified when built a Jws Parser.
When attempting to read the body of a signed jwt without setting a key, an IllegalArgumentException is thrown. For example: Jwts.parser().parseClaimsJws(someJwtString).getBody().get("iss")
. This makes sense, as it prevents users from ignoring signatures when they shouldn't.
However, sometimes it is useful to know some fields of the body before checking the signature. For example, if there are several possible issuers to a token, each with different signing keys or signature mechanisms. Addition of a method like parseUnsafe
would grant the ability to inspect the body as well as alert the user (through the name) of the danger of the method. The user could then go back and parse the jwt as normal with signature checking.
Is it possible to force the signature algorithm on parse? Meaning that the jwt is only considered valid if it is signed with a particular algorithm?
If not, is it possible to disallow the NONE algorithm or otherwise check the algorithm and make sure that the jwt is signed on parse?
Readme here on github indicates latest version is 0.6, but the latest build in maven is 0.5.1. https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22io.jsonwebtoken%22%20AND%20a%3A%22jjwt%22
Line 35 of SigningKeyResolverAdapter.java
has a typo. You referenced the (JwtHeader, String)
signature twice. I suspect you meant one (JwtHeader, String)
and one (JwtHeader, Claims)
.
I just added the library to dependencies.
dependencies
{
compile 'io.jsonwebtoken:jjwt:0.6.0'
}
When i tried to ran the application, I got the following
Error:Execution failed for task ':app:dexDebug'.
com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'C:\Program Files\Java\jdk1.8.0_60\bin\java.exe'' finished with non-zero exit value 2
I've googled around for a while but can't figure this out, so any help would be awesome
ES256, ES384, ES512
By not propagating the generic type to specific generic to the interface, IDEs warn of not passing the specific type in the Jws.
For example:
Jws<MyClaims> jws = Jwts.parser().setSigningKeyResolver(issuerSigningKeyResolver).parse(jwt, new JwtHandlerAdapter<Jws<MyClaims>>() {
@Override
public Jws<MyClaims> onClaimsJws(Jws<Claims> jws) {
MyClaims myClaims = ...;
return new DefaultJws<>(jws.getHeader(), myClaims, jws.getSignature());
}
});
The IDE complains the the returned type is not of Jws<MyClaims>
.
Solution will be add the generic body to the signature of the class:
public class DefaultJws<B> implements Jws<B>
So, when I included the section mentioned in the wiki into my pom.xml of my appengine application (Ninja Framework):
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.1</version>
</dependency>
and ran the application, I got the following stack trace, repeatedly.
[java.net.URLClassLoader$1.run(URLClassLoader.java:366),java.net.URLClassLoader$1.run(URLClassLoader.java:355),java.security.AccessController.doPrivileged(Native Method),java.net.URLClassLoader.findClass(URLClassLoader.java:354),java.lang.ClassLoader.loadClass(ClassLoader.java:425),com.google.appengine.tools.development.IsolatedAppClassLoader.loadClass(IsolatedAppClassLoader.java:216),java.lang.ClassLoader.loadClass(ClassLoader.java:358),java.lang.Class.forName0(Native Method),java.lang.Class.forName(Class.java:270),controllers.api.AuthenticationController.get(AuthenticationController.java:49),sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method),sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57),sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43),java.lang.reflect.Method.invoke(Method.java:606),com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:115),ninja.params.ControllerMethodInvoker.invoke(ControllerMethodInvoker.java:56),ninja.FilterChainEnd.next(FilterChainEnd.java:48),ninja.NinjaDefault.onRouteRequest(NinjaDefault.java:82),ninja.servlet.NinjaServletDispatcher.service(NinjaServletDispatcher.java:83),com.google.inject.servlet.ServletDefinition.doServiceImpl(ServletDefinition.java:278),com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:268),com.google.inject.servlet.ServletDefinition.service(ServletDefinition.java:180),com.google.inject.servlet.ManagedServletPipeline.service(ManagedServletPipeline.java:93),com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:85),com.googlecode.objectify.cache.AsyncCacheFilter.doFilter(AsyncCacheFilter.java:59),com.googlecode.objectify.ObjectifyFilter.doFilter(ObjectifyFilter.java:49),com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82),com.google.inject.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:120),com.google.inject.servlet.GuiceFilter$1.call(GuiceFilter.java:134),com.google.inject.servlet.GuiceFilter$1.call(GuiceFilter.java:131),com.google.inject.servlet.GuiceFilter$Context.call(GuiceFilter.java:208),com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:131),org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157),com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74),org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157),com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:127),org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157),com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34),org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157),com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:63),org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157),com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43),org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157),com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125),org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157),com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:366),com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:349),com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116),org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157),org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388),org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216),org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182),org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765),org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418),com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:98),org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152),com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:491),org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152),org.mortbay.jetty.Server.handle(Server.java:326),org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542),org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938),org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755),org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218),org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404),org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409),org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)]
The resolution of this was to manually include the dependency for fasterxml.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.2</version>
</dependency>
I'm not sure why this is the case, but wanted to document it here just in case anybody else runs into this in the future.
BTW, This looks like an AWESOME library!
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
Hi, your lib is awesome. Could you please add some manifest data to run it in osgi-container?
How do I add a map of custom claims to the jwt ? For example, if I wanted to add a user's role
Currently iam doing it like this
return Jwts.builder()
.setSubject(subject)
.setIssuer(issuer)
.setId(UUID.randomUUID().toString())
.setExpiration(setExpiry(expiresIn))
.setClaims(claims)
.signWith(this.Algo, this.getEncodedSecret())
.compact();
This is just a portion of a function. Claims is variable of Map<String, Object> type. Iam using this as the custom claims, but when I do this, my token is generated without an expiry date. What am I doing wrong?
Two security issues.
Must change the parse function and make it mandatory to specify decrypt algorithm instead of reading it from header.
'none' algorithm is open for abuse.
Please read this article https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/ to see the detail discussion on these issues.
I already create a question on StackOverflow for the issue.
Thanks you.
I'm playing with the library right now, and most of the default class impls don't have useful toString() implementations on them. JwtMap could have a simple toString() (delegate to the internal map). Would be nice to add toString() to some of the other value types (e.g. DefaultJws, etc.).
Hello, an interface Jwt (io.jsonwebtoken) has only two methods: getHeader() and getBody().
How to retrieve ALL token's headers? I am thinking a method like "getHeaders()".
Can i do it?
thankx
Hi, I'm getting this error:
Getting: java.lang.IllegalStateException: Either 'payload' or 'claims' must be specified.
try {
String s = Jwts.builder().signWith(SignatureAlgorithm.HS256, "61c5fd4007060fd9ed41fc6f2a155a3a47629b9e9b83d75d1c0d97ebb177fa83").compact();
Jwts.parser().setSigningKey(s).parseClaimsJws(obj.getString(JSONNodes.json_token));
//OK, we can trust this JWT
app.getDatabase().beginTransaction();
app.user.setToken(obj.getString(JSONNodes.json_token));
app.getDatabase().commitTransaction();
} catch(SignatureException e) {
//Don't trust the JWT! Clear user or handle error messaging
app.clearUser();
}
What I'm missing or doing wrong?
For example token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0NTAzNDQ4NDcsImV4cCI6MTQ1MDM0NDkwNywidXNlcl9pZCI6bnVsbCwicmlnaHRzIjpudWxsfQ.p4v00qCakzuMZgLHAlzPB9o0z1DhLz8Ky03fmSaAxcc
The documentation does not state it, but in the code, you can see that any call to setClaims(...)
in JwtBuilder
will overwrite any convenience claims that were written (e.g., setIssuer()
, setAudience()
, etc.). This is somewhat inconsistent, since audience
, issuer
, etc., are claims (registered) as well. It may be more clear to just leave out setIssuer()
, setAudience()
, and company, rather than allowing them in the builder, even if they are convenient there. What is the expected behavior when you set the audience
in the claims
and in the builder
? It now depends on the order in which you set them:
JwtBuilder
) before you set the claims they will be erased, but if you set the audience AFTER you set the claims they will be set.Claims
and then set it again in the JwtBuilder
(AFTER calling setClaims
), the audience will be overwritten by the one set in JwtBuilder
.I don't think people should be setting them in both places very often and if they do it's almost always going to be by mistake, but I still think it would be more clear to remove the convenience methods for setting default claims out of the builder. Or, remove/rename setClaims
and change it to addClaims
(add claims won't overwrite claims now, but just add onto it if it already exist).
Parsin JWT string using jjwt-0.5 fails on android platform.
jjwt library is added to android project as gradle dependency.
compile 'io.jsonwebtoken:jjwt:0.5'
Following code
String json = "{ \"name\" : \"John\"}";
String jwt = Jwts.builder().setPayload(json).compact();
System.out.println("JWT = " + jwt);
String name = Jwts.parser().parseClaimsJwt(jwt).getBody().get("name").toString();
System.out.println("name = " + name);
works correctly on desktop JDK producing following output
JWT = eyJhbGciOiJub25lIn0.eyAibmFtZSIgOiAiSm9obiJ9.
name = John
However when the same code is run on android (Nexus-5 device running android 5.1.1) if fails with exception thrown from parseClaimsJwt
method:
JWT = eyJhbGciOiJub25lIn0.eyAibmFtZSIgOiAiSm9obiJ9.
Caused by: io.jsonwebtoken.UnsupportedJwtException: Signed JWSs are not supported.
at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJwt(DefaultJwtParser.java:365)
at com.example.MainActivity.onCreate(MainActivity.java:53)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
... 10 more
Caused by: java.lang.IllegalArgumentException: bad base-64
at android.util.Base64.decode(Base64.java:161)
at android.util.Base64.decode(Base64.java:136)
at android.util.Base64.decode(Base64.java:118)
at io.jsonwebtoken.impl.AndroidBase64Codec.decode(AndroidBase64Codec.java:28)
at io.jsonwebtoken.impl.Base64UrlCodec.decode(Base64UrlCodec.java:78)
at io.jsonwebtoken.impl.AbstractTextCodec.decodeToString(AbstractTextCodec.java:36)
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:161)
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:325)
at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJwt(DefaultJwtParser.java:358)
It looks to me that android.util.Base64.decode()
method (that is used internally by jjwt) requires input to contain padding characters (=
) (or it just needs to be configured/called different way).
If I modify JWT string passed to parseClaimsJwt
method by adding missing padding character (=
) then it works correctly on android. Following code (with =
added in proper place inside JWT string)
String jwt = "eyJhbGciOiJub25lIn0=.eyAibmFtZSIgOiAiSm9obiJ9.";
String name = Jwts.parser().parseClaimsJwt(jwt).getBody().get("name").toString();
System.out.println("name = " + name);
... produces expected result:
name = John
I glimpsed quickly through the jjwt code and line https://github.com/mikosik/jjwt/blob/master/src/main/java/io/jsonwebtoken/impl/Base64UrlCodec.java#L85 looks fishy to me.
It is:
int paddingCount = chars.length % 4;
but I guess it should be
int paddingCount = 4 - chars.length % 4;
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.