Next mvp - Logging has Login, using identity-backend

 Great, I have now fully consumed both microservices.

Next, I'll outline how to implement robust, identity-backend-controlled authentication and login for your /logs endpoint.


Context Recap

  • identity-backend:

    • Issues/validates JWTs, but currently only supports service tokens (not user sessions/logins).

    • No UI, but could easily serve login pages or handle user credentials.

  • logging-backend:

    • Exposes /logs (and related endpoints) protected by JWT (validated locally using the shared secret, audience, and issuer).

    • No UI, currently expects Authorization header in every request.

    • No notion of "users"—only services with JWTs.


Your Goal

  • Make /logs a secure log viewer accessible only to authenticated users.

  • Delegate all authentication and login logic to identity-backend.

  • Enable identity-backend to serve a login page for any microservice, not just logging-backend.


1. Proposed Authentication Flow

A. Browser/User visits /logging-backend/logs:

  1. If JWT cookie is missing or invalid, redirect to /identity-backend/login?redirect_url=https://aurorahours.com/logging-backend/logs

  2. identity-backend serves a login page, authenticates user, issues JWT as a cookie (or as part of a redirect).

  3. User is redirected back to /logs with JWT included (cookie or URL param).

  4. logging-backend validates JWT as usual—if valid, serve logs.

B. Key features:

  • Centralizes all login and security logic in one place (identity-backend).

  • Supports extensibility: any service can use the identity-backend login page via redirect.

  • Keeps logging-backend stateless: just validates JWT.


2. Minimal Implementation Roadmap

A. identity-backend: Add User Login + Login UI

  • Implement /login endpoint (GET = serve login page, POST = process credentials).

  • On success, issue JWT (same format as service tokens, but with "sub" as username or user_id, audience as "logging-service").

  • Support redirect_url param so login flow can return to caller.

  • Set JWT as a secure, HTTP-only cookie, or as a URL param (your choice, but cookie is preferred for UX).

Example login flow:

  • User goes to /identity-backend/login?redirect_url=https://aurorahours.com/logging-backend/logs

  • After successful login, user is redirected to the original page, with JWT in a cookie.

B. logging-backend: Require User JWT for Log Viewer

  • For browser /logs endpoint, check for JWT in cookie (if present), else check Authorization header (for API/bots).

  • If no valid JWT, redirect to /identity-backend/login?...

  • Validate JWT as before (must have correct audience, issuer, not expired).


3. Your Next Steps

Step 1: Add User Login to identity-backend

  • Basic username/password (can be a static dict, SQLite, or a simple in-memory check for MVP).

  • Issue JWT with subject = username, audience = requested microservice.

Step 2: Implement /login page in identity-backend

  • Simple HTML form (GET = render form, POST = process login).

  • On success: issue JWT (as cookie), redirect to redirect_url param.

Step 3: Update logging-backend /logs to support JWT in Cookie

  • On page request, check for JWT in cookie (fallback to Authorization header for APIs).

  • If JWT missing/invalid: redirect to identity-backend login (with proper redirect_url).

Step 4: (Optional, but recommended)


Sample Sequence Diagram

User (browser) -> GET /logging-backend/logs
  -> [no JWT] -> redirect to /identity-backend/login?redirect_url=...
    -> [enters creds]
    -> [POST login] -> /identity-backend/login
      -> [success] -> Set JWT cookie, redirect back to /logging-backend/logs
User (browser) -> GET /logging-backend/logs (now with JWT)
  -> [JWT valid] -> Show logs

Recommended JWT Format (User Session)

{
  "iss": "identity-backend",
  "sub": "saad",          // user
  "aud": "logging-service",
  "iat": ...,
  "exp": ...
}

This matches your current token structure—only sub is now a username instead of a service.


4. Code Sample: identity-backend Login Route (MVP)

# In identity-backend/app.py
from flask import Flask, request, jsonify, redirect, render_template_string, make_response
import jwt, datetime

# Add a fake user for MVP
USERS = {"saad": "password123"}

@app.route("/login", methods=["GET", "POST"])
def login():
    redirect_url = request.args.get("redirect_url", "/")
    if request.method == "GET":
        # Serve simple HTML login form
        return render_template_string("""
        <form method="post">
            Username: <input name="username"><br>
            Password: <input name="password" type="password"><br>
            <input type="hidden" name="redirect_url" value="{{ redirect_url }}">
            <button type="submit">Login</button>
        </form>
        """, redirect_url=redirect_url)
    else:
        username = request.form["username"]
        password = request.form["password"]
        if USERS.get(username) != password:
            return "Login failed", 401
        now = datetime.datetime.utcnow()
        payload = {
            "iss": JWT_ISSUER,
            "sub": username,
            "aud": "logging-service",  # or make dynamic!
            "iat": now,
            "exp": now + datetime.timedelta(minutes=JWT_EXPIRATION_MINUTES)
        }
        token = jwt.encode(payload, JWT_SECRET_KEY, algorithm="HS256")
        resp = make_response(redirect(redirect_url))
        resp.set_cookie("jwt", token, httponly=True, secure=True)
        return resp

5. Code Sample: logging-backend JWT Handling (Browser)

from flask import request, redirect

def get_jwt():
    # Prefer JWT from cookie for browser, else Authorization header for API
    token = request.cookies.get("jwt")
    if not token:
        auth_header = request.headers.get("Authorization", "")
        if auth_header.startswith("Bearer "):
            token = auth_header.split(" ")[1]
    return token

@app.route("/logs", methods=["GET"])
def get_logs():
    token = get_jwt()
    if not token:
        # No token: redirect to login page
        login_url = f"https://aurorahours.com/identity-backend/login?redirect_url=https://aurorahours.com/logging-backend/logs"
        return redirect(login_url)
    # ...proceed to validate token as before

6. Summary Table

What Who serves it Auth logic UX for browser
Log viewer (/logs) logging-backend Checks JWT, redirects if absent Seamless SSO
Login page (/login) identity-backend Handles username/password Centralized, reusable

Ready for Implementation?

If you’re happy with this pattern, I can:

  • Write you the complete code for both changes, or

  • Walk you through how to build each step in your current repos.

Let me know how you want to proceed!
(Or if you want SPA support, OAuth, multi-microservice logins, etc.—just say the word.)

Comments

Popular posts from this blog

Feature: Audit log for one login, and identity service

Getting started - Build your data science lab environment

QA - Run #1 - Results