Giter VIP home page Giter VIP logo

vertx-auth's People

Contributors

afloarea avatar agilob avatar alliagesphere avatar brunovernay avatar cescoffier avatar dependabot[bot] avatar drakkan avatar francoisprunier avatar gaol avatar jo5ef avatar johnoliver avatar jponge avatar lusoalex avatar matthudsonatx avatar mguillet avatar nevenr avatar otricadziziusz avatar paulgallagher75 avatar pendula95 avatar pmlopes avatar purplefox avatar rgmz avatar sczyh30 avatar slinkydeveloper avatar stephanebastian avatar tsegismont avatar vietj avatar vorimo avatar ynojima avatar zenios 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

vertx-auth's Issues

Add an option to specify the signing algorithm

Actually the signing algorithm is the same as the certificate, but in some cases you must use another.

  CryptoSignature(final X509Certificate certificate, final PrivateKey privateKey) {
    this.certificate = certificate;
    this.privateKey = privateKey;
    try {
      this.sig = Signature.getInstance(certificate.getSigAlgName());
    } catch (NoSuchAlgorithmException e) {
      throw new RuntimeException(e);
    }
  }

In the "Google Cloud Plataform" we need to sign the JWT with SHA256withRSA using the private key of PKCS#12 certificate. The certificate is generated by Google and the sign algorithm of certificate is SHA1withRSA :(

https://developers.google.com/identity/protocols/OAuth2ServiceAccount

vertx-auth-jwt not working

I'm trying to integrate jwt token in my vertx but can't generate a token.

I got the exception below:

java.lang.RuntimeException: Algorithm not supported
    at io.vertx.ext.auth.jwt.impl.JWT.sign(JWT.java:171)
    at io.vertx.ext.auth.jwt.impl.JWTAuthProviderImpl.generateToken(JWTAuthProviderImpl.java:145)
    at ca.mavencode.pga.handler.AuthHandler.lambda$handle$5(AuthHandler.java:42)
    at ca.mavencode.pga.handler.AuthHandler$$Lambda$19/1795160029.handle(Unknown Source)
    at ca.mavencode.pga.jdbc.impl.JDBCAuthImpl.lambda$authenticate$1(JDBCAuthImpl.java:66)
    at ca.mavencode.pga.jdbc.impl.JDBCAuthImpl$$Lambda$20/305717969.accept(Unknown Source)
    at ca.mavencode.pga.jdbc.impl.JDBCAuthImpl.lambda$null$3(JDBCAuthImpl.java:119)
    at ca.mavencode.pga.jdbc.impl.JDBCAuthImpl$$Lambda$24/394295754.handle(Unknown Source)
    at io.vertx.core.impl.FutureImpl.checkCallHandler(FutureImpl.java:135)
    at io.vertx.core.impl.FutureImpl.setHandler(FutureImpl.java:100)
    at io.vertx.core.impl.ContextImpl.lambda$null$13(ContextImpl.java:288)
    at io.vertx.core.impl.ContextImpl$$Lambda$26/456330793.handle(Unknown Source)
    at io.vertx.core.impl.ContextImpl.lambda$wrapTask$15(ContextImpl.java:314)
    at io.vertx.core.impl.ContextImpl$$Lambda$3/1729958231.run(Unknown Source)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:357)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
    at java.lang.Thread.run(Thread.java:745)

But I can see these logs on my console,

Sep 19, 2015 6:18:41 PM io.vertx.ext.auth.jwt.impl.JWT
INFO: HS256 not available
Sep 19, 2015 6:18:41 PM io.vertx.ext.auth.jwt.impl.JWT
INFO: HS384 not available
Sep 19, 2015 6:18:41 PM io.vertx.ext.auth.jwt.impl.JWT
INFO: HS512 not available
Sep 19, 2015 6:18:41 PM io.vertx.ext.auth.jwt.impl.JWT
INFO: RS256 not available
Sep 19, 2015 6:18:41 PM io.vertx.ext.auth.jwt.impl.JWT
INFO: RS384 not available
Sep 19, 2015 6:18:41 PM io.vertx.ext.auth.jwt.impl.JWT
INFO: RS512 not available
Sep 19, 2015 6:18:41 PM io.vertx.ext.auth.jwt.impl.JWT
INFO: ES256 not available
Sep 19, 2015 6:18:41 PM io.vertx.ext.auth.jwt.impl.JWT
INFO: ES384 not available
Sep 19, 2015 6:18:41 PM io.vertx.ext.auth.jwt.impl.JWT
INFO: ES512 not available

How can I resolve this and generate jwt tokens

Btw, I generated my keystore and added it to my classpath

keytool -genseckey -keystore keystore.jck -storetype jceks -storepass password -keyalg AES -keysize 256 -alias pga -keypass password 

Refactor roles/permissions to authorities

Currently we have user.hasRole(String) and user.hasPermission(String) even though the separation of roles and permissions sounds logic there are some deficiencies with the current implementation.

The first false assumption is that roles and permissions are independent and relate to a user. So say that user Paulo has role dev and permission push. Now lets assume the whole application knows about the roles dev and devops and a dev role can push code and a devops role can push releases into production.

Now with our model if we want to assert if Paulo can push to production we need to do:

paulo.hasRole("devops") && paulo.hasPermission("push")

The logic here would fail since false && true is false. Now just say that because I am the lead developer i might have read access to prod to pull logs or something... so now Paulo is a dev with push permissions and devops with read permissions.

The same check from above will assert true even tough it is not correct. The hasPermission has no context about from which role to check the permission for.

How can we fix this:

We need to refactor the User to have a method hasAuthority(String) if we like the Spring style or isPermitted(String) if we like the Shiro style. After reading both I am tending for Shiro...

Now the assertion is a String, both Spring and Shiro have conventions about the format of the Strings. Looking at Shiro a authority has the format:

<role or domain>[:<action>[:<instance>]]

examples would be:

printers:print:color_printer_1st_floor
devops:read
dev:push

The impact is that using this approach we can have the same model fitting all current implementations:

  • shiro
  • jwt
  • jdbc

The Strings are opaque so they only have specific meaning to the implementations and no assumptions on the format is made by vertx-auth, the usage of the format above is just an example and if one prefers can use String notation:

Role_devops
Role_dev
devops:push
devops:read
dev:push

Since the assumption is that the String are opaque it is to the implementation of auth providers to define if they support or not wildcards, e.g.: printers:print:*.

JWTAuth.create(...) skip parameter is a bit too eager when logic invoked in JWTAuthHandlerImpl

Version

  • vert.x core: 3.2.1
  • vert.x auth: 3.2.1

Context

The skip parameter is too eager. The code checks for whether or not the skip string contains the request string:

if (skip != null && skip.contains(request.path())) {
        context.next();
        return;
}

If the skip String is configured such as '/health' and the request.path() == '/' then the skip execution always occurs which is probably not what was intended?

I'm not sure what the best behavior here is... My suggestion would be to make it so that if someone specifies a skip that does not end in * or /* then the check should be for equality, for example, only skip if request.path().equals(skip). If the skip String is, for example, instead /health* or /health/* then it should should work as request.path().startsWith(skip). Perhaps the inverse should be true if someone specifies a skip string preceded by * or */.

Do you have a reproducer?

Not public at the moment. Trivial to see the problem though.

Steps to reproduce

Extra

I worked around the issue by sub classing the JWTAuthHandlerImpl and writing my own skip implementation that works for my specific situation.

vertx mongo auth js is broken

Version

  • vert.x core:3.2.1
  • vert.x auth:3.2.1

Context

The Javascript example for vertx mongo auth just does not work.

Do you have a reproducer?

https://groups.google.com/forum/#!topic/vertx/AfjHVJy4wtk has already raised the issue. I am repeating it here to see if it helps.

Steps to reproduce

Just follow the documentation to create a JS vertx mongo auth client. Call to authenticate fails with a TypeErrpr. https://github.com/markus-simon/auth example is linked from the Google Groups link above

OAuth2AuthHandler callback allows unauthorized access

Version

  • vert.x core: 3.2.1
  • vert.x auth: 3.2.1

Context

http://localhost:8080/callback?redirect_uri=/private/somepage/test leads to unauthorized acces while http://localhost:8080/private/somepage/test starts auth process correctly.

Output:
Welcome to the protected resource! :

{
"error" : "bad_verification_code",
"error_description" : "The code passed is incorrect or expired.",
"error_uri" : "https://developer.github.com/v3/oauth/#bad-verification-code"
}

Do you have a reproducer?

https://gist.github.com/amoAHCP/b3509d859096952caf76f46665835525

code error

Version

  • vert.x core: 3.2.1
  • vert.x auth: 3.2.1

Context

This is the code in MongoAuthImpl


String permissionField = config.getString(PROPERTY_PERMISSION_FIELD);
if (roleField != null) {
setPermissionField(permissionField);

}

I think the if condition should be

if (permissionField != null) {

Similar LDAP Auth as in SpringBoot

Hi @pmlopes @vietj I looked into the shiro eample in vertx-auth but could not find equivalent to SpringBoot's LDAP auth:

https://spring.io/guides/gs/authenticating-ldap/

More specifically, how to use a bind DN (manager DN) to authenticate users - using group search base and search filter? Here is what we are doing with Spring:

public void init(AuthenticationManagerBuilder auth) throws Exception {
            auth.ldapAuthentication()
                    .userSearchFilter(
                            "((sAMAccountName={0})(objectclass=organizationalPerson))")
                    .userSearchBase("OU="+environment.getProperty("ldap.user-search-base.name"))
                    .groupSearchFilter("(member={0})")
                    .groupSearchBase("OU=Global-Groups")
                    .contextSource().url(environment.getProperty("ldap.url"))
                    .managerDn(environment.getProperty("ldap.conn.user"))
                    .managerPassword(environment.getProperty("ldap.conn.pwd"));

            setAuthenticationManager(auth.getObject());

        }

Is this something supported by vetx-auth right now? or a future feature? Without a similar LDAP auth as SprintBoot offering, it is hard to for us to use vertx-web to migrate existing spring web projects fully over to vertx.

Please advise. Thanks!

Alan

"vertx-auth-shiro-js/shiro_auth" will crash if you included "vertx-web-js/router" before it and authenticate successfully

For some reason the order of inclusion of Vert.x JS components matters: putting the router before shiro auth causes this error on the 3.0.0 release upon successful authentication:

Unhandled exception 
vertx-js/util/utils.js:208 TypeError: undefined is not an Object
        at jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:57)
        at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:213)
        at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:185)
        at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:172)
        at jdk.nashorn.internal.objects.Global.checkObject(Global.java:1673)
        at jdk.nashorn.internal.objects.NativeObject.create(NativeObject.java:261)
        at jdk.nashorn.internal.scripts.Script$Recompilation$122$5673AA$\^eval\_#88\!17\^eval\_.L:1$convReturnVertxGen(vertx-js/util/utils.js:208)
        at jdk.nashorn.internal.scripts.Script$Recompilation$154$2273A$\^eval\_#88\!17\^eval\_.L:1$AuthProvider$authenticate$L:60(vertx-auth-common-js/auth_provider.js:62)
        at io.vertx.core.Handler$$NashornJavaAdapter.handle(Unknown Source)
        at io.vertx.core.impl.FutureImpl.checkCallHandler(FutureImpl.java:135)
        at io.vertx.core.impl.FutureImpl.setHandler(FutureImpl.java:100)
        at io.vertx.core.impl.ContextImpl.lambda$null$13(ContextImpl.java:288)
        at io.vertx.core.impl.ContextImpl$$Lambda$12/390709726.handle(Unknown Source)
        at io.vertx.core.impl.ContextImpl.lambda$wrapTask$15(ContextImpl.java:314)
        at io.vertx.core.impl.ContextImpl$$Lambda$7/1318310462.run(Unknown Source)
        at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:357)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357)
        at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
        at java.lang.Thread.run(Thread.java:745)

That was from vertx run shirotest.js with the following code and a shirotest.properties file containing user.correct = pw. It works fine if you reverse the order and include shiro_auth before router or if you use invalid credentials. Perhaps something to do with creating the User object?

var Router = require("vertx-web-js/router");
var ShiroAuth = require("vertx-auth-shiro-js/shiro_auth");
var shiroConfig = {
  "properties_path" : "file:shirotest.properties"
};
var shiro = ShiroAuth.create(vertx, 'PROPERTIES', shiroConfig);
var authInfo = {
  "username" : "correct",
  "password" : "pw"
};
shiro.authenticate(authInfo, function (res, res_err) {
  if (res_err === null) {
    logger.info("yep");
  } else {
    logger.info("nope");
  }
});

Suppress error stack of JWT trying to load unsupported MAC

Hi,

Currently, as JWT class is trying to load MAC algorithm of configured keystore file, it logs NullPointerException if an algorithm isn't supported, as shown in this line. This makes the application logs to be polluted with rather meaningless error stack trace like so

22:49:23.968 [vert.x-eventloop-thread-2] io.vertx.ext.auth.jwt.impl.JWT [WARN ] [API] - HS256 not supported
java.lang.NullPointerException: null
    at io.vertx.ext.auth.jwt.impl.JWT.getMac(JWT.java:86) ~[vertx-auth-jwt-3.0.0-milestone6.jar:na]
    at io.vertx.ext.auth.jwt.impl.JWT.<init>(JWT.java:53) ~[vertx-auth-jwt-3.0.0-milestone6.jar:na]
    at io.vertx.ext.auth.jwt.impl.JWTAuthProviderImpl.<init>(JWTAuthProviderImpl.java:77) [vertx-auth-jwt-3.0.0-milestone6.jar:na]
    at io.vertx.ext.auth.jwt.JWTAuth.create(JWTAuth.java:39) [vertx-auth-jwt-3.0.0-milestone6.jar:na]
    at com.panjiesw.std.api.ApiVerticle.createAuthProvider(ApiVerticle.java:115) [main/:na]
    at com.panjiesw.std.api.ApiVerticle.startModule(ApiVerticle.java:88) [main/:na]
    at com.panjiesw.std.api.ApiVerticle.lambda$handleService$1(ApiVerticle.java:78) [main/:na]
    at com.panjiesw.std.api.ApiVerticle$$Lambda$8/383266732.handle(Unknown Source) [main/:na]
    at io.vertx.core.impl.DeploymentManager.lambda$reportResult$159(DeploymentManager.java:436) [vertx-core-3.0.0-milestone6.jar:na]
    at io.vertx.core.impl.DeploymentManager$$Lambda$14/677334899.handle(Unknown Source) [vertx-core-3.0.0-milestone6.jar:na]
    at io.vertx.core.impl.ContextImpl.lambda$wrapTask$15(ContextImpl.java:312) [vertx-core-3.0.0-milestone6.jar:na]
    at io.vertx.core.impl.ContextImpl$$Lambda$7/1448061896.run(Unknown Source) [vertx-core-3.0.0-milestone6.jar:na]
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:380) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_45]
22:49:23.969 [vert.x-eventloop-thread-2] io.vertx.ext.auth.jwt.impl.JWT [WARN ] [API] - HS384 not supported
java.lang.NullPointerException: null
    at io.vertx.ext.auth.jwt.impl.JWT.getMac(JWT.java:86) ~[vertx-auth-jwt-3.0.0-milestone6.jar:na]
    at io.vertx.ext.auth.jwt.impl.JWT.<init>(JWT.java:53) ~[vertx-auth-jwt-3.0.0-milestone6.jar:na]
    at io.vertx.ext.auth.jwt.impl.JWTAuthProviderImpl.<init>(JWTAuthProviderImpl.java:77) [vertx-auth-jwt-3.0.0-milestone6.jar:na]
    at io.vertx.ext.auth.jwt.JWTAuth.create(JWTAuth.java:39) [vertx-auth-jwt-3.0.0-milestone6.jar:na]
    at com.panjiesw.std.api.ApiVerticle.createAuthProvider(ApiVerticle.java:115) [main/:na]
    at com.panjiesw.std.api.ApiVerticle.startModule(ApiVerticle.java:88) [main/:na]
    at com.panjiesw.std.api.ApiVerticle.lambda$handleService$1(ApiVerticle.java:78) [main/:na]
    at com.panjiesw.std.api.ApiVerticle$$Lambda$8/383266732.handle(Unknown Source) [main/:na]
    at io.vertx.core.impl.DeploymentManager.lambda$reportResult$159(DeploymentManager.java:436) [vertx-core-3.0.0-milestone6.jar:na]
    at io.vertx.core.impl.DeploymentManager$$Lambda$14/677334899.handle(Unknown Source) [vertx-core-3.0.0-milestone6.jar:na]
    at io.vertx.core.impl.ContextImpl.lambda$wrapTask$15(ContextImpl.java:312) [vertx-core-3.0.0-milestone6.jar:na]
    at io.vertx.core.impl.ContextImpl$$Lambda$7/1448061896.run(Unknown Source) [vertx-core-3.0.0-milestone6.jar:na]
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:380) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_45]
22:49:23.971 [vert.x-eventloop-thread-2] io.vertx.ext.auth.jwt.impl.JWT [WARN ] [API] - HS512 not supported
java.lang.NullPointerException: null
    at io.vertx.ext.auth.jwt.impl.JWT.getMac(JWT.java:86) ~[vertx-auth-jwt-3.0.0-milestone6.jar:na]
    at io.vertx.ext.auth.jwt.impl.JWT.<init>(JWT.java:53) ~[vertx-auth-jwt-3.0.0-milestone6.jar:na]
    at io.vertx.ext.auth.jwt.impl.JWTAuthProviderImpl.<init>(JWTAuthProviderImpl.java:77) [vertx-auth-jwt-3.0.0-milestone6.jar:na]
    at io.vertx.ext.auth.jwt.JWTAuth.create(JWTAuth.java:39) [vertx-auth-jwt-3.0.0-milestone6.jar:na]
    at com.panjiesw.std.api.ApiVerticle.createAuthProvider(ApiVerticle.java:115) [main/:na]
    at com.panjiesw.std.api.ApiVerticle.startModule(ApiVerticle.java:88) [main/:na]
    at com.panjiesw.std.api.ApiVerticle.lambda$handleService$1(ApiVerticle.java:78) [main/:na]
    at com.panjiesw.std.api.ApiVerticle$$Lambda$8/383266732.handle(Unknown Source) [main/:na]
    at io.vertx.core.impl.DeploymentManager.lambda$reportResult$159(DeploymentManager.java:436) [vertx-core-3.0.0-milestone6.jar:na]
    at io.vertx.core.impl.DeploymentManager$$Lambda$14/677334899.handle(Unknown Source) [vertx-core-3.0.0-milestone6.jar:na]
    at io.vertx.core.impl.ContextImpl.lambda$wrapTask$15(ContextImpl.java:312) [vertx-core-3.0.0-milestone6.jar:na]
    at io.vertx.core.impl.ContextImpl$$Lambda$7/1448061896.run(Unknown Source) [vertx-core-3.0.0-milestone6.jar:na]
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:380) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_45]

The log should not include the error stack trace i think, like in SIGNATURE loops below that line

fromRealm returns null

As per my exploration of using vertx with shiro and stormpath here https://groups.google.com/forum/?fromgroups=#!topic/vertx/rO8xlDof1qA

I have encountered a defect.

If in my code I do this:

  router.route().handler((RoutingContext context) -> {
        context.user().isAuthorised("role:84c2a410-b761-44cd-88c7-a8bba0e976cb+admins", (AsyncResult<Boolean> res) -> {
           if (res.succeeded()) {
              boolean hasPermission = res.result();
              if (hasPermission) {
                 context.next();
              } else {
                 context.response().setStatusCode(403).end("You do not have access to that group!");
              }
           } else {
              context.response().setStatusCode(403).end("Error asking if authorised");
           }
        });
     });

The isAuthorised calls through to stormpath's implementation of doGetAuthorizationInfo

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
   assertState();
   SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
   String href = getAccountHref(principals);
...
protected String getAccountHref(PrincipalCollection principals) {
   Collection c = principals.fromRealm(getName());
   //Based on the createPrincipals implementation above, the first one is the Account href:
   return (String) c.iterator().next();
}

Which calls vert'x:

public class SimplePrincipalCollection implements PrincipalCollection {
...
@Override
public Collection fromRealm(String realmName) {
  return null;
}

And is hardcoded to null. And thus exceptions in getAccountHref

KeyCloak jwt support

Scenario: A JavaScript UI that uses the KeyCloak redirect flow, and a Vert.x REST backend. The UI authenticates with the redirect and gets a token from KeyCloak. The token is added to each request to the Vert.x backend.

The KeyCloak token is, according the KeyCloak docs, "an extension of JWT". The token is self contained, meaning that user info such as the user's roles are embedded in the token. To check authorization for a specific action on the Vert.x backend, the backend would have to verify the token (using the public key), and read the roles from the token. No communication with KeyCloak is required.

Problem: The oauth2 module for Vert.x supports KeyCloak, but only the redirect flow. This is not useful in the scenario where Vert.x is only used for serving the backend. The jwt module sort of does the right thing, but doesn't seem to support KeyCloak token. This has to do with the specific format of the token, but I'm not sure about the details of this problem.

This should be supported out of the box. I did create a workaround, but this relies on an implementation class from the oauth2 module. Alternatively one of the available 3rd party JWT libraries could be used, but support in Vert.x would be a lot easier.
The following is an example of the code that I'm currently using for auth, based on the TokenVerifier, which is an implementation class.

import io.vertx.ext.auth.oauth2.impl.crypto.TokenVerifier;

public void handle(RoutingContext req) {
        String authHeader = req.request().getHeader("Authorization");
        if(authHeader != null) {
            String jwt = authHeader.substring(authHeader.indexOf(" ") + 1);
            TokenVerifier tokenVerifier = new TokenVerifier(m_config.keycloakPublicKey);
            JsonObject verify = tokenVerifier.verify(jwt);
            req.setUser(new User(new WebUser(verify)));

            req.next();
        } else {
            req.response().setStatusCode(403).end();
        }
    }

The WebUser type is just a wrapper.

public class WebUser implements User{

    private final JsonObject m_principal;

    public WebUser(JsonObject principal) {
        this.m_principal = principal;
    }

    @Override
    public User isAuthorised(String authority, Handler<AsyncResult<Boolean>> resultHandler) {
        return this;
    }

    @Override
    public User clearCache() {
        return this;
    }

    @Override
    public JsonObject principal() {
        return m_principal;
    }

    @Override
    public void setAuthProvider(AuthProvider authProvider) {
    }
}

Once we decide on the correct solution I would be happy to work on a PR.

OAuth getToken result.failed() information is inconsistent when sending invalid code as payload

Version

  • vert.x core: 3.3.0
  • vert.x auth: 3.3.2

Context

OAuth getToken never flags result.failed() as true for invalid code sent. I am testing this with GitHub provider. Note in the debugger image that the result.failed() is always false and docs (http://vertx.io/docs/vertx-auth-oauth2/java/) says it should be true on error.

oauth2.getToken(new JsonObject().put("code", code).put("redirect_uri", "http://localhost:8080/callback"), res -> {
  if (res.failed()) {
    // error, the code provided is not valid
  } else {
    // save the token and continue...
  }
});

Do you have a reproducer?

screen shot 2016-07-13 at 2 40 47 pm

screen shot 2016-07-13 at 2 41 04 pm

Feature: Do not require private key for JWT if not planning to sign tokens?

Right now the JWT module requires a private key for asymetric keys in order to be used, however, if you're only interested in decoding and verifying a key then this is an unnecessary additional piece of security data that needs to be stored in the key store. The piece of code responsible for this is located here:

X509Certificate certificate = getCertificate(keyStore, alg);
PrivateKey privateKey = getPrivateKey(keyStore, keyStorePassword, alg);
if (certificate != null && privateKey != null) {
  tmp.put(alg, new CryptoSignature(alias.get(alg), certificate, privateKey));
} else {
  log.info(alg + " not available");
}

Can the requirement that a private key be present be lifted?

MongoAuth assumes username

Version

  • vert.x core: 3.3.3
  • vert.x auth: 3.3.3

Context

I noticed the MongoAuth is assuming that users are identified using a username. This applies to both the API (eg from MongoAuthImpl: public void insertUser(String username, String password,...)), as well as any error messages: (eg: resultHandler.handle((Future.failedFuture("Username must be set for authentication.")));).

I would like to use user emails rather than usernames, and although I perfectly can using the customisation options, I do feel there is a bit of a mismatch.

I suggest replacing username by userIdentifier or something similar. This could be changed without breaking compatibility.

OAuth2 final redirect should be a HTTP redirect

Currently the final redirect is handled internally, however this can cause problems if a user refreshes the html page since a new token request is done and invalidates the token.

Doing a HTTP redirect (would enforce users use a session handler) so state is preserved and no issues would happen due to refresh page.

Keycloak handler fails on reload

Version

  • vert.x core: master (May 1st)
  • vert.x auth: master (May 1st)

Context

I created a Keycloak handler as shown in this video.

Vertx vertx = Vertx.vertx();        
Router router = Router.router(vertx);
OAuth2AuthHandler oauth2 = OAuth2AuthHandler.create(OAuth2Auth.createKeycloak(vertx, OAuth2FlowType.AUTH_CODE, new JsonObject("...")), "http://localhost:8282");
oauth2.setupCallback(router.get("/callback"));
router.route("/secure/*").handler(oauth2);
router.route("/secure/test").handler(rc -> {
    rc.response().end("This is a secure page!");
});

vertx.createHttpServer().requestHandler(router::accept).listen(8282);

The request to secure/test gets redirected to the Keycloak login page as expected. After login I get redirected like url http://localhost:8282/callback?redirect_uri=/secure/test&state=&code=mYYbNf79vby_ALu5M2swWwJ0Com4eto5RQNJpPjjduQ.b09a7d59-ef84-4dd1-a981-b16a396fed16, which shows This is a secure page! correctly.
When I refresh the page however, it fails. The page returns "Internal Server Error", and on the application's console I see:

io.vertx.ext.web.impl.RoutingContextImplBase
SEVERE: Unexpected exception in route
io.vertx.core.impl.NoStackTraceThrowable: Bad Request

Creating a new JWT token and adding user to session results in exceptions deserializing the JWT user object later

When clustered using Hazelcast, create JWT Token, validate it by calling provider.authenticate() then routingContext.setUser() so it is available immediately. Next requests that come in all fail with:

19:19:56.440 [vert.x-eventloop-thread-2] ERROR i.v.e.w.impl.RoutingContextImplBase - Unexpected exception in route
com.hazelcast.nio.serialization.HazelcastSerializationException: Problem while reading DataSerializable, namespace: 0, id: 0, class: 'io.vertx.spi.cluster.hazelcast.impl.HazelcastAsyncMap$DataSerializableHolder', exception: Failed to load class io.vertx.core.VertxException: java.lang.InstantiationException: io.vertx.ext.auth.jwt.impl.JWTUser
    at com.hazelcast.nio.serialization.DataSerializer.read(DataSerializer.java:120) ~[hazelcast-3.5.jar:3.5]
    at com.hazelcast.nio.serialization.DataSerializer.read(DataSerializer.java:39) ~[hazelcast-3.5.jar:3.5]
    at com.hazelcast.nio.serialization.StreamSerializerAdapter.read(StreamSerializerAdapter.java:41) ~[hazelcast-3.5.jar:3.5]
    at com.hazelcast.nio.serialization.SerializationServiceImpl.toObject(SerializationServiceImpl.java:276) ~[hazelcast-3.5.jar:3.5]
    at com.hazelcast.spi.impl.NodeEngineImpl.toObject(NodeEngineImpl.java:200) ~[hazelcast-3.5.jar:3.5]
    at com.hazelcast.map.impl.MapServiceContextImpl.toObject(MapServiceContextImpl.java:281) ~[hazelcast-3.5.jar:3.5]
    at com.hazelcast.map.impl.proxy.MapProxySupport.toObject(MapProxySupport.java:1114) ~[hazelcast-3.5.jar:3.5]
    at com.hazelcast.map.impl.proxy.MapProxyImpl.get(MapProxyImpl.java:82) ~[hazelcast-3.5.jar:3.5]
    at io.vertx.spi.cluster.hazelcast.impl.HazelcastAsyncMap.lambda$get$13(HazelcastAsyncMap.java:46) ~[vertx-hazelcast-3.0.0.jar:na]
    at io.vertx.spi.cluster.hazelcast.impl.HazelcastAsyncMap$$Lambda$72/589483425.handle(Unknown Source) ~[na:na]
    at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$14(ContextImpl.java:279) ~[vertx-core-3.0.0.jar:na]
    at io.vertx.core.impl.ContextImpl$$Lambda$35/1335061928.run(Unknown Source) ~[na:na]
    at io.vertx.core.impl.OrderedExecutorFactory$OrderedExecutor.lambda$new$161(OrderedExecutorFactory.java:91) ~[vertx-core-3.0.0.jar:na]
    at io.vertx.core.impl.OrderedExecutorFactory$OrderedExecutor$$Lambda$34/711310213.run(Unknown Source) ~[na:na]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_25]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_25]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_25]
Caused by: java.lang.IllegalStateException: Failed to load class io.vertx.core.VertxException: java.lang.InstantiationException: io.vertx.ext.auth.jwt.impl.JWTUser
    at io.vertx.spi.cluster.hazelcast.impl.HazelcastAsyncMap$DataSerializableHolder.readData(HazelcastAsyncMap.java:178) ~[vertx-hazelcast-3.0.0.jar:na]
    at com.hazelcast.nio.serialization.DataSerializer.read(DataSerializer.java:111) ~[hazelcast-3.5.jar:3.5]
    ... 16 common frames omitted
Caused by: io.vertx.core.VertxException: io.vertx.core.VertxException: java.lang.InstantiationException: io.vertx.ext.auth.jwt.impl.JWTUser
    at io.vertx.ext.web.sstore.impl.SessionImpl.readDataFromBuffer(SessionImpl.java:309) ~[vertx-web-3.0.0.jar:na]
    at io.vertx.ext.web.sstore.impl.SessionImpl.readFromBuffer(SessionImpl.java:145) ~[vertx-web-3.0.0.jar:na]
    at io.vertx.spi.cluster.hazelcast.impl.HazelcastAsyncMap$DataSerializableHolder.readData(HazelcastAsyncMap.java:176) ~[vertx-hazelcast-3.0.0.jar:na]
    ... 17 common frames omitted
Caused by: io.vertx.core.VertxException: java.lang.InstantiationException: io.vertx.ext.auth.jwt.impl.JWTUser
    at io.vertx.ext.web.handler.impl.UserHolder.readFromBuffer(UserHolder.java:79) ~[vertx-web-3.0.0.jar:na]
    at io.vertx.ext.web.sstore.impl.SessionImpl.readDataFromBuffer(SessionImpl.java:299) ~[vertx-web-3.0.0.jar:na]
    ... 19 common frames omitted
Caused by: java.lang.InstantiationException: io.vertx.ext.auth.jwt.impl.JWTUser
    at java.lang.Class.newInstance(Class.java:423) ~[na:1.8.0_25]
    at io.vertx.ext.web.handler.impl.UserHolder.readFromBuffer(UserHolder.java:75) ~[vertx-web-3.0.0.jar:na]
    ... 20 common frames omitted
Caused by: java.lang.NoSuchMethodException: io.vertx.ext.auth.jwt.impl.JWTUser.<init>()
    at java.lang.Class.getConstructor0(Class.java:3074) ~[na:1.8.0_25]
    at java.lang.Class.newInstance(Class.java:408) ~[na:1.8.0_25]
    ... 21 common frames omitted

That last "caused by" seems to say that something wants it to have a default constructor and it does not?

Stormpath and vertx realm name disagree

This is the next issue related to #21, see that ticket for the setup.

protected String getAccountHref(PrincipalCollection principals) {
       Collection c = principals.fromRealm(getName());
       //Based on the createPrincipals implementation above, the first one is the Account href:
       return (String) c.iterator().next();
 }

The getName() returns com.stormpath.shiro.realm.ApplicationRealm_0 and then in principals.fromRealm it does:

public Collection fromRealm(String realmName) {
    if (realmPrincipals == null || realmPrincipals.isEmpty()) {
        return Collections.EMPTY_SET;
    }
    Set principals = realmPrincipals.get(realmName);
    if (principals == null || principals.isEmpty()) {
        principals = Collections.EMPTY_SET;
    }
    return Collections.unmodifiableSet(principals);
}

Where the realmPrincipals is a map with one entry: vertx-auth-shiro

So it seems stormpath is looking up by principal using it's name, but somehow only vertx-auth-shiro has been registered.

New key for playing around if you didn't sign up yourself:

apiKey.id = 1Z1YUWJA1YVHAICAOIU8P96VW
apiKey.secret = Bb9pCd07rzCOlQ7uLr1ZZF2Q/zKQi8dfGHerMJ8fBE8

JWT algorithm typo?

java.lang.RuntimeException: Algorithm not supported
at io.vertx.ext.auth.jwt.impl.JWT.sign(JWT.java:180)
at io.vertx.ext.auth.jwt.impl.JWTAuthProviderImpl.generateToken(JWTAuthProviderImpl.java:145)
at io.vertx.groovy.ext.auth.jwt.JWTAuth.generateToken(JWTAuth.groovy:55)
at io.vertx.groovy.ext.auth.jwt.JWTAuth$generateToken$0.call(Unknown Source)

https://github.com/vert-x3/vertx-auth/blob/master/vertx-auth-jwt/src/main/java/io/vertx/ext/auth/jwt/impl/JWT.java

public String sign(JsonObject payload, JsonObject options) {
final String algorithm = options.getString("algorithm", "HS256"); <<-- Supposed to be RS256?

generateToken with a none algorithm fails to generate a third segment

Version

  • vert.x core: 3.3.3
  • vert.x auth: 3.3.3

Context

Generate a token as such:

val payload = JsonObject()
        .put("sub", "UserUnderTest")
        .put("aud", "OrganizationUnderTest")
        .put("iat", 1431695313)
        .put("exp", 1747055313)
        .put("roles", JsonArray(listOf("admin", "developer", "user")))
        .put("permissions", JsonArray(listOf("read", "write", "execute")))

return authProvider.generateToken(payload, JWTOptions().setSubject("UserUnderTest").setAlgorithm("none"))

The output token is:

eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0=.eyJzdWIiOiJVc2VyVW5kZXJUZXN0IiwiYXVkIjpbIk9yZ2FuaXphdGlvblVuZGVyVGVzdCJdLCJleHAiOjE3NDcwNTUzMTMsImlhdCI6MTQzMTY5NTMxMywicGVybWlzc2lvbnMiOlsicmVhZCIsIndyaXRlIiwiZXhlY3V0ZSJdLCJyb2xlcyI6WyJhZG1pbiIsImRldmVsb3BlciIsInVzZXIiXX0=.

Do you have a reproducer?

This fails during JWT decode because of this code (there are only two generated segments)

    String[] segments = token.split("\\.");
    if (segments.length != 3) {
      throw new RuntimeException("Not enough or too many segments");
    }

Allow using Google JWT directly (by implementing server-to-server communication)

Google allows applications to communicate securely using just JWTs over its OAuth2 interface. This is also known as server to server communication and avoids the OAuth2 redirect flow.

We could already do this with the current JWT module but we could add an helper to simplify its usage.

This mode of communication is very useful for consuming APIs from google for example consuming good drive files.

ShiroAuthService seems to autologout after 5 seconds.

This is mostly a query to see if I have misunderstood the behaviour, but it seems that refreshLoginSession must be called immediately after a login, otherwise the session is timeout'd the first time the reaper is run.

Is it also intended that refreshLoginSession should be called manually to keep the login session alive? I would have guessed that calls to hasPermission() and hasRole() would keep the login session alive as well.

Looks like vertx-auth might also be vulnerable to this attack

Version

  • vert.x core: 3.3.2
  • vert.x auth: 3.3.2

Context

https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/

Looks like JWT.java purely relies on what is in the token to specify the alogirithm. This could allow the attacker to attack a vertx server using asym algorithms by signing a token with the known public key, but setting the algorithm to HS256. Vertx would then verify the token purely using the public key instead of the private one.

public JWTAuthProviderImpl(Vertx vertx, JsonObject config) {

config should be expanded to support a "algorithm" parameter, and this should be passed down into JWT when it verifies the token.

Workaround

Do not use asymmetric algorithms for your tokens. Use symmetric algos with a private signing key.

Decoding UNSECURE token fails, as none of the algorithms match JWT Header

Version

  • vert.x core: 3.3.3
  • vert.x auth: 3.3.3

Context

Decoding token with JWT created with no Keystore fails. This is because unsecured is set to true and cryptoMap is empty.

I'm not sure if it is a bug or a concision design decisions.

Not validating a signature in production is another problem in itself, I do realize that, however, I'm using JWT class directly as I have a very specific needs for AuthProvider and AuthHandler.

I stumbled across this issue unit testing my AuthProvider.
The interesting line is https://github.com/vert-x3/vertx-auth/blob/master/vertx-auth-jwt/src/main/java/io/vertx/ext/auth/jwt/impl/JWT.java#L187

Perhaps it should read:

if (!unsecure && crypto == null) { throw new RuntimeException("Algorithm not supported"); }

Also, the entire signature validation block would have to be skipped.
Any thoughts ?

Signature validation for Eliptic Curve is not working

token eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJzdWIiOiJwYXVsbyIsImlhdCI6MTQ0Mjk5ODIxNX0=.MEQCICUVOYsAvKSng-4SDaZBdcYTKLHtxZqHcl4wqvZcdseoAiBj7kGiOhyYES1wdpg0FashauDgue86oWmyQVYc7t7NEQ==
java.lang.RuntimeException: java.security.SignatureException: object not initialized for verification
at io.vertx.ext.auth.jwt.impl.CryptoSignature.verify(Crypto.java:85)
at io.vertx.ext.auth.jwt.impl.JWT.decode(JWT.java:158)
at io.vertx.ext.auth.jwt.impl.JWTAuthProviderImpl.authenticate(JWTAuthProviderImpl.java:78)
at id.netzme.skyfeed.ConfigurationTest.testJWT(ConfigurationTest.java:60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
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.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
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

Exceptions thrown due to lack of SecurityManager

The following exception is thrown when logging in to the example app at https://github.com/vert-x3/vertx-examples/blob/master/web-examples/src/main/java/io/vertx/example/web/auth/Server.java

Currently the exception is swallowed as the DefaultSubjectContext that should log the error receives a NOPLogger, not sure why, may be due to Shiro using slf4j and the app being configured for JUL. Certainly in my project in which I have logback configured I see these exceptions, and in the demo app if you breakpoint inside DefaultSubjectContext.resolveSecurityManager you can see the exception get thrown.

org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton.  This is an invalid application configuration.
        at org.apache.shiro.SecurityUtils.getSecurityManager(SecurityUtils.java:123)
        at org.apache.shiro.subject.support.DefaultSubjectContext.resolveSecurityManager(DefaultSubjectContext.java:106)
        at org.apache.shiro.mgt.DefaultSecurityManager.ensureSecurityManager(DefaultSecurityManager.java:411)
        at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:333)
        at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:183)
        at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:283)
        at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)
        at io.vertx.ext.auth.shiro.impl.ShiroAuthProviderImpl.lambda$authenticate$3(ShiroAuthProviderImpl.java:79)
        at io.vertx.ext.auth.shiro.impl.ShiroAuthProviderImpl$$Lambda$31/2109966893.handle(Unknown Source)
        at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$14(ContextImpl.java:279)
        at io.vertx.core.impl.ContextImpl$$Lambda$32/1669819723.run(Unknown Source)
        at io.vertx.core.impl.OrderedExecutorFactory$OrderedExecutor.lambda$new$161(OrderedExecutorFactory.java:91)
        at io.vertx.core.impl.OrderedExecutorFactory$OrderedExecutor$$Lambda$3/1309238149.run(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

race condition while reading keystore file from vertx cache

  • vert.x auth: 3.3.1-RC2 and earlier

i copy description from [forum thread re this issue ] :(https://groups.google.com/forum/#!topic/vertx/Jqk6R2buSDY)

we have a verticle that creates vertx-web routes and then starts an http server. on some routes we add a JWTAuthHandler to provide jwt based security.
the keystore,jceks file used for that matter is in the classpath.
all worked fine while we had 2 verticle instances, but once we increased the number of instances our verticle started to randomly (but frequently :) ) crash during deployment:
the two exceptions we've seen as the reason for crash are:

java.lang.RuntimeException:
java.io.FileNotFoundException: .vertx\file-cache-812c2a19-b5b6-4339-8a80-fabdfa90cb4e\jwt-keystore.jceks (The process cannot access the file because it is being used by another process)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.(FileInputStream.java:138)
at io.vertx.ext.auth.jwt.impl.JWTAuthProviderImpl.(JWTAuthProviderImpl.java:61)
at io.vertx.ext.auth.jwt.JWTAuth.create(JWTAuth.java:41)
at com.zzz.rest.verticles.RestServerVerticle.addJwtSecurity(RestServerVerticle.java:144)
at com.zzz.rest.verticles.RestServerVerticle.start(RestServerVerticle.java:78)
at io.vertx.core.impl.DeploymentManager.lambda$doDeploy$8(DeploymentManager.java:434)
at io.vertx.core.impl.ContextImpl.lambda$wrapTask$3(ContextImpl.java:359)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:339)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:393)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:742)
at java.lang.Thread.run(Thread.java:745)

and

java.io.EOFException
at java.io.DataInputStream.readInt(DataInputStream.java:392)
at com.sun.crypto.provider.JceKeyStore.engineLoad(JceKeyStore.java:698)
at java.security.KeyStore.load(KeyStore.java:1445)
at io.vertx.ext.auth.jwt.impl.JWTAuthProviderImpl.(JWTAuthProviderImpl.java:62)
at io.vertx.ext.auth.jwt.JWTAuth.create(JWTAuth.java:41)
at com.zzz.rest.verticles.RestServerVerticle.addJwtSecurity(RestServerVerticle.java:144)
at com.zzz.rest.verticles.RestServerVerticle.start(RestServerVerticle.java:78)
at io.vertx.core.impl.DeploymentManager.lambda$doDeploy$8( .java:434)
at io.vertx.core.impl.ContextImpl.lambda$wrapTask$3(ContextImpl.java:359)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:339)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:393)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:742)
at java.lang.Thread.run(Thread.java:745)

as you can see, in both cases the problem occurs while JWTAuth tries to load a keystore file from vertx cache. the exception is thrown from the following code in JWTAuthProviderImpl:

try (InputStream in = new FileInputStream(vertxInternal.resolveFile(keyStore.getString("path"))))

it seems the reading from the fileinputstream should be synchronized to prevent this from happen.

JWT Signature verification failed with multithread

sometimes JWT.decode will throw the RuntimeException("Signature verification failed") when we use blockingHandler or generateToken/authenticate in different thread.

I think it's because CryptoMac use mac.doFinal to generate digests and it's not thread-safe.

OAuth getToken don't response when java.net.UnknownHostException is thrown

Version

  • vert.x core:3.3.2
  • vert.x auth:3.3.2

Context

OAuth getToken can't set exceptionHandler to HttpClientRequest and don't call callback method when exception is thrown in HttpClientRequest.
When java.net.UnknownHostException was thrown (Google's OAuth API Server downed), my app couldn't response anything to browser.

OAuth2API can't handle plain text responses

Version

  • vert.x core: 3.2.1
  • vert.x auth: 3.2.1

Context

I was trying to get an access token from facebook and noticed it returns text/plain which OAuth2API cannot handle. The error thrown is:

Access Token Error: Cannot handle content type: text/plain

Steps to reproduce

Try to use the configuration described here to get an access token from facebook:
http://vertx.io/docs/vertx-auth-oauth2/java/

Extra

Here's someone else that ran into this:
http://stackoverflow.com/questions/35245955/vert-x-oauth2-facebook-api-call-to-get-access-token-fails-because-of-text-plain

Control of configuration for the underlying HttpClient

Hi
On line
https://github.com/vert-x3/vertx-auth/blob/master/vertx-auth-oauth2/src/main/java/io/vertx/ext/auth/oauth2/impl/OAuth2API.java#L114

client = provider.getVertx().createHttpClient(new HttpClientOptions() .setSsl(isSecure) .setDefaultHost(host) .setDefaultPort(port));

new client is created for the request. It would be nice to be able to control the client configuration from the overall OAuth2ClientOptions.

For example:

client = provider.getVertx().createHttpClient(config);

Wasn't that the intention #56 and #57 ?

At the moment I can't ignore SSL errors in my test environment or add keystore for the client.

Greg

JWT authenticate security issue!

Version

all versions

  • vert.x auth jwt:

Context

In io.vertx.ext.auth.jwt.impl.JWT#decode you get the algorithm to use form the JWT header segment. But this let an attacker select the algorithm that is used to check the token. Just change the JWT header “alg” to “none” and you have a valid token!

Do you have a reproducer?

add to io.vertx.ext.auth.test.jwt.JWTAuthProviderTest

  @Test
  public void testAcceptInvalidJWT() {
    String[] segments = JWT_INVALID.split("\\.");
    // All segment should be base64
    String headerSeg = segments[0];

    // change alg to none
    JsonObject headerJson = new JsonObject(new String(Base64.getUrlDecoder().decode(headerSeg.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));
    headerJson.put("alg", "none");
    headerSeg = Base64.getUrlEncoder().encodeToString(headerJson.encode().getBytes(StandardCharsets.UTF_8));

    // fix time exp
    String payloadSeg = segments[1];
    JsonObject bodyJson = new JsonObject(new String(Base64.getUrlDecoder().decode(payloadSeg.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));
    bodyJson.put("exp", System.currentTimeMillis() + 10000);
    payloadSeg = Base64.getUrlEncoder().encodeToString(headerJson.encode().getBytes(StandardCharsets.UTF_8));

    String signatureSeg = segments[2];

    // build attack token
    String attackerJWT = headerSeg+"."+payloadSeg+"."+signatureSeg;
    JsonObject authInfo = new JsonObject().put("jwt", attackerJWT);
    authProvider.authenticate(authInfo, onFailure(thr -> {
      assertNotNull(thr);
      testComplete();
    }));
    await();
  }

Shiro - remember me flag

Version

  • vert.x core: 3.3.0
  • vert.x auth: 3.3.0

Context

I am using shiro for authentication, I have noticed that in ShiroAuthProviderImpl.java the properties "username" and "password" are used to create an UsernamePasswordToken object but not the remember me flag (that is supported by UsernamePasswordToken):

  @Override
  public void authenticate(JsonObject authInfo, Handler<AsyncResult<User>> resultHandler) {
    vertx.executeBlocking(fut -> {
      SubjectContext subjectContext = new DefaultSubjectContext();
      Subject subject = securityManager.createSubject(subjectContext);
      String username = authInfo.getString("username");
      String password = authInfo.getString("password"); 
      AuthenticationToken token = new UsernamePasswordToken(username, password);
      try {
        subject.login(token);
      } catch (AuthenticationException e) {
        throw new VertxException(e);
      }
      fut.complete(new ShiroUser(vertx, securityManager, subject, rolePrefix));
    }, resultHandler);
  }

Do you think that modifying the code above in something like the following will magically enable the remember me feature ?

@Override
public void authenticate(JsonObject authInfo, Handler<AsyncResult<User>> resultHandler) {
  vertx.executeBlocking(fut -> {
  SubjectContext subjectContext = new DefaultSubjectContext();
  Subject subject = securityManager.createSubject(subjectContext);
  String username = authInfo.getString("username");
  String password = authInfo.getString("password"); 
  Boolean rememberMe = Boolean.parseBoolean(authInfo.getString("rememberme"));  <-- HERE
  AuthenticationToken token = new UsernamePasswordToken(username, password, rememberMe); <-- HERE
  try {
    subject.login(token);
  } catch (AuthenticationException e) {
    throw new VertxException(e);
  }
  fut.complete(new ShiroUser(vertx, securityManager, subject, rolePrefix));
  }, resultHandler);
}

I am fairly new to Shiro and Vert.x, so I am not sure if this will be enough and maybe you already have experience with this issue.

thanks ;)

Vertx Shiro's BasicAuthentication fail when login with browser

Version

  • vert.x core: 3.3.0
  • vert.x auth: 3.3.0

Context

I written some code to perform Basic Authentication with Vertx ShiroAuth.

    JsonObject authConfigObject = new JsonObject();
        authConfigObject.put(
                PropertiesProviderConstants.PROPERTIES_PROPS_PATH_FIELD,
                new File(appConfig.getUserPropertiesPath()).toURI().toString() /*to let shiro auto reload properties file */
        );

        ShiroAuthOptions shiroAuthOptions = new ShiroAuthOptions();
        shiroAuthOptions.setType(ShiroAuthRealmType.PROPERTIES);
        shiroAuthOptions.setConfig(authConfigObject);

Example properties file:

user.admin=12345678
user.staff=123

When user login with browser, vertx throw a null Throwable (stacktrace), hence we must add this stupid if block to handle it:

    public void handleFailure(RoutingContext context) {
        if (context.failure() == null || context.failure() instanceof FileNotFoundException) {
            context.next();
            return;
        }
   //handle another failure....

I feel that add that if block is a trick :(

Groovy can not find method ShiroAuth.create(vertx, realm)

At the last of the documents (http://vert-x3.github.io/docs/vertx-auth-shiro/groovy/), I see I can use other Realm
class MyRealm extends AuthorizingRealm {
// other codes.
}
import io.vertx.groovy.ext.auth.shiro.ShiroAuth;
def realm = new MyRealm();
def provider = ShiroAuth.create(vertx, realm);

But When I create an Realm, I see there is no method ShiroAuth.create(vertx, realm);
groovy.lang.MissingMethodException: No signature of method: static io.vertx.groovy.ext.auth.shiro.ShiroAuth.create() is applicable for argument types: (io.vertx.groovy.core.Vertx, MyRealm)

simple oauth2 server side support

For 3.2 we would like to have some simple oauth2 support, the MVP is to support authentication using a third party such as Github/Facebook/Google

Shiro's BasicAuthentication doesn't detect deleted key-value on reload

Version

  • vert.x core: 3.3.0
  • vert.x auth: 3.3.0

Context

I written some code to perform Basic Authentication with Vertx ShiroAuth.

        JsonObject authConfigObject = new JsonObject();
        authConfigObject.put(
                PropertiesProviderConstants.PROPERTIES_PROPS_PATH_FIELD,
                new File(appConfig.getUserPropertiesPath()).toURI().toString() /*to let shiro auto reload properties file */
        );

        ShiroAuthOptions shiroAuthOptions = new ShiroAuthOptions();
        shiroAuthOptions.setType(ShiroAuthRealmType.PROPERTIES);
        shiroAuthOptions.setConfig(authConfigObject);

Example properties file:

user.admin=12345678
user.staff=123

If I add new key-value to properties file, Shiro can detect and reload perfectly. But when I delete, shiro reload (the debug log said that) but nothing change (user can still login by using those deleted key-value).

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.