Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development: Enable bearer authentication #9403

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import java.util.regex.Pattern;

import jakarta.annotation.Nullable;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.constraints.NotNull;

import org.slf4j.Logger;
Expand Down Expand Up @@ -52,7 +52,6 @@
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
import org.springframework.web.socket.sockjs.transport.handler.WebSocketTransportHandler;
import org.springframework.web.util.WebUtils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Iterators;
Expand Down Expand Up @@ -203,8 +202,7 @@ public boolean beforeHandshake(@NotNull ServerHttpRequest request, @NotNull Serv
@NotNull Map<String, Object> attributes) {
if (request instanceof ServletServerHttpRequest servletRequest) {
attributes.put(IP_ADDRESS, servletRequest.getRemoteAddress());
Cookie jwtCookie = WebUtils.getCookie(servletRequest.getServletRequest(), JWTFilter.JWT_COOKIE_NAME);
return JWTFilter.isJwtCookieValid(tokenProvider, jwtCookie);
return JWTFilter.extractValidJwt((HttpServletRequest) servletRequest, tokenProvider) != null;
janthoXO marked this conversation as resolved.
Show resolved Hide resolved
janthoXO marked this conversation as resolved.
Show resolved Hide resolved
}
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;

import javax.annotation.Nullable;
janthoXO marked this conversation as resolved.
Show resolved Hide resolved

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
Expand All @@ -31,26 +33,72 @@ public JWTFilter(TokenProvider tokenProvider) {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
Cookie jwtCookie = WebUtils.getCookie(httpServletRequest, JWT_COOKIE_NAME);
if (isJwtCookieValid(this.tokenProvider, jwtCookie)) {
Authentication authentication = this.tokenProvider.getAuthentication(jwtCookie.getValue());

// check if valid JWT token is in the cookie or in the Authorization header
janthoXO marked this conversation as resolved.
Show resolved Hide resolved
// then proceed to do authentication with this token
String jwtToken = extractValidJwt(httpServletRequest, this.tokenProvider);
if (jwtToken != null) {
Authentication authentication = this.tokenProvider.getAuthentication(jwtToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
}

filterChain.doFilter(servletRequest, servletResponse);
}

/**
* Checks if the cookie containing the jwt is valid
* Extracts a valid jwt token from the cookie first or if not set from the Authorization header
*
* @param tokenProvider the artemis token provider used to generate and validate jwt's
* @param jwtCookie the cookie containing the jwt
* @return true if the jwt is valid, false if missing or invalid
* @param httpServletRequest the http request
* @param tokenProvider the artemis token provider used to generate and validate jwt's
janthoXO marked this conversation as resolved.
Show resolved Hide resolved
* @return the valid jwt token or null if not found or invalid
*/
public static @Nullable String extractValidJwt(HttpServletRequest httpServletRequest, TokenProvider tokenProvider) {
Cookie jwtCookie = WebUtils.getCookie(httpServletRequest, JWT_COOKIE_NAME);
String jwtToken;
// returns the first valid jwt token found in the cookie or the Authorization header
if (isJwtValid(tokenProvider, jwtToken = getJwtFromCookie(jwtCookie))
|| isJwtValid(tokenProvider, jwtToken = getJwtFromBearer(httpServletRequest.getHeader("Authorization")))) {
return jwtToken;
}

return null;
}
janthoXO marked this conversation as resolved.
Show resolved Hide resolved

/**
* Extracts the jwt token from the cookie
*
* @param jwtCookie the cookie with Key "jwt"
* @return the jwt token
*/
public static boolean isJwtCookieValid(TokenProvider tokenProvider, Cookie jwtCookie) {
private static String getJwtFromCookie(Cookie jwtCookie) {
if (jwtCookie == null) {
return false;
return null;
}
String jwt = jwtCookie.getValue();
return StringUtils.hasText(jwt) && tokenProvider.validateTokenForAuthority(jwt);
return jwtCookie.getValue();
}

/**
* Extracts the jwt token from the Authorization header
*
* @param jwtBearer the content of the Authorization header
* @return the jwt token
*/
private static String getJwtFromBearer(String jwtBearer) {
if (!StringUtils.hasText(jwtBearer) || !jwtBearer.startsWith("Bearer ")) {
return null;
}

return jwtBearer.substring(7);
}
janthoXO marked this conversation as resolved.
Show resolved Hide resolved

/**
* Checks if the jwt token is valid
*
* @param tokenProvider the artemis token provider used to generate and validate jwt's
* @param jwtToken the jwt token
* @return true if the jwt is valid, false if missing or invalid
*/
public static boolean isJwtValid(TokenProvider tokenProvider, String jwtToken) {
janthoXO marked this conversation as resolved.
Show resolved Hide resolved
return StringUtils.hasText(jwtToken) && tokenProvider.validateTokenForAuthority(jwtToken);
janthoXO marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public PublicUserJwtResource(JWTCookieService jwtCookieService, AuthenticationMa
*/
@PostMapping("authenticate")
@EnforceNothing
public ResponseEntity<Void> authorize(@Valid @RequestBody LoginVM loginVM, @RequestHeader("User-Agent") String userAgent, HttpServletResponse response) {
public ResponseEntity<String> authorize(@Valid @RequestBody LoginVM loginVM, @RequestHeader("User-Agent") String userAgent, HttpServletResponse response) {

var username = loginVM.getUsername();
var password = loginVM.getPassword();
Expand All @@ -86,7 +86,7 @@ public ResponseEntity<Void> authorize(@Valid @RequestBody LoginVM loginVM, @Requ
ResponseCookie responseCookie = jwtCookieService.buildLoginCookie(rememberMe);
response.addHeader(HttpHeaders.SET_COOKIE, responseCookie.toString());

return ResponseEntity.ok().build();
return ResponseEntity.ok(responseCookie.getValue());
iyannsch marked this conversation as resolved.
Show resolved Hide resolved
}
catch (BadCredentialsException ex) {
log.warn("Wrong credentials during login for user {}", loginVM.getUsername());
Expand Down
Loading