π― Learning Objectives
By the end of today's session, you will be able to:
- Access all service endpoints and admin interfaces
- Check service health and status
- View and analyze container logs
- Debug common startup and connectivity issues
- Navigate monitoring dashboards
π Service Endpoints Directory
Here's your comprehensive guide to all EmpowerNow service endpoints:
π The Life of a Request
Let's follow Alice as she logs into EmpowerNow. Her browser sends a request, but what happens next? Understanding this flow is the key to debugging any issue you'll ever encounter in this platform.
When Alice clicks "Login", a carefully choreographed dance begins between services. Each service plays a specific role, and if any one of them stumbles, the whole flow breaks. Let's trace the journey step by step.
Why does this matter? When something goes wrong, knowing this flow helps you pinpoint exactly where the problem is. Is the BFF not reaching IdP? Is PDP returning DENY? Is Redis failing to store the session? Each symptom points to a specific part of this journey.
π§ͺ Try It: Follow a Request in Real-Time
Open your browser's Developer Tools (F12), go to the Network tab, then use this runner. Watch how each request flows through the system:
π Health Checks
All EmpowerNow services expose health endpoints. Test them interactively:
π§ͺ Try It: Check All Service Health
Click each button to verify the service is running and healthy:
BFF Gateway
Identity Provider (IdP)
Policy Decision Point (PDP)
Membership Service
Quick Health Check Script
# Quick health check for all services
$services = @(
"https://bff.self.empowernow.ai/health",
"https://idp.self.empowernow.ai/health",
"https://pdp.self.empowernow.ai/health",
"https://membership.self.empowernow.ai/health"
)
foreach ($url in $services) {
try {
$response = Invoke-WebRequest -Uri $url -TimeoutSec 5
Write-Host "β
$url - $($response.StatusCode)" -ForegroundColor Green
} catch {
Write-Host "β $url - FAILED" -ForegroundColor Red
}
}
π Become a Log Detective
It's Monday morning. Users are complaining they can't login. Your mission: find the culprit. Your weapon? The logs. Let's learn to read the clues.
Every request that flows through EmpowerNow leaves a trail. These logs are structured as JSON, making them both machine-readable and human-searchable. The key to becoming a great debugger is learning to follow these trails.
Understanding the Clues
Here's what a typical log entry looks like. Each field tells you something important:
The Golden Thread: Correlation ID
The correlation_id is your best friend. When a request enters the BFF, it gets assigned a unique ID
that follows it through every service it touches. If you have a failing request, grab its correlation ID
and you can trace its entire journey.
Key Events to Watch For
Not all log events are created equal. Here are the ones that usually point to problems:
bff_request_errorβ A request failed. Check theerrorfield for details.token_mint_errorβ Token issuance failed. Often means IdP can't reach its database.circuit_breaker_openedβ A service is failing repeatedly. Something is very wrong.upstream_timeoutβ A downstream service didn't respond in time.
Your Detective Toolkit
View All Logs
# All services (can be overwhelming)
docker compose logs
# Follow logs in real-time
docker compose logs -f
# Last 50 lines per service
docker compose logs --tail 50
Service-Specific Logs
# IdP service logs
docker compose logs -f idp
# BFF service logs
docker compose logs -f bff
# Multiple services
docker compose logs -f idp pdp bff
# Filter with grep
docker compose logs idp | grep ERROR
docker compose logs pdp | grep "policy evaluation"
Pro Detective Techniques
# Find all errors across all services
docker compose logs | grep '"level":"error"'
# Follow a specific correlation ID through the system
docker compose logs --tail 5000 | grep "abc-123-def"
# Watch for authentication failures in real-time
docker compose logs -f idp | grep -E "401|403|invalid"
# Find slow requests (look for high latency_ms values)
docker compose logs bff | grep "latency_ms" | grep -E "[0-9]{4,}"
π§ͺ Detective Exercise: Trace a Request
1. Run this health check and note the response headers
2. Look for X-Correlation-ID in the response
3. Use docker compose logs | grep "YOUR_CORRELATION_ID" to trace it
Use Dozzle for Better Logs
If you started the monitoring profile, access dozzle.self.empowernow.ai for a web-based log viewer with filtering and search. It's like having X-ray vision for your containers.
π§ When Things Go Wrong
Every developer has that moment: you start the services, but something isn't working. Don't panic. Let's walk through the most common issues you'll encounter, told as case studies from real debugging sessions.
Think of debugging as detective work. Each symptom is a clue, and your job is to follow the evidence to find the culprit. Here are the cases you're most likely to encounter.
The Symptom
You run docker compose ps and see the BFF container status showing "Restarting"
over and over. The health check never passes.
The Investigation
Check the BFF logs: docker compose logs bff --tail 50
You'll likely see: "Failed to load DCR secret" or "CSRF secret key required"
The Culprit
The BFF needs certain secrets to exist before it can start. These are typically created by bootstrap scripts that weren't run.
The Fix
Run the initialization script from the Deployment folder:
./scripts/create-idp-admin-jwt-secret.ps1
Then restart: docker compose restart bff
The Symptom
Users can login, but then see a spinning loader forever. The BFF logs show
"upstream_timeout" when calling PDP.
The Investigation
The timeout happens because PDP can't respond. Check why:
docker compose logs pdp --tail 50
Also check Neo4j: docker compose logs neo4j --tail 20
The Culprit
PDP depends on Neo4j for policy storage. If Neo4j isn't ready, PDP can't answer authorization queries. This creates a cascade: BFF waits for PDP, PDP waits for Neo4j.
The Fix
Wait for Neo4j to be fully healthy: docker compose ps neo4j
If it's stuck, restart it: docker compose restart neo4j
Then restart PDP: docker compose restart pdp
The Symptom
You call the token endpoint and get 401 Unauthorized with
"error": "invalid_client". Your client credentials worked yesterday!
The Investigation
First, verify the client exists by checking the discovery endpoint:
curl https://idp.../api/oidc/.well-known/openid-configuration
Then check if your token's kid matches what IdP publishes:
curl https://idp.../api/oidc/.well-known/jwks.json | jq '.keys[].kid'
The Culprit
Usually one of: (1) Client was deleted/recreated with new credentials, (2) TOKEN_KEY_ID config doesn't match the actual key, or (3) Database was reset.
The Fix
If the client is missing, re-register it via DCR (see the DCR section below).
If keys don't match, check TOKEN_KEY_ID in env/services/idp.env.
The Symptom
You navigate to https://idp.self.empowernow.ai and get
"This site can't be reached" or DNS errors.
The Investigation
Try pinging the hostname: ping idp.self.empowernow.ai
If it fails, the hostname isn't resolving.
The Culprit
These are local development domains that need to be in your hosts file. Without them, your browser doesn't know to look at localhost.
The Fix
Edit your hosts file and add the entries below. Windows: C:\Windows\System32\drivers\etc\hosts (open as Administrator). macOS/Linux: /etc/hosts (e.g. sudo nano /etc/hosts).
127.0.0.1 idp.self.empowernow.ai bff.self.empowernow.ai pdp.self.empowernow.ai
See Day 02 for the complete hosts file setup.
The Symptom
Users login successfully but are immediately logged out on the next request. Or sessions seem to "forget" they're authenticated.
The Investigation
Check Redis connectivity from BFF:
docker exec bff_app wget -qO- http://localhost:8000/health | jq '.checks.redis'
Also verify Redis is running: docker compose ps redis
The Culprit
BFF stores sessions in Redis. If Redis isn't reachable, sessions can't be stored or retrieved. This usually means Redis didn't start, or there's a network/password mismatch.
The Fix
Test Redis directly: docker exec redis redis-cli ping (should return PONG)
If that works, check REDIS_URL in BFF config matches the actual Redis host.
π οΈ Hands-on Labs
Theory is great, but nothing beats getting your hands dirty. These labs are designed to take you through real scenarios you'll encounter daily. Set aside about 30 minutes to work through them all.
Lab 1: The Complete Service Discovery Tour (10 minutes)
In this lab, you'll systematically explore every running service, understand what it does, and verify it's working correctly.
Step 1: Check What's Running
First, let's see the current state of your environment:
# See all containers and their status
docker compose ps
# Expected output should show services like:
# NAME STATUS PORTS
# bff_app Up (healthy) 0.0.0.0:8000->8000/tcp
# idp_app Up (healthy) 0.0.0.0:8002->8002/tcp
# pdp_app Up (healthy) 0.0.0.0:8001->8001/tcp
# ...
Self-Check
Count the services. Do you see at least 5 containers with "Up (healthy)" status? If any show "Restarting" or "Exit", that's a problem to investigate.
Step 2: Visit Each Service
Open each URL in your browser and note what you see:
- BFF Gateway -
https://bff.self.empowernow.ai/healthβ Should return JSON with "healthy" status - IdP -
https://idp.self.empowernow.ai/api/oidc/.well-known/openid-configurationβ Should return OIDC discovery document - PDP -
https://pdp.self.empowernow.ai/healthβ Should return health status - IdP Admin UI -
https://authn.self.empowernow.aiβ Should show login page
π§ͺ Try It: Explore the OIDC Discovery Document
This document tells clients everything they need to know about the IdP. Look for
token_endpoint, authorization_endpoint, and scopes_supported:
Self-Check Questions
From the discovery document, can you answer:
- What is the token endpoint URL?
- What scopes are supported?
- What grant types can you use?
- Where do you find the public keys (JWKS)?
Lab 2: The Authentication Flow (10 minutes)
Now let's actually authenticate. You'll get a token, decode it, and understand what's inside.
Step 1: Get an Access Token
Use client credentials to get a token (this simulates a backend service authenticating):
π§ͺ Get Your Token
Click Send and copy the access_token from the response. You'll need it for the next steps.
Step 2: Decode the Token
JWTs are base64-encoded. Let's see what's inside. Copy your token and paste it at jwt.io, or use this PowerShell command:
# Replace YOUR_TOKEN with the access_token you received
$token = "YOUR_TOKEN"
# Split the token and decode the payload (middle part)
$parts = $token.Split('.')
$payload = $parts[1]
# Add padding if needed and decode
$padding = 4 - ($payload.Length % 4)
if ($padding -lt 4) { $payload += "=" * $padding }
[System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($payload)) | ConvertFrom-Json | ConvertTo-Json
# You should see claims like: sub, aud, scope, iss, exp, iat
Self-Check Questions
Looking at your decoded token:
- What is the
iss(issuer)? Does it match the IdP URL? - What scopes were granted in the
scopeclaim? - When does the token expire? (Check
exp- it's a Unix timestamp) - What is the
sub(subject)? This identifies who the token represents.
Step 3: Use the Token for Authorization
Now let's check if this token's subject has permission to do something. We'll ask the PDP if "alice" can read a document:
π§ͺ Check Authorization with PDP
This is an AuthZEN evaluation request. The response will be PERMIT or DENY:
Try modifying the request: change the action to "delete" or the resource type to "admin-panel". Does the decision change? Understanding these patterns is key to working with the PDP.
Lab 3: The Log Investigation Challenge (10 minutes)
This lab simulates a real debugging scenario. You'll generate traffic, find it in the logs, and trace a request through the system.
Step 1: Set Up Your Terminals
Open two terminal windows:
- Terminal 1: For watching logs
- Terminal 2: For running commands
Step 2: Start Watching Logs
In Terminal 1, start following the BFF logs:
# Watch BFF logs in real-time
docker compose logs -f bff
# You'll see logs streaming as requests come in
# Look for entries with "correlation_id" - that's your tracking number
Step 3: Generate Traffic
In Terminal 2, make a request and note the correlation ID:
# Make a health check request (returns headers including correlation ID)
curl -v https://bff.self.empowernow.ai/health 2>&1 | Select-String "correlation|x-request"
# Or use PowerShell to capture headers
$response = Invoke-WebRequest -Uri "https://bff.self.empowernow.ai/health" -Headers @{Accept="application/json"}
$response.Headers
# Note the X-Correlation-ID value (something like "abc123-def456-...")
Step 4: Find Your Request in the Logs
Now use the correlation ID to find your specific request in the logs:
# Replace YOUR_CORRELATION_ID with the actual value
docker compose logs --tail 500 | Select-String "YOUR_CORRELATION_ID"
# You should see multiple log entries - one for request start, one for completion
# If your request touched IdP or PDP, you'd see it there too
Challenge: Find an Error
Now intentionally cause an error and find it in the logs:
- Make a request to a non-existent endpoint:
curl https://bff.self.empowernow.ai/does-not-exist - Find the 404 in the logs using:
docker compose logs bff | Select-String "404" - Can you find the correlation ID for the failed request?
Lab 4: The Container Deep Dive (5 minutes)
Sometimes logs aren't enough. Let's go inside a container and explore.
Step 1: Enter the Container
# Get a shell inside the BFF container
docker exec -it bff_app /bin/sh
# You're now INSIDE the container. The prompt changes to show you're in a different environment.
Step 2: Explore the Environment
Inside the container, run these commands and observe the output:
# Where is the application code?
ls -la /app
# What secrets are mounted?
ls -la /run/secrets/
# What environment variables are set? (Look for IdP, Redis URLs)
printenv | grep -i "idp\|redis\|bff" | sort
# Can we reach the IdP from here?
wget -qO- http://idp-app:8002/health
# Check network resolution
cat /etc/hosts
cat /etc/resolv.conf
# Exit the container when done
exit
Self-Check
After exploring, can you answer:
- What's the BFF's internal Redis URL?
- How many secret files are mounted?
- What Python version is running? (hint:
python --version) - Can you curl the PDP from inside the BFF container?
Lab 5: Build Your Own Health Dashboard (Bonus - 5 minutes)
Let's create a simple script that checks all services at once β a tool you'll use regularly.
# Save this as health-check.ps1 in your Deployment folder
$services = @{
"BFF" = "https://bff.self.empowernow.ai/health"
"IdP" = "https://idp.self.empowernow.ai/health"
"PDP" = "https://pdp.self.empowernow.ai/health"
"Membership" = "https://membership.self.empowernow.ai/health"
}
Write-Host "`n===== EmpowerNow Health Check =====" -ForegroundColor Cyan
Write-Host "Time: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')`n"
foreach ($service in $services.GetEnumerator()) {
try {
$response = Invoke-WebRequest -Uri $service.Value -TimeoutSec 5 -ErrorAction Stop
$status = ($response.Content | ConvertFrom-Json).status
if ($status -eq "healthy") {
Write-Host "β
$($service.Key)" -ForegroundColor Green -NoNewline
Write-Host " - healthy" -ForegroundColor DarkGray
} else {
Write-Host "β οΈ $($service.Key)" -ForegroundColor Yellow -NoNewline
Write-Host " - $status" -ForegroundColor DarkGray
}
} catch {
Write-Host "β $($service.Key)" -ForegroundColor Red -NoNewline
Write-Host " - FAILED: $($_.Exception.Message)" -ForegroundColor DarkGray
}
}
Write-Host "`n===================================`n"
Save the script and run it:
# Run the health check
.\health-check.ps1
# Run it in a loop every 10 seconds (Ctrl+C to stop)
while ($true) { .\health-check.ps1; Start-Sleep 10 }
Lab Complete!
You've now explored services, decoded tokens, traced logs, inspected containers, and built a monitoring tool. These are the core skills you'll use every day when working with EmpowerNow.
π Your First Metrics Journey
Numbers tell stories. Every request, every error, every millisecond of latency is recorded. Let's learn to read these stories and understand what your services are really doing.
EmpowerNow services expose metrics in Prometheus format. These metrics are scraped by Prometheus and visualized in Grafana. Here's how the data flows:
What Metrics Tell You
Metrics answer questions you didn't know you had:
- How many requests per second? β Is traffic normal or is something hammering your service?
- What's the error rate? β Are 5xx errors creeping up?
- How fast are responses? β Is latency within acceptable bounds?
- Are resources exhausted? β CPU, memory, connection pools?
π§ͺ Try It: See Raw Metrics
This is what Prometheus scrapes every 15 seconds. Look for http_requests_total
and http_request_duration_seconds:
Your First Prometheus Query
Once you're in Prometheus (at prometheus.self.empowernow.ai), try these queries
to understand what's happening:
# How many requests in the last 5 minutes?
increase(http_requests_total[5m])
# Request rate per second
rate(http_requests_total[5m])
# Only error responses (5xx status codes)
rate(http_requests_total{status=~"5.."}[5m])
# 95th percentile response time
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
Navigating Grafana
Grafana turns these raw numbers into beautiful, actionable dashboards. Here's your quick-start guide:
- First login: Navigate to
grafana.self.empowernow.ai, login withadmin/admin - Find dashboards: Click the hamburger menu β Dashboards β Browse
- Look for: "BFF Overview", "IdP Metrics", "PDP Performance"
- Time range: Use the time picker (top-right) to zoom in on incidents
The Golden Signals
When looking at dashboards, focus on: Latency (how fast), Traffic (how much), Errors (how often things fail), and Saturation (how full your resources are). These four tell you almost everything you need to know.
π³ Inside the Container
Sometimes you need to go inside to understand what's happening. Let's explore the container filesystem like archaeologists examining an ancient temple.
Containers are isolated environments, but you can shell into them to poke around. This is invaluable when logs aren't telling the whole story.
Application Code"] secrets["/run/secrets
Mounted Secrets"] logs["/logs
Log Files"] tmp["/tmp
Temp Files"] end subgraph host [Host Machine] configsecrets["config_secrets/"] envfiles["env/services/bff.env"] end configsecrets -.->|"mounted as files"| secrets envfiles -.->|"loaded as env vars"| app
Getting a Shell
# Get an interactive shell in BFF
docker exec -it bff_app /bin/sh
# Once inside, explore:
ls -la /app # Application code
ls -la /run/secrets # Mounted secrets (filenames only!)
printenv | grep -i idp # Environment variables
cat /etc/hosts # Container's hosts file
Network Debugging from Inside
Containers have their own network namespace. Sometimes the issue is that one container can't reach another. Here's how to test:
# From BFF, can we reach IdP?
docker exec bff_app wget -qO- http://idp-app:8002/health
# Can we reach the database?
docker exec bff_app nc -zv postgres 5432
# What DNS names are available?
docker exec bff_app cat /etc/resolv.conf
# List all containers on the network
docker network inspect empowernow_default | jq '.[0].Containers'
Resource Inspection
Is a container eating all your memory? Is CPU maxed out? Here's how to check:
# Live resource usage (like top for containers)
docker stats --no-stream
# Detailed container state
docker inspect bff_app | jq '.[0].State'
# Check if container is resource-limited
docker inspect bff_app | jq '.[0].HostConfig.Memory'
# View container's process list
docker exec bff_app ps aux
π§ͺ Exploration Exercise: Find the Secrets
Try this sequence to explore inside a container:
- Shell into BFF:
docker exec -it bff_app /bin/sh - List the secrets directory:
ls -la /run/secrets/ - Check an environment variable:
echo $BFF_COOKIE_DOMAIN - Test network to IdP:
wget -qO- http://idp-app:8002/health - Exit the container:
exit
π Advanced Topics
Data Collector (DC UI)
The Data Collector is a key component for inventory collection and data integration.
Its UI is delivered as an Experience platform plugin (experience/plugins/dc-ui/),
accessible alongside IT Shop, My Identity, and other modules. Day 26 covers DataCollector concepts; day 27 covers the DC-UI in depth.
What is Data Collector?
The Data Collector service discovers and inventories systems, users, and resources across your enterprise. It connects to various sources (AD, databases, cloud services) to build a comprehensive view of your environment.
Starting the Data Collector Profile
# Start Data Collector with core services
docker compose --profile core --profile datacollector up -d
# View Data Collector services
docker compose ps | Select-String "datacollector|dc-"
Data Collector Services
Core data collection engine - connects to external systems
Administrative UI for configuring collection jobs and viewing inventory
Database migrations for Data Collector schema
DC-UI is an Experience platform plugin
The Data Collector UI is loaded as a plugin under the Experience platform β typically reachable at /dc-ui/ through the Experience shell. Day 16 walks through the basics; days 27β28 are the full reference.
Your App Needs an Identity: Client Registration
Every application that talks to EmpowerNow needs an identity β a client ID and credentials. Think of it like getting a passport. Without one, your app can't authenticate, can't get tokens, can't do anything. Let's walk through the registration process.
Dynamic Client Registration (DCR) lets you create OAuth clients programmatically. This is how CI/CD pipelines, AI agents, and new services get their credentials automatically, without someone manually clicking through an admin UI.
The Client Lifecycle
A client goes through several stages from creation to retirement:
Client Profiles
Not all clients are created equal. Choose the right profile for your use case:
Step-by-Step: Register Your First Client
Let's walk through registering a confidential client for a backend service:
π§ͺ Step 1: Register the Client
This creates a new OAuth client. Save the client_id and client_secret from the response!
π§ͺ Step 2: Get a Token with Your Client
Now use your new client credentials to get an access token. Replace the Authorization header
with your actual credentials (base64 encoded client_id:client_secret):
Managing Your Clients
Once registered, you can manage your clients via the same endpoint:
# View your client configuration
curl https://idp.../api/oidc/register/YOUR_CLIENT_ID \
-H "Authorization: Bearer YOUR_REGISTRATION_TOKEN"
# Update client settings
curl -X PUT https://idp.../api/oidc/register/YOUR_CLIENT_ID \
-H "Authorization: Bearer YOUR_REGISTRATION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"client_name": "Updated Name"}'
# Delete the client (revoke all tokens)
curl -X DELETE https://idp.../api/oidc/register/YOUR_CLIENT_ID \
-H "Authorization: Bearer YOUR_REGISTRATION_TOKEN"
Want to Go Deeper?
For advanced DCR behavior, secret handling, and compliance-oriented detail, use the official EmpowerNow documentation and your support channel rather than internal deep-dive bundles.
Quick Reference: Client Types
| Client Type | Use Case | Secret Required | Example |
|---|---|---|---|
public |
SPAs, mobile apps | β No | React/Angular frontend |
confidential |
Backend services | β Yes | BFF, microservices |
Agent Registration (A2A)
AI agents use a special client profile for registration:
# Agent-specific DCR request
POST /api/oidc/register
{
"client_profile": "agent-app",
"client_name": "Invoice Processing Agent",
"jwks_uri": "https://agent.empowerid.com/.well-known/jwks.json",
"custom_metadata": {
"agent": {
"class": "llm-assistant",
"capabilities": ["invoice:read", "invoice:approve"]
}
}
}
# Agent ARN format: auth:agent:{tenant}:{client_id}
# Example: auth:agent:acme-corp:invoice-agent
Preview: Agent Lifecycle v2.0
In Week 5, Day 23, you'll learn about vault-backed agent credentials where secrets are never exposed in plaintext. The Bootstrap API uses Initial Access Tokens (IATs), stores credentials in Vault, and supports multi-IdP registration (Auth0, Entra ID, Salesforce).
OAuth Clients Database Schema
Understanding how clients are stored helps with debugging:
-- Core table (hot path - token endpoint reads this)
CREATE TABLE idp.oauth_clients (
client_id TEXT PRIMARY KEY,
client_name TEXT NOT NULL,
client_type TEXT CHECK (client_type IN ('public', 'confidential')),
secret_hash TEXT,
redirect_uris TEXT[] DEFAULT '{}',
grant_types TEXT[] DEFAULT '{authorization_code}',
scopes TEXT[] DEFAULT '{openid}',
fapi_profile TEXT DEFAULT 'none',
token_endpoint_auth TEXT DEFAULT 'client_secret_basic'
);
-- Extension table (config, metadata - not on hot path)
CREATE TABLE idp.oauth_client_ext (
client_id TEXT PRIMARY KEY REFERENCES idp.oauth_clients,
config JSONB DEFAULT '{}', -- TTLs, feature flags
metadata JSONB DEFAULT '{}' -- UI prefs, contact info
);
BFF Registration Script
The BFF service needs to be registered with IdP on first startup. If BFF is failing to authenticate, run the script from ServiceConfigs/Deployment to create the admin JWT secret used for BFF Dynamic Client Registration (DCR):
# Windows (PowerShell):
.\scripts\create-idp-admin-jwt-secret.ps1
# Mac/Linux:
./scripts/create-idp-admin-jwt-secret.sh
π Knowledge Check
Before moving on to Week 2, let's make sure you've absorbed the key concepts. Try to answer these questions without looking back. If you get stuck, revisit the relevant section.
Service Architecture
Question 1: The BFF's Role
What does the BFF (Backend-for-Frontend) do? Why do browsers talk to the BFF instead of directly to IdP or PDP?
Show Answer
The BFF acts as a gateway and authentication proxy. Browsers can't securely store client secrets, so the BFF handles OAuth flows, stores sessions in Redis, and proxies API requests. It also handles CSRF protection and adds security headers.
Question 2: Request Flow
When a user clicks "Login," what's the sequence of services involved? (Hint: Think about the flow diagram)
Show Answer
Browser β BFF (initiates OAuth) β IdP (authentication) β BFF (receives code, exchanges for tokens) β Redis (stores session) β PDP (checks permissions) β BFF β Browser (welcome message)
Debugging Skills
Question 3: The Correlation ID
What is a correlation ID and why is it important for debugging?
Show Answer
A correlation ID is a unique identifier assigned to a request when it enters the system. It's passed through every service the request touches, appearing in all related log entries. This lets you trace a single request's journey through multiple services and find exactly where something went wrong.
Question 4: Container in Restart Loop
The BFF container keeps restarting. What are the first two things you should check?
Show Answer
1. Check the logs: docker compose logs bff --tail 50 β look for error messages about
missing secrets or configuration.
2. Check if secrets exist: ls config_secrets/ β the BFF needs certain secrets to start.
Run the initialization scripts if they're missing.
Authentication & Authorization
Question 5: JWT Structure
A JWT has three parts. What are they and what does each contain?
Show Answer
1. Header - Contains the algorithm (e.g., RS256) and token type (JWT)
2. Payload - Contains claims: sub (subject), iss (issuer), exp (expiration), scope, etc.
3. Signature - Cryptographic signature to verify the token wasn't tampered with
Question 6: IdP vs PDP
What's the difference between what IdP does and what PDP does?
Show Answer
IdP (Identity Provider) handles authentication β "Who are you?"
It verifies credentials and issues tokens.
PDP (Policy Decision Point) handles authorization β "What can you do?"
It evaluates policies and returns PERMIT/DENY decisions.
Practical Commands
Question 7: Essential Commands
Without looking, write the commands to:
- Check which containers are running
- View the last 100 lines of IdP logs
- Get a shell inside the BFF container
Show Answer
docker compose ps
docker compose logs --tail 100 idp
docker exec -it bff_app /bin/sh
How Did You Do?
6-7 correct without hints: Excellent! You're ready for Week 2.
4-5 correct: Good foundation. Review the sections you struggled with.
Less than 4: Consider re-reading Day 5 and re-doing the labs before moving on.
π Week 1 Complete!
Week 1 Recap: Foundations & Environment
Congratulations!
You've completed Week 1! You now have a solid foundation in the EmpowerNow platform architecture, development environment, and operational knowledge.
What You Learned This Week:
- β EmpowerNow architecture and service responsibilities
- β Setting up a complete development environment
- β Docker Compose profiles for efficient development
- β Configuration management and secrets handling
- β Service exploration, health checks, and debugging
- β Data Collector (DC UI) for inventory management
- β Dynamic Client Registration (DCR) for OAuth clients
Next Week Preview: Core Services Deep Dive
In Week 2, you'll dive deep into the authentication and authorization services:
- Day 6-7: IdP deep dive - OIDC, OAuth2, token flows
- Day 8-9: PDP deep dive - AuthZEN, policies, evaluation
- Day 10: Membership service and Neo4j