Reputation: 165
I am using JBOSS EAP 8. I package in a single war file For learning purposes I have implemented a REST API with a login Endpoint which returns a JWToken to the client. Other REST endpoints are protected by
import java.io.IOException;
import java.util.Base64;
import jakarta.annotation.Priority;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
@Provider
@Priority(Priorities.AUTHENTICATION)
public class JWTAuthenticationFilter implements ContainerRequestFilter {
private static final String SECRET_KEY = Base64.getEncoder().encodeToString("your-256-bit-secret-key-in-base64".getBytes());
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
String authHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
return; // No token, skip authentication
}
String token = authHeader.substring(7); // Strip "Bearer "
try {
Claims claims = parseToken(token);
String username = claims.getSubject();
String role = (String) claims.get("role");
if (username != null && role != null) {
// Set a custom security context with the principal and role
requestContext.setSecurityContext(new JWTSecurityContext(username, role));
} else {
abortWithUnauthorized(requestContext);
}
} catch (Exception e) {
abortWithUnauthorized(requestContext);
}
}
private Claims parseToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(Base64.getDecoder().decode(SECRET_KEY))
.build()
.parseClaimsJws(token)
.getBody();
}
private void abortWithUnauthorized(ContainerRequestContext requestContext) {
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Unauthorized").build());
}
}
public class JWTSecurityContext implements SecurityContext {
private final JWTPrincipal principal;
private final String role;
public JWTSecurityContext(String username, String role) {
this.principal = new JWTPrincipal(username);
this.role = role;
}
@Override
public Principal getUserPrincipal() {
return principal;
}
@Override
public boolean isUserInRole(String role) {
return this.role != null && this.role.equals(role);
}
@Override
public boolean isSecure() {
return true; // Assume HTTPS is used
}
@Override
public String getAuthenticationScheme() {
return "Bearer";
}
}
This works fine. The token is processed and Username and Role are extracted.
@Path("/api")
public class AdminEndpoint {
@EJB
private SecuredService securedService;
@GET
@Path("/admin")
@Produces(MediaType.TEXT_PLAIN)
public Response adminEndpoint(@Context HttpHeaders headers) {
return Response.ok(securedService.performAdminTask()).build();
}
}
But I want to use the role to authorize
@Stateless
@DeclareRoles({"Admin"})
public class SecuredService {
@RolesAllowed({"Admin"})
public String performAdminTask() {
String result = "Admin task performed!";
System.out.println(result);
return result;
}
}
This does not work WFLYEJB0364: Aufruf an Methode: public java.lang.String ejb.SecuredService.performAdminTask() von Bean: SecuredService ist nicht gestattet Translates to caoll of method … not allowed. I have not figured out how to propagate the SecurityContext to the EJB. Any help would be greatly appreciated.
Upvotes: 0
Views: 28