#include "common/OidcUserClaims.h" #include namespace visione::oidc { namespace { std::string claimString(const Json::Value &value, const char *primary, const char *secondary = nullptr) { const auto primaryValue = value.get(primary, ""); if (primaryValue.isString() && !primaryValue.asString().empty()) { return primaryValue.asString(); } if (secondary) { const auto secondaryValue = value.get(secondary, ""); if (secondaryValue.isString()) { return secondaryValue.asString(); } } return {}; } std::string trimFiscalPrefix(std::string value) { const std::string prefix = "TINIT-"; if (value.rfind(prefix, 0) == 0) { value.erase(0, prefix.size()); } std::transform(value.begin(), value.end(), value.begin(), [](unsigned char ch) { return static_cast(std::toupper(ch)); }); return value; } } // namespace std::optional normalizeIdTokenClaims( const std::string &issuer, const Json::Value &claims) { if (!claims.isObject()) { return std::nullopt; } const auto subject = claims.get("sub", "").asString(); const auto fiscal = trimFiscalPrefix( claims.get("fiscal_number", claims.get("https://attributes.eid.gov.it/fiscal_number", "")) .asString()); if (subject.empty() || fiscal.empty()) { return std::nullopt; } NormalizedUserClaims user; user.issuer = issuer; user.subject = subject; user.firstName = claims.get("given_name", "").asString(); user.lastName = claims.get("family_name", "").asString(); user.email = claims.get("email", "").asString(); user.fiscalCode = fiscal; user.rawClaims = claims; return user; } std::optional mergeUserClaims( const std::string &issuer, const Json::Value &idTokenClaims, const Json::Value &userinfoClaims) { if (!idTokenClaims.isObject() || !userinfoClaims.isObject()) { return std::nullopt; } Json::Value merged = idTokenClaims; for (const auto &name : userinfoClaims.getMemberNames()) { merged[name] = userinfoClaims[name]; } const auto subject = claimString(merged, "sub"); const auto fiscal = trimFiscalPrefix(claimString( merged, "fiscal_number", "https://attributes.eid.gov.it/fiscal_number")); if (subject.empty() || fiscal.empty()) { return std::nullopt; } NormalizedUserClaims user; user.issuer = issuer; user.subject = subject; user.firstName = claimString(merged, "given_name"); user.lastName = claimString(merged, "family_name"); user.email = claimString(merged, "email"); user.fiscalCode = fiscal; user.rawClaims = merged; return user; } } // namespace visione::oidc