Skip to content

Commit

Permalink
fix: operate uses different csrf header for different versions (#161) (
Browse files Browse the repository at this point in the history
…#163)

(cherry picked from commit b700589)
  • Loading branch information
jonathanlukas authored Dec 9, 2024
1 parent 1f36a72 commit bbcea8b
Showing 1 changed file with 37 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.ProtocolException;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SimpleAuthentication implements Authentication {
private static final String CSRF_HEADER = "OPERATE-X-CSRF-TOKEN";
private static final Set<String> CSRF_HEADER_CANDIDATES =
Set.of("X-CSRF-TOKEN", "OPERATE-X-CSRF-TOKEN");
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

private final SimpleCredential simpleCredential;
private SimpleAuthToken token;
private LocalDateTime sessionTimeout;

public SimpleAuthentication(SimpleCredential simpleCredential) {
this.simpleCredential = simpleCredential;
Expand All @@ -39,9 +41,11 @@ private SimpleAuthToken retrieveToken() {
"Unable to login, response code " + response.getCode());
}
String csrfTokenCandidate = null;
Header csrfTokenHeader = response.getHeader(CSRF_HEADER);
String csrfTokenHeaderName = null;
Header csrfTokenHeader = findCsrfTokenHeader(response);
if (csrfTokenHeader != null) {
csrfTokenCandidate = csrfTokenHeader.getValue();
csrfTokenHeaderName = csrfTokenHeader.getName();
}
Header[] cookieHeaders = response.getHeaders("Set-Cookie");
String sessionCookie = null;
Expand All @@ -51,11 +55,18 @@ private SimpleAuthToken retrieveToken() {
if (cookieHeader.getValue().startsWith(sessionCookieName)) {
sessionCookie = cookieHeader.getValue();
}
if (cookieHeader.getValue().startsWith(CSRF_HEADER)) {
csrfCookie = cookieHeader.getValue();
for (String candidate : CSRF_HEADER_CANDIDATES) {
if (cookieHeader.getValue().startsWith(candidate)) {
csrfCookie = cookieHeader.getValue();
}
}
}
return new SimpleAuthToken(sessionCookie, csrfCookie, csrfTokenCandidate);
return new SimpleAuthToken(
sessionCookie,
csrfCookie,
csrfTokenCandidate,
csrfTokenHeaderName,
LocalDateTime.now().plus(simpleCredential.sessionTimeout()));
});
if (simpleAuthToken.sessionCookie() == null) {
throw new RuntimeException(
Expand All @@ -67,13 +78,24 @@ private SimpleAuthToken retrieveToken() {
if (simpleAuthToken.csrfCookie() == null) {
LOG.info("No CSRF cookie found");
}
sessionTimeout = LocalDateTime.now().plus(simpleCredential.sessionTimeout());
return simpleAuthToken;
} catch (Exception e) {
throw new RuntimeException("Unable to authenticate", e);
}
}

private Header findCsrfTokenHeader(ClassicHttpResponse response) throws ProtocolException {
if (token != null) {
return response.getHeader(token.csrfTokenHeaderName());
}
for (String candidate : CSRF_HEADER_CANDIDATES) {
if (response.containsHeader(candidate)) {
return response.getHeader(candidate);
}
}
return null;
}

private HttpPost buildRequest(SimpleCredential simpleCredential) {
HttpPost httpPost = new HttpPost(simpleCredential.baseUrl().toString() + "/api/login");
List<NameValuePair> params = new ArrayList<>();
Expand All @@ -85,12 +107,12 @@ private HttpPost buildRequest(SimpleCredential simpleCredential) {

@Override
public Map<String, String> getTokenHeader() {
if (token == null || sessionTimeout.isBefore(LocalDateTime.now())) {
if (token == null || token.sessionTimeout().isBefore(LocalDateTime.now())) {
token = retrieveToken();
}
Map<String, String> headers = new HashMap<>();
if (token.csrfToken() != null) {
headers.put(CSRF_HEADER, token.csrfToken());
headers.put(token.csrfTokenHeaderName(), token.csrfToken());
}
headers.put(
"Cookie",
Expand All @@ -105,5 +127,10 @@ public void resetToken() {
token = null;
}

private record SimpleAuthToken(String sessionCookie, String csrfCookie, String csrfToken) {}
private record SimpleAuthToken(
String sessionCookie,
String csrfCookie,
String csrfToken,
String csrfTokenHeaderName,
LocalDateTime sessionTimeout) {}
}

0 comments on commit bbcea8b

Please sign in to comment.