Regalamiunsorriso/www/_inc_faceai_identity.jsp
MaddoScientisto 1d1bccdae6 Add Playwright tests for live site authentication and race page loading
- Introduced `auth.setup.js` to handle authentication against the live site and store the session state.
- Created `live-race.spec.js` to test loading a live race page with an authenticated session, including cookie validation.
- Added utility functions in `live-site-test-utils.js` for managing authentication, dismissing cookie banners, and checking UI states.
- Included a temporary JSON file for live state inspection.
- Updated deployment manifest to reflect new and modified files.
- Implemented `_inc_faceai_identity.jsp` for managing FaceAI identity cookies and included it in relevant JSP files.
- Added language management JavaScript in `lang.js`.
- Adjusted `fotoCR-en.jsp` and `fotoCR.jsp` to include the FaceAI identity logic.
- Created a tarball for staging deployment.
2026-04-19 10:26:34 +02:00

260 lines
No EOL
8.5 KiB
Text

<%@ page language="java" import="java.nio.charset.StandardCharsets" %>
<%@ page language="java" import="java.util.Base64" %>
<%@ page language="java" import="java.lang.reflect.Method" %>
<%@ page language="java" import="javax.crypto.Mac" %>
<%@ page language="java" import="javax.crypto.spec.SecretKeySpec" %>
<%!
private String faceAiCookieEnv(String key, String defaultValue) {
String value = System.getenv(key);
if (value == null || value.trim().length() == 0) {
value = System.getProperty(key, defaultValue);
}
if (value == null) {
return defaultValue;
}
value = value.trim();
return value.length() == 0 ? defaultValue : value;
}
private String faceAiBase64Url(byte[] value) {
return Base64.getUrlEncoder().withoutPadding().encodeToString(value);
}
private String faceAiJsonEscape(String value) {
if (value == null) {
return "";
}
StringBuilder builder = new StringBuilder(value.length() + 16);
for (int index = 0; index < value.length(); index++) {
char current = value.charAt(index);
switch (current) {
case '\\':
builder.append("\\\\");
break;
case '"':
builder.append("\\\"");
break;
case '\b':
builder.append("\\b");
break;
case '\f':
builder.append("\\f");
break;
case '\n':
builder.append("\\n");
break;
case '\r':
builder.append("\\r");
break;
case '\t':
builder.append("\\t");
break;
default:
if (current < 0x20) {
String hex = Integer.toHexString(current);
builder.append("\\u");
for (int padding = hex.length(); padding < 4; padding++) {
builder.append('0');
}
builder.append(hex);
} else {
builder.append(current);
}
break;
}
}
return builder.toString();
}
private Object faceAiInvoke(Object bean, String methodName) {
if (bean == null || methodName == null || methodName.length() == 0) {
return null;
}
try {
Method method = bean.getClass().getMethod(methodName, new Class[0]);
return method.invoke(bean, new Object[0]);
} catch (Exception ignored) {
return null;
}
}
private long faceAiUserId(Object user) {
Object value = faceAiInvoke(user, "getId_users");
if (value instanceof Number) {
return ((Number) value).longValue();
}
if (value != null) {
try {
return Long.parseLong(String.valueOf(value));
} catch (NumberFormatException ignored) {
return 0L;
}
}
return 0L;
}
private String faceAiUserString(Object user, String methodName) {
Object value = faceAiInvoke(user, methodName);
return value == null ? "" : String.valueOf(value).trim();
}
private boolean faceAiUserDaRinnovare(Object user) {
Object value = faceAiInvoke(user, "isDaRinnovare");
return value instanceof Boolean ? ((Boolean) value).booleanValue() : false;
}
private String faceAiCookieDisplayName(Object user) {
String nome = faceAiUserString(user, "getNome");
String cognome = faceAiUserString(user, "getCognome");
String displayName = (nome + " " + cognome).trim();
if (displayName.length() > 0) {
return displayName;
}
String email = faceAiUserString(user, "getEMail");
if (email.length() > 0) {
return email;
}
return String.valueOf(faceAiUserId(user));
}
private String faceAiIdentityToken(Object user, String secret, long expiresAt) throws Exception {
String email = faceAiUserString(user, "getEMail");
String membershipStatus = faceAiUserDaRinnovare(user) ? "inactive" : "active";
String payload = "{"
+ "\"type\":\"legacy-identity\","
+ "\"userId\":\"" + faceAiJsonEscape(String.valueOf(faceAiUserId(user))) + "\","
+ "\"displayName\":\"" + faceAiJsonEscape(faceAiCookieDisplayName(user)) + "\","
+ "\"email\":\"" + faceAiJsonEscape(email) + "\","
+ "\"membershipStatus\":\"" + membershipStatus + "\","
+ "\"expiresAt\":" + expiresAt
+ "}";
String body = faceAiBase64Url(payload.getBytes(StandardCharsets.UTF_8));
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
String signature = faceAiBase64Url(mac.doFinal(body.getBytes(StandardCharsets.UTF_8)));
return body + "." + signature;
}
private boolean faceAiRequestIsSecure(javax.servlet.http.HttpServletRequest request) {
if (request == null) {
return false;
}
if (request.isSecure()) {
return true;
}
String forwardedProto = request.getHeader("X-Forwarded-Proto");
if (forwardedProto != null && "https".equalsIgnoreCase(forwardedProto.trim())) {
return true;
}
String frontEndHttps = request.getHeader("Front-End-Https");
return frontEndHttps != null && "on".equalsIgnoreCase(frontEndHttps.trim());
}
private void faceAiWriteCookieHeader(javax.servlet.http.HttpServletResponse response, String cookieName, String cookieValue, int maxAgeSeconds, boolean secureCookie) {
StringBuilder headerValue = new StringBuilder();
headerValue.append(cookieName).append('=').append(cookieValue == null ? "" : cookieValue);
headerValue.append("; Max-Age=").append(maxAgeSeconds);
headerValue.append("; Path=/; HttpOnly; SameSite=Lax");
if (secureCookie) {
headerValue.append("; Secure");
}
response.addHeader("Set-Cookie", headerValue.toString());
}
private Object faceAiResolveUser(javax.servlet.jsp.PageContext pageContext) {
if (pageContext == null) {
return null;
}
Object[] candidates = new Object[] {
pageContext.findAttribute("user"),
pageContext.findAttribute("utenteLogon")
};
for (int index = 0; index < candidates.length; index++) {
Object candidate = candidates[index];
if (candidate != null && faceAiUserId(candidate) > 0L) {
return candidate;
}
}
return null;
}
private Object faceAiResolveUserFromSession(javax.servlet.jsp.PageContext pageContext) {
if (pageContext == null || pageContext.getSession() == null) {
return null;
}
Object loginUserId = pageContext.getSession().getAttribute("loginUser_id");
long resolvedLoginUserId = 0L;
if (loginUserId instanceof Number) {
resolvedLoginUserId = ((Number) loginUserId).longValue();
} else if (loginUserId != null) {
try {
resolvedLoginUserId = Long.parseLong(String.valueOf(loginUserId));
} catch (NumberFormatException ignored) {
resolvedLoginUserId = 0L;
}
}
if (resolvedLoginUserId <= 0L) {
return null;
}
Object sessionUser = pageContext.findAttribute("utenteLogon");
if (sessionUser == null) {
return null;
}
if (faceAiUserId(sessionUser) == resolvedLoginUserId) {
return sessionUser;
}
try {
Method findByPrimaryKey = sessionUser.getClass().getMethod("findByPrimaryKey", long.class);
findByPrimaryKey.invoke(sessionUser, Long.valueOf(resolvedLoginUserId));
} catch (NoSuchMethodException missingPrimitiveOverload) {
try {
Method findByPrimaryKey = sessionUser.getClass().getMethod("findByPrimaryKey", Long.class);
findByPrimaryKey.invoke(sessionUser, new Long(resolvedLoginUserId));
} catch (Exception ignored) {
return null;
}
} catch (Exception ignored) {
return null;
}
return faceAiUserId(sessionUser) > 0L ? sessionUser : null;
}
%>
<%
String faceAiCookieName = faceAiCookieEnv("FACEAI_IDENTITY_COOKIE", "rus_faceai_identity");
String faceAiCookieSecret = faceAiCookieEnv("FACEAI_SHARED_SECRET", "disagio-spaghetti-science-lol-boh");
Object faceAiRequestUser = pageContext.findAttribute("user");
Object faceAiSessionUser = pageContext.findAttribute("utenteLogon");
long faceAiRequestUserId = faceAiUserId(faceAiRequestUser);
long faceAiSessionUserId = faceAiUserId(faceAiSessionUser);
Object faceAiCookieUser = faceAiRequestUserId > 0L ? faceAiRequestUser : (faceAiSessionUserId > 0L ? faceAiSessionUser : faceAiResolveUserFromSession(pageContext));
boolean faceAiSecureCookie = faceAiRequestIsSecure(request);
if (faceAiFeatureEnabled && faceAiCookieUser != null && faceAiUserId(faceAiCookieUser) > 0L) {
long faceAiExpiresAt = System.currentTimeMillis() + (30L * 60L * 1000L);
try {
String faceAiToken = faceAiIdentityToken(faceAiCookieUser, faceAiCookieSecret, faceAiExpiresAt);
faceAiWriteCookieHeader(response, faceAiCookieName, faceAiToken, 30 * 60, faceAiSecureCookie);
} catch (Exception faceAiIdentityError) {
faceAiWriteCookieHeader(response, faceAiCookieName, "", 0, faceAiSecureCookie);
log("Unable to mint FaceAI identity cookie", faceAiIdentityError);
}
} else {
faceAiWriteCookieHeader(response, faceAiCookieName, "", 0, faceAiSecureCookie);
}
%>