So either you configured this provider in openejb-jar.xml or
JWTAuthenticationFilter
is not a CDI bean


Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Tomitriber
<http://www.tomitribe.com>

2015-04-09 15:55 GMT+02:00 Alex Soto <[email protected]>:

> mm strange look:
>
> @ApplicationScoped
> public class UserService {
> }
>
> @Provider
> @Priority(Priorities.AUTHENTICATION)
> public class JWTAuthenticationFilter implements ContainerRequestFilter {
>
>     private static final List<Class<? extends Annotation>>
> securityAnnotations =
>         Arrays.asList(DenyAll.class, PermitAll.class, RolesAllowed.class);
>
>     @Context
>     ResourceInfo resourceInfo;
>
>     @Context
>     HttpServletRequest servletRequest;
>
>     @Context
>     UriInfo uriInfo;
>
>     @Inject
>     UserService userservice;
>
>     @Override
>     public void filter(ContainerRequestContext request) throws IOException
> {
> }
>
> and userService is null.
>
> El dj., 9 abr., 2015 a les 15:53, Alex Soto (<[email protected]>) va
> escriure:
>
> > I am going to take another look to the code to see what's happening :S
> >
> > El dj., 9 abr., 2015 a les 15:47, Romain Manni-Bucau (<
> > [email protected]>) va escriure:
> >
> > cdi works:
> >> https://git-wip-us.apache.org/repos/asf?p=tomee.git;a=blob;f
> >> =server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/
> >> CDIProviderContainerRequestFilterTest.java;h=6c180
> >> 2c9e2e825172f550d7793450a81899cfa46;hb=d08f37411b41e19a3e5c2ff1c1620a
> >> cb27c94d5b
> >>
> >>
> >> Romain Manni-Bucau
> >> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> >> <http://rmannibucau.wordpress.com> | Github <https://github.com/
> >> rmannibucau> |
> >> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Tomitriber
> >> <http://www.tomitribe.com>
> >>
> >> 2015-04-09 11:38 GMT+02:00 Romain Manni-Bucau <[email protected]>:
> >>
> >> > Well not using ejb is surely the current way. They will be reserved
> for
> >> > scheduling in todays apps i guess.
> >> >  Le 9 avr. 2015 10:06, "Alex Soto" <[email protected]> a écrit :
> >> >
> >> >> Ok then I need to implement in two different ways. :( This is
> >> something to
> >> >> improve (I think Java EE 8 is on that way) because security is
> >> something
> >> >> transversal so it should be global, not having to implement several
> >> pieces
> >> >> in several places.
> >> >>
> >> >> Well thanks then last option is my option :)
> >> >>
> >> >> El dj., 9 abr., 2015 a les 10:02, Romain Manni-Bucau (<
> >> >> [email protected]>)
> >> >> va escriure:
> >> >>
> >> >> > Hi
> >> >> >
> >> >> > Le 9 avr. 2015 09:15, "Alex Soto" <[email protected]> a écrit :
> >> >> > >
> >> >> > > Hello, I am trying to create an application where I can mix Java
> EE
> >> >> > > security annotations in JAX-RS endpoints. I am using current
> TomEE
> >> 2
> >> >> > > Snapshot and basically I am creating two ContainerRequestFilter.
> >> >> > > One for authentication and another for authorization.
> >> >> > >
> >> >> > > @Provider
> >> >> > > @Priority(Priorities.AUTHENTICATION)
> >> >> > > public class JWTAuthenticationFilter implements
> >> >> ContainerRequestFilter {
> >> >> > >
> >> >> > >     private static final List<Class<? extends Annotation>>
> >> >> > > securityAnnotations =
> >> >> > >         Arrays.asList(DenyAll.class, PermitAll.class,
> >> >> > RolesAllowed.class);
> >> >> > >
> >> >> > >     @Context
> >> >> > >     private ResourceInfo resourceInfo;
> >> >> > >
> >> >> > >     private UserService userservice = new UserService();
> >> >> > >
> >> >> > >     @Override
> >> >> > >     public void filter(ContainerRequestContext request) throws
> >> >> > IOException {
> >> >> > >         if (isSecuredResource()) {
> >> >> > >
> >> >> > >             String token = request.getHeaderString("x-acc
> >> ess-token");
> >> >> > >
> >> >> > >             try {
> >> >> > >                 String username = getUsernameFromToken(token);
> >> >> > >                 final User user = userservice.findUser(username);
> >> >> > >
> >> >> > >                 request.setSecurityContext(new SecurityContext()
> {
> >> >> > >
> >> >> > >                     @Override
> >> >> > >                     public boolean isUserInRole(String role) {
> >> >> > >                         return user.isUserInRole(role);
> >> >> > >                     }
> >> >> > >
> >> >> > >                     @Override
> >> >> > >                     public boolean isSecure() {
> >> >> > >                         return false;
> >> >> > >                     }
> >> >> > >
> >> >> > >                     @Override
> >> >> > >                     public Principal getUserPrincipal() {
> >> >> > >                         return user;
> >> >> > >                     }
> >> >> > >
> >> >> > >                     @Override
> >> >> > >                     public String getAuthenticationScheme() {
> >> >> > >                         return SecurityContext.BASIC_AUTH;
> >> >> > >                     }
> >> >> > >                 });
> >> >> > >
> >> >> > >             } catch (java.text.ParseException | JOSEException |
> >> >> > > NullPointerException e) {
> >> >> > >                 request.abortWith(Response.status(404).build());
> >> >> > >             }
> >> >> > >         }
> >> >> > >     }
> >> >> > >
> >> >> > >     private boolean isSecuredResource() {
> >> >> > >
> >> >> > >         for (Class<? extends Annotation> securityClass :
> >> >> > > securityAnnotations) {
> >> >> > >             if (resourceInfo.getResourceMethod().
> >> isAnnotationPresent(
> >> >> > >                 securityClass)) {
> >> >> > >                 return true;
> >> >> > >             }
> >> >> > >         }
> >> >> > >
> >> >> > >         for (Class<? extends Annotation> securityClass :
> >> >> > > securityAnnotations) {
> >> >> > >             if (resourceInfo.getResourceClass().
> >> isAnnotationPresent(
> >> >> > >                 securityClass)) {
> >> >> > >                 return true;
> >> >> > >             }
> >> >> > >         }
> >> >> > >
> >> >> > >         return false;
> >> >> > >     }
> >> >> > >
> >> >> > >     private String getUsernameFromToken(String token)
> >> >> > >             throws java.text.ParseException, JOSEException {
> >> >> > >
> >> >> > >         SignedJWT signedJWT = SignedJWT.parse(token);
> >> >> > >         JWSVerifier verifier = new MACVerifier(SharedSecret.
> >> >> > getSecret());
> >> >> > >
> >> >> > >         if (signedJWT.verify(verifier)) {
> >> >> > >             return signedJWT.getJWTClaimsSet().getSubject();
> >> >> > >         } else {
> >> >> > >             throw new JOSEException("Firm is not verified.");
> >> >> > >         }
> >> >> > >     }
> >> >> > > }
> >> >> > >
> >> >> > >
> >> >> > > note that I am creating a custom security context and for
> >> >> authorization:
> >> >> > >
> >> >> > > @Provider
> >> >> > > @Priority(Priorities.AUTHORIZATION)
> >> >> > > public class RolesAllowedFilter implements
> ContainerRequestFilter {
> >> >> > >
> >> >> > >   private static final Response NOT_FOUND = Response.status(
> >> >> > >       Response.Status.NOT_FOUND).entity("{\"message\": \"Resource
> >> Not
> >> >> > > Found\"}").build();
> >> >> > >
> >> >> > >   @Context
> >> >> > >   private ResourceInfo resourceInfo;
> >> >> > >
> >> >> > >   @Override
> >> >> > >   public void filter(ContainerRequestContext requestContext)
> >> >> > >       throws IOException {
> >> >> > >     Method resourceMethod = resourceInfo.getResourceMethod();
> >> >> > >
> >> >> > >     // DenyAll on the method take precedence over RolesAllowed
> and
> >> >> > PermitAll
> >> >> > >     if (resourceMethod.isAnnotationPresent(DenyAll.class)) {
> >> >> > >       requestContext.abortWith(NOT_FOUND);
> >> >> > >       return;
> >> >> > >     }
> >> >> > >
> >> >> > >     // RolesAllowed on the method takes precedence over PermitAll
> >> >> > >     RolesAllowed ra =
> >> >> resourceMethod.getAnnotation(RolesAllowed.class);
> >> >> > >     if(assertRole(requestContext, ra)) {
> >> >> > >       return;
> >> >> > >     }
> >> >> > >
> >> >> > >     // PermitAll takes precedence over RolesAllowed on the class
> >> >> > >     if (resourceMethod.isAnnotationPresent(PermitAll.class)) {
> >> >> > >       // Do nothing.
> >> >> > >       return;
> >> >> > >     }
> >> >> > >
> >> >> > >     if
> >> >> >
> (resourceInfo.getResourceClass().isAnnotationPresent(DenyAll.class))
> >> >> > > {
> >> >> > >       requestContext.abortWith(NOT_FOUND);
> >> >> > >     }
> >> >> > >
> >> >> > >     // RolesAllowed on the class takes precedence over PermitAll
> >> >> > >     ra =
> >> >> > resourceInfo.getResourceClass().getAnnotation(RolesAllowed.class);
> >> >> > >     if(assertRole(requestContext, ra)) {
> >> >> > >       return;
> >> >> > >     }
> >> >> > >   }
> >> >> > >
> >> >> > >   private boolean assertRole(ContainerRequestContext
> >> requestContext,
> >> >> > > RolesAllowed ra) {
> >> >> > >
> >> >> > >     if (ra != null) {
> >> >> > >       String[] roles = ra.value();
> >> >> > >       for (String role : roles) {
> >> >> > >         if
> (requestContext.getSecurityContext().isUserInRole(role))
> >> {
> >> >> > >           return true;
> >> >> > >         }
> >> >> > >       }
> >> >> > >       requestContext.abortWith(NOT_FOUND);
> >> >> > >     }
> >> >> > >     return false;
> >> >> > >   }
> >> >> > > }
> >> >> > >
> >> >> > > And the business code:
> >> >> > >
> >> >> > > @Stateless
> >> >> > > @Path("/app")
> >> >> > > public class UiApplication {
> >> >> > >
> >> >> > >     @Inject
> >> >> > >     UserService userService;
> >> >> > >
> >> >> > >     @Inject
> >> >> > >     MovieService moviesService;
> >> >> > >
> >> >> > >     @POST
> >> >> > >     @Consumes(MediaType.APPLICATION_JSON)
> >> >> > >     @Produces(MediaType.APPLICATION_JSON)
> >> >> > >     public Response login(JsonObject jsonObject) throws
> >> JOSEException
> >> >> {
> >> >> > >
> >> >> > >       JsonString username = (JsonString)
> >> jsonObject.get("username");
> >> >> > >       JsonString password = (JsonString)
> >> jsonObject.get("password");
> >> >> > >
> >> >> > >       if (authenticate(username.getString(),
> >> password.getString())) {
> >> >> > >
> >> >> > >         String token = createToken(username.getString(), "
> >> example.com
> >> >> ");
> >> >> > >
> >> >> > >         JsonObject responseDocument = Json.createObjectBuilder()
> >> >> > >           .add("user", Json.createObjectBuilder().add("username",
> >> >> > > username).build())
> >> >> > >           .add("token", token)
> >> >> > >           .build();
> >> >> > >
> >> >> > >         return Response.ok(responseDocument).build();
> >> >> > >
> >> >> > >       }
> >> >> > >
> >> >> > >       return Response.status(Status.NOT_FOUND).build();
> >> >> > >
> >> >> > >     }
> >> >> > >
> >> >> > >     @GET
> >> >> > >     @Produces(MediaType.APPLICATION_JSON)
> >> >> > >     @RolesAllowed("admin")
> >> >> > >     public Response movies() {
> >> >> > >         return Response.ok("{\"message\":\"a\"}").build();
> >> >> > >     }
> >> >> > >
> >> >> > >     private boolean authenticate(String username, String
> password)
> >> {
> >> >> > >         return this.userService.findUser(username, password);
> >> >> > >     }
> >> >> > >
> >> >> > >     private String createToken(String subject, String issuer)
> >> throws
> >> >> > > JOSEException {
> >> >> > >
> >> >> > >       JWSSigner signer = new MACSigner(SharedSecret.getSecret());
> >> >> > >
> >> >> > >       JWTClaimsSet claimsSet = new JWTClaimsSet();
> >> >> > >       claimsSet.setSubject(subject);
> >> >> > >       claimsSet.setIssueTime(new Date());
> >> >> > >       claimsSet.setIssuer(issuer);
> >> >> > >
> >> >> > >       SignedJWT signedJWT = new SignedJWT(new
> >> >> > > JWSHeader(JWSAlgorithm.HS256), claimsSet);
> >> >> > >       signedJWT.sign(signer);
> >> >> > >
> >> >> > >       return signedJWT.serialize();
> >> >> > >
> >> >> > >     }
> >> >> > >
> >> >> > > }
> >> >> > >
> >> >> > > If I run in this way it doesn't work because the endpoint is also
> >> an
> >> >> EJB
> >> >> > > and because security context of EJB is not shared with the
> JAX-RS,
> >> the
> >> >> > > method throws an 403 Forbidden. Is there any clean way to make
> that
> >> >> this
> >> >> > > don't happen? Of course I can make JAXRS class as none EJB, but
> >> this
> >> >> > would
> >> >> > > be my last option.
> >> >> > >
> >> >> >
> >> >> > Well with @Transactional it would makes sense since you handle
> >> security.
> >> >> > Using jaas would be the way to have custom logic in ejbs.
> >> >> >
> >> >> > > Also is there a way to use @Inject in ContainerRequestFilter?
> >> >> Currently I
> >> >> > > cannot use it because the instance is not injected.
> >> >> > >
> >> >> >
> >> >> > Not yet, dont recall what spec says about it btw
> >> >> >
> >> >> > > Thank you so much.
> >> >> > >
> >> >> > > Alex.
> >> >> >
> >> >>
> >> >
> >>
> >
>

Reply via email to