I am using JWT in header for verifying user request.
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("token");
// Verify a Token
try {
Algorithm algorithm = Algorithm.HMAC256("secret");
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer("auth0")
.build(); //Reusable verifier instance
DecodedJWT jwt = verifier.verify(token);
} catch (UnsupportedEncodingException exception) {
// send internal server error in response
} catch (JWTVerificationException exception) {
// send invalid token
}
return chain.filter(exchange);
}
When I use
return Mono.empty();
It ends requests, but how to set a proper response? e.g. "Invalid token" OR "Internal Server Error" in response.
In the catch block you can do the following or rethrow the exception so you have some GlobalExceptionHandler by implementing "org.springframework.web.server.WebExceptionHandler" and there you can have this logic as well. The Key here is using DataBufferFactory and then using ObjectMapper of Jackson to serialize your custom error object to string and then write the response as well as set the HTTP Status using exchange.getResponse().setStatusCode
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@Autowired
ObjectMapper objMapper;
ApiError apiError = new ApiError(HttpStatus.UNAUTHORIZED);
apiError.setTimestamp(LocalDateTime.now());
apiError.setMessage("Invalid token" + exception.getMessage() + ":"+exception.getLocalizedMessage());
DataBuffer buf = null;
try {
buf = dataBufferFactory.wrap(objMapper.writeValueAsBytes(apiError));
} catch (JsonProcessingException e) {
LOG.debug("Exception during processing JSON", e);
apiError.setMessage(e.getMessage());
}
if(buf == null) buf = dataBufferFactory.wrap("".getBytes());
exchange.getResponse().setStatusCode(apiError.getStatus());
return exchange.getResponse().writeWith(Flux.just(buf));
ApiError is a custom class that has HTTP Status and timestamp and stuff like below or your custom datastructure as well.
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
import org.springframework.http.HttpStatus;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ApiError implements Serializable{
private HttpStatus status;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "MM/dd/yyyy hh:mm:ss a")
private LocalDateTime timestamp;
private String message;
private String debugMessage;
public ApiError() {
timestamp = LocalDateTime.now();
}
public ApiError(HttpStatus status) {
this();
this.status = status;
}
public ApiError(HttpStatus status, Throwable ex) {
this();
this.status = status;
this.message = "Unexpected error";
this.debugMessage = ex.getLocalizedMessage();
}
public ApiError(HttpStatus status, String message, Throwable ex) {
this();
this.status = status;
this.message = message;
this.debugMessage = ex.getLocalizedMessage();
}
}
Maybe this will help, this is for x509 authentication but it will work for JWT.
Check Authentication by certificate for WebFlux?
Key points are:
Hope this helps
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With