Skip to content

Commit

Permalink
Make JwtParser and JwtRolesMapper injectable
Browse files Browse the repository at this point in the history
  • Loading branch information
andreas-eberle committed Feb 28, 2020
1 parent d2fea75 commit db2501d
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.security.deployment.JCAProviderBuildItem;
import io.quarkus.smallrye.jwt.runtime.auth.DefaultJwtParser;
import io.quarkus.smallrye.jwt.runtime.auth.DefaultJwtRolesMapper;
import io.quarkus.smallrye.jwt.runtime.auth.JWTAuthMechanism;
import io.quarkus.smallrye.jwt.runtime.auth.JwtPrincipalProducer;
import io.quarkus.smallrye.jwt.runtime.auth.JwtTokenUtils;
import io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator;
import io.quarkus.smallrye.jwt.runtime.auth.RawOptionalClaimCreator;
import io.smallrye.jwt.algorithm.SignatureAlgorithm;
Expand Down Expand Up @@ -79,6 +82,9 @@ void registerAdditionalBeans(BuildProducer<AdditionalBeanBuildItem> additionalBe
removable.addBeanClass(RawClaimTypeProducer.class);
removable.addBeanClass(JsonValueProducer.class);
removable.addBeanClass(JwtPrincipalProducer.class);
removable.addBeanClass(JwtTokenUtils.class);
removable.addBeanClass(DefaultJwtParser.class);
removable.addBeanClass(DefaultJwtRolesMapper.class);
removable.addBeanClass(Claim.class);
additionalBeans.produce(removable.build());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
import io.quarkus.security.identity.request.TokenAuthenticationRequest;
import io.quarkus.security.runtime.AnonymousIdentityProvider;
import io.quarkus.security.runtime.QuarkusIdentityProviderManagerImpl;
import io.quarkus.smallrye.jwt.runtime.auth.DefaultJwtParser;
import io.quarkus.smallrye.jwt.runtime.auth.DefaultJwtRolesMapper;
import io.quarkus.smallrye.jwt.runtime.auth.JwtParser;
import io.quarkus.smallrye.jwt.runtime.auth.JwtRolesMapper;
import io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator;
import io.smallrye.jwt.auth.principal.JWTAuthContextInfo;

Expand All @@ -30,7 +34,9 @@ public void testAuthenticator() throws Exception {
PublicKey pk1 = keyPair.getPublic();
PrivateKey pk1Priv = keyPair.getPrivate();
JWTAuthContextInfo contextInfo = new JWTAuthContextInfo((RSAPublicKey) pk1, "https://server.example.com");
MpJwtValidator jwtValidator = new MpJwtValidator(contextInfo);
JwtParser jwtParser = new DefaultJwtParser();
JwtRolesMapper jwtRolesMapper = new DefaultJwtRolesMapper();
MpJwtValidator jwtValidator = new MpJwtValidator(contextInfo, jwtParser, jwtRolesMapper);
QuarkusIdentityProviderManagerImpl authenticator = QuarkusIdentityProviderManagerImpl.builder()
.addProvider(new AnonymousIdentityProvider())
.setBlockingExecutor(new Executor() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.quarkus.smallrye.jwt.runtime.auth;

import javax.enterprise.context.ApplicationScoped;

import org.jose4j.jwt.consumer.JwtContext;

import io.quarkus.arc.DefaultBean;
import io.smallrye.jwt.auth.principal.DefaultJWTTokenParser;
import io.smallrye.jwt.auth.principal.JWTAuthContextInfo;
import io.smallrye.jwt.auth.principal.ParseException;

@DefaultBean
@ApplicationScoped
public class DefaultJwtParser implements JwtParser {
private final DefaultJWTTokenParser parser = new DefaultJWTTokenParser();

@Override
public JwtContext parse(String token, JWTAuthContextInfo authContextInfo) throws ParseException {
return parser.parse(token, authContextInfo);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.quarkus.smallrye.jwt.runtime.auth;

import java.util.HashSet;

import javax.enterprise.context.ApplicationScoped;

import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.MalformedClaimException;

import io.quarkus.arc.DefaultBean;

@DefaultBean
@ApplicationScoped
public class DefaultJwtRolesMapper implements JwtRolesMapper {

@Override
public HashSet<String> mapGroupsAndRoles(JwtClaims claims) throws MalformedClaimException {
return new HashSet<>(claims.getStringListClaimValue("groups"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import io.smallrye.jwt.auth.AbstractBearerTokenExtractor;
import io.smallrye.jwt.auth.cdi.PrincipalProducer;
import io.smallrye.jwt.auth.principal.JWTAuthContextInfo;
import io.vertx.ext.web.Cookie;
import io.vertx.core.http.Cookie;
import io.vertx.ext.web.RoutingContext;

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.quarkus.smallrye.jwt.runtime.auth;

import org.jose4j.jwt.consumer.JwtContext;

import io.smallrye.jwt.auth.principal.JWTAuthContextInfo;
import io.smallrye.jwt.auth.principal.ParseException;

public interface JwtParser {
JwtContext parse(String token, JWTAuthContextInfo authContextInfo) throws ParseException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.quarkus.smallrye.jwt.runtime.auth;

import java.util.HashSet;

import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.MalformedClaimException;

public interface JwtRolesMapper {
HashSet<String> mapGroupsAndRoles(JwtClaims claims) throws MalformedClaimException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.quarkus.smallrye.jwt.runtime.auth;

import javax.enterprise.context.ApplicationScoped;

import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;

@ApplicationScoped
public class JwtTokenUtils {
public JwtClaims decodeTokenUnverified(String tokenString) throws InvalidJwtException {
JwtConsumer consumer = new JwtConsumerBuilder()
.setSkipAllValidators()
.setDisableRequireSignature()
.setSkipSignatureVerification()
.build();
return consumer.processToClaims(tokenString);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.quarkus.smallrye.jwt.runtime.auth;

import java.util.HashSet;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

Expand All @@ -18,7 +17,6 @@
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.security.identity.request.TokenAuthenticationRequest;
import io.quarkus.security.runtime.QuarkusSecurityIdentity;
import io.smallrye.jwt.auth.principal.DefaultJWTTokenParser;
import io.smallrye.jwt.auth.principal.JWTAuthContextInfo;
import io.smallrye.jwt.auth.principal.ParseException;

Expand All @@ -31,16 +29,14 @@ public class MpJwtValidator implements IdentityProvider<TokenAuthenticationReque
private static final Logger log = Logger.getLogger(MpJwtValidator.class);

final JWTAuthContextInfo authContextInfo;

private final DefaultJWTTokenParser parser = new DefaultJWTTokenParser();

public MpJwtValidator() {
authContextInfo = null;
}
final JwtParser parser;
final JwtRolesMapper jwtRolesMapper;

@Inject
public MpJwtValidator(JWTAuthContextInfo authContextInfo) {
public MpJwtValidator(JWTAuthContextInfo authContextInfo, JwtParser parser, JwtRolesMapper jwtRolesMapper) {
this.authContextInfo = authContextInfo;
this.parser = parser;
this.jwtRolesMapper = jwtRolesMapper;
}

@Override
Expand All @@ -65,12 +61,12 @@ public CompletionStage<SecurityIdentity> authenticate(TokenAuthenticationRequest
QuarkusJwtCallerPrincipal principal = new QuarkusJwtCallerPrincipal(name, claims);
return CompletableFuture
.completedFuture(QuarkusSecurityIdentity.builder().setPrincipal(principal)
.addRoles(new HashSet<>(claims.getStringListClaimValue("groups")))
.addRoles(jwtRolesMapper.mapGroupsAndRoles(claims))
.addAttribute(SecurityIdentity.USER_ATTRIBUTE, principal).build());

} catch (ParseException | MalformedClaimException e) {
log.debug("Authentication failed", e);
CompletableFuture<SecurityIdentity> cf = new CompletableFuture<SecurityIdentity>();
CompletableFuture<SecurityIdentity> cf = new CompletableFuture<>();
cf.completeExceptionally(new AuthenticationFailedException(e));
return cf;
}
Expand Down

0 comments on commit db2501d

Please sign in to comment.