I'm getting 403 forbidden error for the external requests. And found the authorization is failing from the isAuthorized method inside the CsrfAuthorizer.class which is derived from pac4j.
And I compared the pack4j version 4.3.1, the isAuthorized method is pretty much different in the 4.3.1. Here is the two methods in the different versions.
VERSION 4.3.1
boolean checkRequest = this.checkAllRequests || ContextHelper.isPost(context) || ContextHelper.isPut(context) || ContextHelper.isPatch(context) || ContextHelper.isDelete(context);
if (!checkRequest) {
return true;
} else {
String parameterToken = (String)context.getRequestParameter(this.parameterName).orElse((Object)null);
String headerToken = (String)context.getRequestHeader(this.headerName).orElse((Object)null);
Optional<String> sessionToken = context.getSessionStore().get(context, "pac4jCsrfToken");
return sessionToken.isPresent() && (((String)sessionToken.get()).equals(parameterToken) || ((String)sessionToken.get()).equals(headerToken));
}
}
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
VERSION 5.3.1
public boolean isAuthorized(final WebContext context, final SessionStore sessionStore, final List<UserProfile> profiles) {
final var checkRequest = checkAllRequests || isPost(context) || isPut(context) || isPatch(context) || isDelete(context);
if (checkRequest) {
final var parameterToken = context.getRequestParameter(parameterName).orElse(null);
final var headerToken = context.getRequestHeader(headerName).orElse(null);
LOGGER.debug("parameterToken: {}", parameterToken);
LOGGER.debug("headerToken: {}", headerToken);
final var sessionPreviousToken = sessionStore.get(context, Pac4jConstants.PREVIOUS_CSRF_TOKEN);
final var sessionToken = sessionStore.get(context, Pac4jConstants.CSRF_TOKEN);
final var sessionDate = sessionStore.get(context, Pac4jConstants.CSRF_TOKEN_EXPIRATION_DATE);
if (sessionStore.getSessionId(context, false).isPresent()) {
sessionStore.set(context, Pac4jConstants.PREVIOUS_CSRF_TOKEN, null);
}
// all checks are always performed, conditional operations are turned into logical ones,
// string comparisons are replaced by hash equalities to be protected against time-based attacks
final var hasSessionData = sessionToken.isPresent() & sessionDate.isPresent();
final var previousToken = (String) sessionPreviousToken.orElse("");
LOGGER.debug("previous token: {}", previousToken);
final var token = (String) sessionToken.orElse("");
LOGGER.debug("token: {}", token);
final var isGoodCurrentToken = hashEquals(token, parameterToken) | hashEquals(token, headerToken);
final var isGoodPreviousToken = hashEquals(previousToken, parameterToken) | hashEquals(previousToken, headerToken);
final var isGoodToken = isGoodCurrentToken | isGoodPreviousToken;
final var expirationDate = (Long) sessionDate.orElse(0L);
final var now = new Date().getTime();
final var isDateExpired = expirationDate < now;
if (!hasSessionData | !isGoodToken | isDateExpired) {
return false;
}
}
return true;
}
--------------------------------------------------------------------------------
final var isGoodCurrentToken = hashEquals(token, parameterToken) | hashEquals(token, headerToken);
final var isGoodPreviousToken = hashEquals(previousToken, parameterToken) | hashEquals(previousToken, headerToken);
final var isGoodToken = isGoodCurrentToken | isGoodPreviousToken;
final var expirationDate = (Long) sessionDate.orElse(0L);
final var now = new Date().getTime();
final var isDateExpired = expirationDate < now;
if (!hasSessionData | !isGoodToken | isDateExpired) {
return false;
}
All of above are false.
So then it returns false always.
Does anyone has a clear idea about the usage of this?