diff --git a/services/analytics-python-service/main.py b/services/analytics-python-service/main.py index f8128a6..e529c4c 100644 --- a/services/analytics-python-service/main.py +++ b/services/analytics-python-service/main.py @@ -94,7 +94,7 @@ def custom_openapi(): try: engine = create_engine(DATABASE_URL) except Exception as e: - print(f"Error creating engine: {e}") + logger.error("analytics.engine_creation_failed", extra={"error": str(e)}) engine = None api_key = os.environ.get("OPENAI_API_KEY") diff --git a/services/auth-service/index.js b/services/auth-service/index.js index fd6afeb..82db4da 100644 --- a/services/auth-service/index.js +++ b/services/auth-service/index.js @@ -1396,6 +1396,35 @@ app.post('/saml/acs', createUserRateLimiter('saml_acs', 20), async (req, res) => if (!signatureVerified) { return res.status(401).json({ message: 'SAML signature verification failed' }); } + + const conditions = doc.getElementsByTagNameNS + ? doc.getElementsByTagNameNS('urn:oasis:names:tc:SAML:2.0:assertion', 'Conditions') + : doc.getElementsByTagName('Conditions'); + + if (conditions.length > 0) { + const condition = conditions[0]; + const notBefore = condition.getAttribute('NotBefore'); + const notOnOrAfter = condition.getAttribute('NotOnOrAfter'); + const now = new Date(); + + if (notBefore && now < new Date(notBefore)) { + return res.status(401).json({ message: 'SAML assertion is not yet valid (NotBefore)' }); + } + + if (notOnOrAfter && now >= new Date(notOnOrAfter)) { + return res.status(401).json({ message: 'SAML assertion has expired (NotOnOrAfter)' }); + } + + const audienceNodes = doc.getElementsByTagNameNS + ? doc.getElementsByTagNameNS('urn:oasis:names:tc:SAML:2.0:assertion', 'Audience') + : doc.getElementsByTagName('Audience'); + + for (let i = 0; i < audienceNodes.length; i++) { + if (audienceNodes[i].textContent === SAML_IDP_ENTITY_ID) { + break; + } + } + } } const nameIdMatch = decodedXml.match(/]*>([^<]+)<\/saml2:NameID>/);