Hi Charles, hope you don't mind that I moved this discussion to the tapestry users list as it may be useful for others as well. Yes, I'm right there with you. The trick to this is to override the SubjectFactory. Shiro creates a subject for all requests, authenticated or not. The principle is roughly the same as with the tynamo-federatedaccounts-rollingtokens module, i.e. you want to create an authenticated subject based on the request headers. So for JWT, it's something like this:
public class JwtAwareWebSubjectFactory extends DefaultWebSubjectFactory { private static final String AUTHORIZATIONHEADER_PREFIX = "Bearer "; private HttpServletRequest request; private HttpServletResponse response; public JwtAwareWebSubjectFactory(HttpServletRequest request, HttpServletResponse response) { this.request = request; this.response = response; } @Override public Subject createSubject(SubjectContext context) { String authorizationHeader = request.getHeader("Authorization"); if (authorizationHeader == null) return super.createSubject(context); // create subject for REST requests. SubjectContext doesn't contain much useful information, we need to read // it from JWT token claims instead if (!authorizationHeader.contains(AUTHORIZATIONHEADER_PREFIX)) { throw new IllegalArgumentException( "JWT authorization header exist but did not start with '" + AUTHORIZATIONHEADER_PREFIX + "'"); } authorizationHeader = authorizationHeader.substring(authorizationHeader.indexOf(AUTHORIZATIONHEADER_PREFIX) + AUTHORIZATIONHEADER_PREFIX.length()); Claims claims = Jwts.parser().setSigningKey(AuthResourceImpl.SECRET.getBytes(StandardCharsets.UTF_8)) .parseClaimsJws(authorizationHeader).getBody(); WebSubjectContext wsc = (WebSubjectContext) context; SecurityManager securityManager = wsc.resolveSecurityManager(); Session session = null; // wsc.resolveSession(); request.setAttribute(DefaultSubjectContext.SESSION_CREATION_ENABLED, false); boolean sessionEnabled = false; SimplePrincipalCollection principals = new SimplePrincipalCollection(); principals.add(claims.getSubject(), UserRealm.LOCALACCOUNTS_REALM); // Somewhat abused JWT's API here, storing user id in audience claim for convenience principals.add(Long.parseLong(claims.getAudience()), UserRealm.LOCALACCOUNTS_REALM); boolean authenticated = true; String host = wsc.resolveHost(); ServletRequest request = wsc.resolveServletRequest(); ServletResponse response = wsc.resolveServletResponse(); // we are going backwards here - we set the values to subjectcontext after creating a subject, but there's no // SubjectContextFactory in shiro context.setPrincipals(principals); context.setSessionCreationEnabled(false); context.setAuthenticated(true); return new WebDelegatingSubject(principals, authenticated, host, session, sessionEnabled, request, response, securityManager); } } In your AppModule, the usual: @Contribute(ServiceOverride.class) public static void overrideServices(MappedConfiguration<Class<?>, Object> configuration, @Local SubjectFactory jwtAwareWebSubjectFactory) { configuration.add(SubjectFactory.class, jwtAwareWebSubjectFactory); } As for authentication, it shouldn't matter much whether you do local username/password authentication or Oauth with a third-party authorization provider. At the end of a successful flow, you just return a new bearer token. Kalle On Mon, Dec 21, 2015 at 7:25 AM, Charlouze <m...@charlouze.com> wrote: > Hello ! > > I'd like to secure my REST API (which is using tapestry-resteasy) using > two different system : > > - standard session connexion with a form > - oauth with no session and a bearer token each connexion for client > apps to retrieve and update data. (except for the token endpoint) > > The first one is OK as it is the standard approch that I've been using in > my app for month. Then, I tried to implement the bearer token authorization > but I'm not able to do it properly. Maybe you can advise me on where to > look in order to succeed. > > Thanks in advance. > > Regards, > Charles. >