solventum-image-metadata/templates/login.html
SamoilenkoVadym e9784d7da8 Phase 4 Complete: Authentication, Database, and Microsoft SSO
This commit implements a complete authentication system with local users,
session management, and Microsoft SSO support for enterprise environments.

New Files Created:
- src/database.py: SQLite database management with users, sessions, audit_log
- src/auth.py: Authentication module with login, SSO, and session management
- templates/login.html: Modern login page with SSO button

Database Schema:
- users table: username, password_hash, email, full_name, auth_method
- sessions table: session management with expiration
- audit_log table: user activity tracking
- Indexes for performance optimization

Authentication Features:
- Local authentication with test user (tester/oliveradmin)
- Password hashing with Werkzeug
- Session management with 24-hour expiration
- @login_required decorator for route protection
- Automatic session cleanup

Microsoft SSO Integration:
- MSAL library integration for Azure AD
- OAuth2 authorization code flow
- Microsoft Graph API user info retrieval
- Automatic user creation/update from SSO
- CSRF protection with state parameter
- Graceful fallback when SSO not configured

Security Improvements:
- All routes protected with @login_required
- Session-based authentication with database storage
- IP address and user agent logging
- Audit trail for user actions
- Secure session token generation

Configuration:
- Environment variables for Azure AD (AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID)
- SECRET_KEY for Flask session encryption
- Optional MSAL dependency (SSO works only if configured)

Dependencies Added:
- Werkzeug>=3.0.0 for password hashing
- msal>=1.20.0 for Microsoft SSO (optional)

Test Credentials:
- Username: tester
- Password: oliveradmin

Phase 4 Status: Complete
Next Phase: Phase 5 (Modern UI Overhaul) for v3.1 release

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-25 15:57:47 +00:00

239 lines
6.1 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login - Oliver Metadata Tool</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.login-container {
background: white;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
width: 100%;
max-width: 450px;
padding: 40px;
}
.logo {
text-align: center;
margin-bottom: 30px;
}
.logo h1 {
color: #667eea;
font-size: 28px;
margin-bottom: 10px;
}
.logo p {
color: #6c757d;
font-size: 14px;
}
.divider {
text-align: center;
margin: 30px 0;
position: relative;
}
.divider::before {
content: '';
position: absolute;
left: 0;
right: 0;
top: 50%;
height: 1px;
background: #dee2e6;
}
.divider span {
background: white;
padding: 0 15px;
color: #6c757d;
font-size: 13px;
position: relative;
z-index: 1;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
font-weight: 600;
color: #495057;
margin-bottom: 8px;
font-size: 14px;
}
.form-group input {
width: 100%;
padding: 12px;
border: 2px solid #dee2e6;
border-radius: 8px;
font-size: 14px;
transition: border-color 0.3s;
}
.form-group input:focus {
outline: none;
border-color: #667eea;
}
.btn {
width: 100%;
padding: 14px;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: transform 0.2s;
}
.btn:hover {
transform: translateY(-2px);
}
.btn-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
margin-bottom: 15px;
}
.btn-sso {
background: white;
color: #495057;
border: 2px solid #dee2e6;
}
.btn-sso:hover {
border-color: #667eea;
color: #667eea;
}
.alert {
padding: 12px;
border-radius: 8px;
margin-bottom: 20px;
font-size: 14px;
}
.alert-error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.alert-info {
background: #d1ecf1;
color: #0c5460;
border: 1px solid #bee5eb;
}
.test-user-info {
background: #f8f9ff;
border: 2px dashed #667eea;
border-radius: 8px;
padding: 15px;
margin-bottom: 20px;
font-size: 13px;
color: #495057;
}
.test-user-info strong {
color: #667eea;
}
.footer-text {
text-align: center;
margin-top: 20px;
font-size: 12px;
color: #6c757d;
}
.microsoft-icon {
display: inline-block;
margin-right: 8px;
}
</style>
</head>
<body>
<div class="login-container">
<div class="logo">
<h1>🎯 Oliver Metadata Tool</h1>
<p>Sign in to continue</p>
</div>
{% if error %}
<div class="alert alert-error">
⚠️ {{ error }}
</div>
{% endif %}
{% if info %}
<div class="alert alert-info">
{{ info }}
</div>
{% endif %}
<div class="test-user-info">
<strong>🧪 Test Account</strong><br>
Username: <code>tester</code><br>
Password: <code>oliveradmin</code>
</div>
<form method="POST" action="{{ url_for('login') }}">
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" name="username" required autofocus placeholder="Enter your username">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" required placeholder="Enter your password">
</div>
<button type="submit" class="btn btn-primary">
🔐 Sign In
</button>
</form>
{% if sso_enabled %}
<div class="divider">
<span>OR</span>
</div>
<a href="{{ url_for('login_microsoft') }}" style="text-decoration: none;">
<button type="button" class="btn btn-sso">
<span class="microsoft-icon">
<svg width="20" height="20" viewBox="0 0 23 23" style="vertical-align: middle;">
<path fill="#f25022" d="M1 1h10v10H1z"/>
<path fill="#00a4ef" d="M12 1h10v10H12z"/>
<path fill="#7fba00" d="M1 12h10v10H1z"/>
<path fill="#ffb900" d="M12 12h10v10H12z"/>
</svg>
</span>
Sign in with Microsoft
</button>
</a>
{% endif %}
<div class="footer-text">
Oliver Metadata Tool v3.1 | Enterprise Edition
</div>
</div>
</body>
</html>