roleallowed support
diff --git a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/cdi/GeronimoJwtAuthExtension.java b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/cdi/GeronimoJwtAuthExtension.java
index 2f54ecb..17c1c31 100644
--- a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/cdi/GeronimoJwtAuthExtension.java
+++ b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/cdi/GeronimoJwtAuthExtension.java
@@ -62,6 +62,7 @@
 import javax.json.spi.JsonProvider;
 import javax.servlet.ServletException;
 
+import org.apache.geronimo.microprofile.impl.jwtauth.config.GeronimoJwtAuthConfig;
 import org.apache.geronimo.microprofile.impl.jwtauth.servlet.JwtRequest;
 import org.eclipse.microprofile.jwt.Claim;
 import org.eclipse.microprofile.jwt.ClaimValue;
@@ -89,6 +90,15 @@
     }
 
     void addClaimBeans(@Observes final AfterBeanDiscovery afterBeanDiscovery) {
+        // it is another instance than th eone used in our initializer but it should be backed by the same impl
+        afterBeanDiscovery.addBean()
+                .id(GeronimoJwtAuthExtension.class.getName() + "#" + GeronimoJwtAuthConfig.class.getName())
+                .beanClass(GeronimoJwtAuthConfig.class)
+                .types(GeronimoJwtAuthConfig.class, Object.class)
+                .qualifiers(Default.Literal.INSTANCE, Any.Literal.INSTANCE)
+                .scope(ApplicationScoped.class)
+                .createWith(ctx -> GeronimoJwtAuthConfig.create());
+
         afterBeanDiscovery.addBean()
                 .id(GeronimoJwtAuthExtension.class.getName() + "#" + JsonWebToken.class.getName())
                 .beanClass(JsonWebToken.class)
diff --git a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/config/DefaultJwtAuthConfig.java b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/config/DefaultJwtAuthConfig.java
new file mode 100644
index 0000000..d338e2a
--- /dev/null
+++ b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/config/DefaultJwtAuthConfig.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.microprofile.impl.jwtauth.config;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.enterprise.inject.Vetoed;
+
+@Vetoed
+class DefaultJwtAuthConfig implements GeronimoJwtAuthConfig {
+    private final Map<String, String> configuration = new HashMap<>();
+
+    DefaultJwtAuthConfig() {
+        System.getProperties().stringPropertyNames()
+                .forEach(k -> configuration.put(k, System.getProperty(k)));
+        try (final InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("META-INF/geronimo/microprofile/jwt-auth.properties")) {
+            if (stream != null) {
+                final Properties properties = new Properties();
+                properties.load(stream);
+                properties.stringPropertyNames().forEach(k -> configuration.put(k, properties.getProperty(k)));
+            }
+        } catch (final IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Override
+    public String read(final String value, final String def) {
+        return configuration.getOrDefault(value, def);
+    }
+}
diff --git a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/config/GeronimoJwtAuthConfig.java b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/config/GeronimoJwtAuthConfig.java
index 2a79393..6b5791e 100644
--- a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/config/GeronimoJwtAuthConfig.java
+++ b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/config/GeronimoJwtAuthConfig.java
@@ -24,7 +24,7 @@
         try {
             return new JwtAuthConfigMpConfigImpl();
         } catch (final NoClassDefFoundError | ExceptionInInitializerError cnfe) {
-            return System::getProperty;
+            return new DefaultJwtAuthConfig();
         }
     }
 }
diff --git a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/config/JwtAuthConfigMpConfigImpl.java b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/config/JwtAuthConfigMpConfigImpl.java
index 6566277..20d9840 100644
--- a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/config/JwtAuthConfigMpConfigImpl.java
+++ b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/config/JwtAuthConfigMpConfigImpl.java
@@ -16,13 +16,16 @@
  */
 package org.apache.geronimo.microprofile.impl.jwtauth.config;
 
+import javax.enterprise.inject.Vetoed;
+
 import org.eclipse.microprofile.config.Config;
 import org.eclipse.microprofile.config.ConfigProvider;
 
-public class JwtAuthConfigMpConfigImpl implements GeronimoJwtAuthConfig {
+@Vetoed
+class JwtAuthConfigMpConfigImpl implements GeronimoJwtAuthConfig {
     private final Config config;
 
-    public JwtAuthConfigMpConfigImpl() {
+    JwtAuthConfigMpConfigImpl() {
         config = ConfigProvider.getConfig();
     }
 
diff --git a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jaxrs/GeronimoJwtAuthExceptionMapper.java b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jaxrs/GeronimoJwtAuthExceptionMapper.java
new file mode 100644
index 0000000..ba77f8a
--- /dev/null
+++ b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jaxrs/GeronimoJwtAuthExceptionMapper.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.microprofile.impl.jwtauth.jaxrs;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;
+
+import javax.enterprise.context.Dependent;
+import javax.inject.Inject;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.geronimo.microprofile.impl.jwtauth.JwtException;
+
+@Provider
+@Dependent
+public class GeronimoJwtAuthExceptionMapper implements ExceptionMapper<JwtException> {
+    @Inject
+    private ResponseBuilder builder;
+
+    @Override
+    public Response toResponse(final JwtException e) {
+        return Response.status(e.getStatus())
+                .entity(builder.toObject(e))
+                .type(APPLICATION_JSON_TYPE)
+                .build();
+    }
+}
diff --git a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jaxrs/GroupMapper.java b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jaxrs/GroupMapper.java
new file mode 100644
index 0000000..a04792f
--- /dev/null
+++ b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jaxrs/GroupMapper.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.microprofile.impl.jwtauth.jaxrs;
+
+import static java.util.Collections.singletonList;
+import static java.util.Optional.ofNullable;
+import static java.util.stream.Collectors.toSet;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.stream.Stream;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import org.apache.geronimo.microprofile.impl.jwtauth.config.GeronimoJwtAuthConfig;
+
+@ApplicationScoped
+class GroupMapper {
+    @Inject
+    private GeronimoJwtAuthConfig config;
+
+    private final Map<String, Collection<String>> mapping = new HashMap<>();
+
+    @PostConstruct
+    private void init() {
+        ofNullable(config.read("geronimo.jwt-auth.groups.mapping", null))
+                .map(String::trim)
+                .filter(s -> !s.isEmpty())
+                .map(s -> {
+                    final Properties properties = new Properties();
+                    try (final Reader reader = new StringReader(s)) {
+                        properties.load(reader);
+                    } catch (final IOException e) {
+                        throw new IllegalArgumentException(e);
+                    }
+                    return properties;
+                })
+                .ifPresent(props -> props.stringPropertyNames()
+                        .forEach(k -> mapping.put(k, Stream.of(props.getProperty(k).split(","))
+                                .map(String::trim)
+                                .collect(toSet()))));
+
+    }
+
+    Collection<String> map(final String tokenName) {
+        return ofNullable(mapping.get(tokenName)).orElse(singletonList(tokenName));
+    }
+}
diff --git a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jaxrs/ResponseBuilder.java b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jaxrs/ResponseBuilder.java
new file mode 100644
index 0000000..e61b341
--- /dev/null
+++ b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jaxrs/ResponseBuilder.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.microprofile.impl.jwtauth.jaxrs;
+
+import static java.util.Collections.emptyMap;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.json.Json;
+import javax.json.JsonBuilderFactory;
+import javax.json.JsonObject;
+
+import org.apache.geronimo.microprofile.impl.jwtauth.JwtException;
+
+@ApplicationScoped
+public class ResponseBuilder {
+    private JsonBuilderFactory factory;
+
+    @PostConstruct
+    private void createBuilderFactory() {
+        factory = Json.createBuilderFactory(emptyMap());
+    }
+
+    public JsonObject toObject(final JwtException exception) {
+        return factory.createObjectBuilder()
+                .add("message", exception.getMessage())
+                .build();
+    }
+}
diff --git a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jaxrs/RolesAllowedFeature.java b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jaxrs/RolesAllowedFeature.java
new file mode 100644
index 0000000..a52c471
--- /dev/null
+++ b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jaxrs/RolesAllowedFeature.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.microprofile.impl.jwtauth.jaxrs;
+
+import static java.util.Collections.emptyList;
+import static java.util.Optional.ofNullable;
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.toMap;
+import static java.util.stream.Collectors.toSet;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.util.Collection;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import javax.annotation.security.DenyAll;
+import javax.annotation.security.PermitAll;
+import javax.annotation.security.RolesAllowed;
+import javax.enterprise.context.Dependent;
+import javax.inject.Inject;
+import javax.ws.rs.container.DynamicFeature;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.ext.Provider;
+
+// not done at cdi level since a lot of apps already activate it
+// so we would break apps too easily
+// todo: probably make it configurable
+@Provider
+@Dependent
+public class RolesAllowedFeature implements DynamicFeature {
+    @Inject
+    private GroupMapper mapper;
+
+    @Override
+    public void configure(final ResourceInfo resourceInfo, final FeatureContext featureContext) {
+        final Map<Class<?>, Annotation> methodAnnotations = collectConfig(resourceInfo.getResourceMethod());
+        if (methodAnnotations.size() > 1) {
+            throw new IllegalArgumentException("Ambiguous configuration for " + resourceInfo.getResourceMethod() + ": " + methodAnnotations);
+        }
+
+        final Map<Class<?>, Annotation> classAnnotations = collectConfig(unwrapClazz(resourceInfo.getResourceClass()));
+        if (classAnnotations.size() > 1) {
+            throw new IllegalArgumentException("Ambiguous configuration for " + resourceInfo.getResourceClass() + ": " + classAnnotations);
+        }
+
+        if (classAnnotations.isEmpty() && methodAnnotations.isEmpty()) {
+            return;
+        }
+
+        final boolean denyAll = methodAnnotations.containsKey(DenyAll.class) || (methodAnnotations.isEmpty() && classAnnotations.containsKey(DenyAll.class));
+        final boolean permitAll = !denyAll && (methodAnnotations.containsKey(PermitAll.class) || (methodAnnotations.isEmpty() && classAnnotations.containsKey(PermitAll.class)));
+        final Collection<String> roles = denyAll || permitAll ?
+                emptyList() :
+                Stream.of(RolesAllowed.class.cast(ofNullable(methodAnnotations.get(RolesAllowed.class)).orElseGet(() -> classAnnotations.get(RolesAllowed.class))).value())
+                        .flatMap(it -> mapper.map(it).stream())
+                        .collect(toSet());
+        featureContext.register(new RolesAllowedRequestFilter(denyAll, permitAll, roles));
+    }
+
+    private Map<Class<?>, Annotation> collectConfig(final AnnotatedElement annotatedElement) {
+        return Stream.of(DenyAll.class, PermitAll.class, RolesAllowed.class)
+                .filter(annotatedElement::isAnnotationPresent)
+                .map(annotatedElement::getAnnotation)
+                .collect(toMap(Annotation::annotationType, identity()));
+    }
+
+    private AnnotatedElement unwrapClazz(final Class<?> resourceClass) {
+        Class<?> current = resourceClass;
+        while (current.getName().contains("$$") && current.getSuperclass() != null) {
+            current = current.getSuperclass();
+        }
+        return current;
+    }
+}
diff --git a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jaxrs/RolesAllowedRequestFilter.java b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jaxrs/RolesAllowedRequestFilter.java
new file mode 100644
index 0000000..db181d8
--- /dev/null
+++ b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jaxrs/RolesAllowedRequestFilter.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.microprofile.impl.jwtauth.jaxrs;
+
+import static java.util.Collections.emptyMap;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import javax.json.Json;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+
+class RolesAllowedRequestFilter implements ContainerRequestFilter {
+    private final Response forbidden = Response
+            .status(Response.Status.FORBIDDEN)
+            .entity(Json.createObjectBuilder(emptyMap()).add("message", "you are not allowed to access that endpoint").build())
+            .build();
+
+    private final boolean denyAll;
+    private final boolean permitAll;
+    private final Collection<String> roles;
+
+    RolesAllowedRequestFilter(final boolean denyAll, final boolean permitAll, final Collection<String> roles) {
+        this.denyAll = denyAll;
+        this.permitAll = permitAll;
+        this.roles = roles;
+    }
+
+    @Override
+    public void filter(final ContainerRequestContext context) throws IOException {
+        if (denyAll) {
+            context.abortWith(forbidden);
+        } else if (!permitAll) {
+            final SecurityContext securityContext = context.getSecurityContext();
+            if (securityContext == null || roles.stream().noneMatch(securityContext::isUserInRole)) {
+                context.abortWith(forbidden);
+            }
+        }
+    }
+}
diff --git a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jwt/JwtService.java b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jwt/JwtParser.java
similarity index 82%
rename from geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jwt/JwtService.java
rename to geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jwt/JwtParser.java
index c0fc52b..8cf5473 100644
--- a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jwt/JwtService.java
+++ b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/jwt/JwtParser.java
@@ -19,6 +19,7 @@
 import static java.util.Collections.emptyMap;
 
 import java.io.ByteArrayInputStream;
+import java.net.HttpURLConnection;
 import java.util.Base64;
 
 import javax.annotation.PostConstruct;
@@ -27,10 +28,12 @@
 import javax.json.JsonObject;
 import javax.json.JsonReaderFactory;
 
+import org.apache.geronimo.microprofile.impl.jwtauth.JwtException;
+import org.eclipse.microprofile.jwt.Claims;
 import org.eclipse.microprofile.jwt.JsonWebToken;
 
 @ApplicationScoped
-public class JwtService {
+public class JwtParser {
     private JsonReaderFactory readerFactory;
 
     @PostConstruct
@@ -48,6 +51,11 @@
 
         final byte[] token = Base64.getUrlDecoder().decode(split[1]);
         final JsonObject json = readerFactory.createReader(new ByteArrayInputStream(token)).readObject();
+        final String issuer = json.getString(Claims.iss.name());
+        if ("INVALID_ISSUER".equals(issuer)) { // todo
+            throw new JwtException("Invalid issuer", HttpURLConnection.HTTP_UNAUTHORIZED);
+        }
+
         return new GeronimoJsonWebToken(jwt, json);
     }
 }
diff --git a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/servlet/GeronimoJwtAuthFilter.java b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/servlet/GeronimoJwtAuthFilter.java
index cb21ab1..b02b407 100644
--- a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/servlet/GeronimoJwtAuthFilter.java
+++ b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/servlet/GeronimoJwtAuthFilter.java
@@ -31,23 +31,24 @@
 import org.apache.geronimo.microprofile.impl.jwtauth.JwtException;
 import org.apache.geronimo.microprofile.impl.jwtauth.cdi.GeronimoJwtAuthExtension;
 import org.apache.geronimo.microprofile.impl.jwtauth.config.GeronimoJwtAuthConfig;
-import org.apache.geronimo.microprofile.impl.jwtauth.jwt.JwtService;
+import org.apache.geronimo.microprofile.impl.jwtauth.jwt.JwtParser;
 
 public class GeronimoJwtAuthFilter implements Filter {
     private String headerName;
     private String prefix;
-    private JwtService service;
+    private JwtParser service;
     private GeronimoJwtAuthExtension extension;
+    private GeronimoJwtAuthConfig config;
 
     @Override
     public void init(final FilterConfig filterConfig) throws ServletException {
-        final GeronimoJwtAuthConfig config = GeronimoJwtAuthConfig.class.cast(filterConfig.getServletContext().getAttribute(GeronimoJwtAuthConfig.class.getName()));
+        final CDI<Object> current = CDI.current();
+        service = current.select(JwtParser.class).get();
+        extension = current.select(GeronimoJwtAuthExtension.class).get();
+        config = current.select(GeronimoJwtAuthConfig.class).get();
+
         headerName = config.read("geronimo.jwt-auth.header.name", "Authorization");
         prefix = config.read("geronimo.jwt-auth.header.prefix", "bearer") + " ";
-
-        final CDI<Object> current = CDI.current();
-        service = current.select(JwtService.class).get();
-        extension = current.select(GeronimoJwtAuthExtension.class).get();
     }
 
     @Override
diff --git a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/servlet/GeronimoJwtAuthInitializer.java b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/servlet/GeronimoJwtAuthInitializer.java
index 6941f78..dc10459 100644
--- a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/servlet/GeronimoJwtAuthInitializer.java
+++ b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/servlet/GeronimoJwtAuthInitializer.java
@@ -38,7 +38,6 @@
     @Override
     public void onStartup(final Set<Class<?>> classes, final ServletContext ctx) throws ServletException {
         final GeronimoJwtAuthConfig appConfig = GeronimoJwtAuthConfig.create();
-        ctx.setAttribute(GeronimoJwtAuthConfig.class.getName(), appConfig);
 
         ofNullable(classes).filter(c -> !c.isEmpty()).ifPresent(marked -> marked.stream()
                 .filter(Application.class::isAssignableFrom) // needed?
diff --git a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/servlet/JwtRequest.java b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/servlet/JwtRequest.java
index 53c7c07..7be1730 100644
--- a/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/servlet/JwtRequest.java
+++ b/geronimo-jwt-auth-impl/src/main/java/org/apache/geronimo/microprofile/impl/jwtauth/servlet/JwtRequest.java
@@ -32,7 +32,7 @@
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.geronimo.microprofile.impl.jwtauth.JwtException;
-import org.apache.geronimo.microprofile.impl.jwtauth.jwt.JwtService;
+import org.apache.geronimo.microprofile.impl.jwtauth.jwt.JwtParser;
 import org.eclipse.microprofile.jwt.JsonWebToken;
 
 public class JwtRequest extends HttpServletRequestWrapper {
@@ -40,7 +40,7 @@
     private final Supplier<JsonWebToken> tokenExtractor;
     private volatile JsonWebToken token; // cache for perf reasons
 
-    JwtRequest(final JwtService service, final String header, final String prefix, final HttpServletRequest request) {
+    JwtRequest(final JwtParser service, final String header, final String prefix, final HttpServletRequest request) {
         super(request);
         this.delegate = request;
 
diff --git a/geronimo-jwt-auth-impl/src/test/resources/META-INF/geronimo/microprofile/jwt-auth.properties b/geronimo-jwt-auth-impl/src/test/resources/META-INF/geronimo/microprofile/jwt-auth.properties
new file mode 100644
index 0000000..6e1a021
--- /dev/null
+++ b/geronimo-jwt-auth-impl/src/test/resources/META-INF/geronimo/microprofile/jwt-auth.properties
@@ -0,0 +1,18 @@
+#Licensed to the Apache Software Foundation (ASF) under one
+#or more contributor license agreements.  See the NOTICE file
+#distributed with this work for additional information
+#regarding copyright ownership.  The ASF licenses this file
+#to you under the Apache License, Version 2.0 (the
+#"License"); you may not use this file except in compliance
+#with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+#Unless required by applicable law or agreed to in writing,
+#software distributed under the License is distributed on an
+#"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#KIND, either express or implied.  See the License for the
+#specific language governing permissions and limitations
+#under the License.
+geronimo.jwt-auth.groups.mapping = \
+Group1MappedRole = group1, Group1MappedRole
diff --git a/geronimo-jwt-auth-impl/src/test/resources/dev.xml b/geronimo-jwt-auth-impl/src/test/resources/dev.xml
index 015bf04..d5817f9 100644
--- a/geronimo-jwt-auth-impl/src/test/resources/dev.xml
+++ b/geronimo-jwt-auth-impl/src/test/resources/dev.xml
@@ -14,8 +14,7 @@
 <suite name="Microprofile-jwt-auth-TCK (dev)" verbose="1" configfailurepolicy="continue" >
   <test name="Tests">
     <classes>
-      <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.RequiredClaimsTest">
-      </class>
+      <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.InvalidTokenTest" />
     </classes>
   </test>
 </suite>