Hello Matthias,
Regarding authentication I normally use a ContainerRequestFilter.
Follows an example of a filter where authentication is done using a JWT
token.
It uses JwtService that is responsible for creating and validating tokens.
It uses jose4j.
@Secured
> @Provider
> @Priority(Priorities.AUTHENTICATION)
> @Component(scope = ServiceScope.PROTOTYPE, //
> service = { ContainerRequestFilter.class }, //
> property = {
> JaxrsWhiteboardConstants.JAX_RS_EXTENSION + "=" + true, //
> JaxrsWhiteboardConstants.JAX_RS_NAME + "=" +
> "TokenAuthenticationFilter", //
> Constants.JAX_RS_APPLICATION_SELECT, //
> })
> public class TokenAuthenticationFilter implements ContainerRequestFilter {
>
> private static final Logger LOGGER =
> LoggerFactory.getLogger(TokenAuthenticationFilter.class);
>
> private static final String AUTHENTICATION_SCHEME = "Bearer";
>
> private static final String AUTHENTICATION_SCHEME_PREFIX =
> AUTHENTICATION_SCHEME + " ";
>
> @Reference(cardinality = ReferenceCardinality.MANDATORY)
> JwtService jwtService;
>
> @Context
> private ResourceInfo resourceInfo;
>
> @Override
> public void filter(ContainerRequestContext requestContext) throws
> IOException {
>
> // Get the Authorization header from the request
> String authorizationHeader =
> requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
> LOGGER.debug("authorizationHeader {}", authorizationHeader);
> // Validate the Authorization header
> if (!isTokenBasedAuthentication(authorizationHeader)) {
> LOGGER.info("Missing auth token. Aborting");
> abortWithUnauthorized(requestContext);
> return;
> }
> // Extract the token from the Authorization header
> final String token =
> authorizationHeader.substring(AUTHENTICATION_SCHEME_PREFIX.length());
> try {
> // Validate the token. An exception will be thrown if invalid
> SubjectDetails subjectDetails =
> jwtService.validateToken(token);
> LOGGER.debug("Token for subject {} accepted",
> subjectDetails.getId());
> initSecurityContext(requestContext, subjectDetails);
> Permission requiredPermission =
> getPermissionForResource(resourceInfo);
> if (!subjectDetails.hasPermission(requiredPermission)) {
> LOGGER.debug("subject {} lack permission {}",
> subjectDetails.getId(), requiredPermission);
> abortWithForbidden(requestContext);
> }
> }
> catch (AuthenticationException e) {
> LOGGER.trace("Ignored", e);
> LOGGER.info("Token validation failed. Aborting");
> abortWithUnauthorized(requestContext);
> }
> }
>
> /**
> * @param requestContext
> * @param subjectDetails
> */
> private void initSecurityContext(ContainerRequestContext
> requestContext, SubjectDetails subjectDetails) {
>
> final SecurityContext currentSecurityContext =
> requestContext.getSecurityContext();
> boolean secure = currentSecurityContext.isSecure();
> requestContext.setSecurityContext(new
> InternalSecurityContext(subjectDetails, secure));
>
> }
>
> private boolean isTokenBasedAuthentication(String authorizationHeader)
> {
>
> // Check if the Authorization header is valid
> // It must not be null and must be prefixed with "Bearer" plus a
> // whitespace
> // The authentication scheme comparison must be case-insensitive
> return StringUtils.startsWithIgnoreCase(authorizationHeader,
> AUTHENTICATION_SCHEME_PREFIX);
> }
>
> private void abortWithUnauthorized(ContainerRequestContext
> requestContext) {
>
> // Abort the filter chain with a 401 status code response
> // The WWW-Authenticate header is sent along with the response
> requestContext.abortWith(
> Response.status(Response.Status.UNAUTHORIZED)
> .header(HttpHeaders.WWW_AUTHENTICATE,
> AUTHENTICATION_SCHEME + " realm=\"" +
> Constants.APP_NAME + "\"")
> .build());
> }
>
> private void abortWithForbidden(ContainerRequestContext
> requestContext) {
>
>
> requestContext.abortWith(Response.status(Response.Status.FORBIDDEN).build());
> }
>
> static Permission getPermissionForResource(ResourceInfo resourceInfo) {
>
> Permission permission =
> extractPermission(resourceInfo.getResourceMethod());
> if (permission != null) {
> return permission;
> }
> permission = extractPermission(resourceInfo.getResourceClass());
> return permission;
>
> }
>
> // Extract Permission from the annotated element
> static Permission extractPermission(AnnotatedElement annotatedElement)
> {
>
> if (annotatedElem