# Authentik Forward Authentication Configuration ## Overview All NPM-managed domains now use Authentik for centralized Single Sign-On (SSO) authentication. When users access any protected site, they are automatically redirected to Authentik for login, then returned to their original destination. ## Authentication Flow 1. **User accesses protected site** (e.g., https://portainer.schweitz.net) 2. **NPM checks authentication** via Authentik forward auth 3. **If not authenticated**: Redirect to https://auth.schweitz.net/outpost.goauthentik.io/start 4. **User logs in** with Google (via Authentik) 5. **Authentik sets session cookie** (8-hour validity) 6. **Redirect back** to originally requested URL 7. **Subsequent requests**: Automatically authenticated (no login required) ## Token & Session Configuration ### Token Validity - **Initial validity**: 8 hours (480 minutes) - **Activity-based extension**: Token stays active on use (rolling expiration) - **Idle timeout**: 8 hours after last activity - **Explicit logout**: Token invalidated immediately ### Session Behavior - **Single login** protects all domains under `*.schweitz.net` - **Cookie domain**: Shared across all sites - **Persistent**: Survives browser restarts (until expiration/logout) - **Secure**: HTTPS-only, HttpOnly flag set ## Protected Domains The following domains are protected with Authentik forward auth: 1. **192.168.86.149** - Direct IP access 2. **amp.schweitz.net** - AMP Server 3. **cloud.schweitz.net** - Nextcloud 4. **code.schweitz.net** - VS Code Server 5. **git.schweitz.net** - Gitea 6. **home.schweitz.net** - Home Assistant/Dashboard 7. **media.schweitz.net** - Media Server 8. **tatlock.schweitz.net** - Tatlock Services 9. **tower-of-joy** - Tower of Joy Services ### Unprotected Domains - **auth.schweitz.net** - Authentik itself (cannot protect the auth provider) ## User Management ### Adding Users 1. Go to https://auth.schweitz.net/if/admin/ 2. Navigate to **Directory** → **Users** 3. Click **Create** → **Create and enroll user** 4. Enter user details 5. Send enrollment invite (they'll set up Google OAuth) ### User Access Control Currently, **all authenticated users** can access protected sites. To restrict access: 1. Go to https://auth.schweitz.net/if/admin/#/core/applications 2. Select **NPM Forward Auth** application 3. Go to **Policy / Group / User Bindings** 4. Add specific users or groups ### Group-Based Access (Future) You can create groups and assign different access levels: - `admin` - Full access to all sites - `family` - Access to media, home - `developers` - Access to code, git ## Logout Users can log out at: https://auth.schweitz.net/if/user/#/settings Click **Sign Out** to invalidate the session across all protected sites. ## Technical Implementation ### Authentik Components 1. **Proxy Provider** (`npm-forward-auth-provider`) - Mode: `forward_single` - External Host: `https://auth.schweitz.net` - Token Validity: 480 minutes 2. **Application** (`NPM Forward Auth`) - Links provider to user interface - Accessible at: https://auth.schweitz.net 3. **Outpost** (`authentik Embedded Outpost`) - Handles authentication requests from NPM - Endpoint: `http://authentik-server:9000/outpost.goauthentik.io` ### NPM Configuration Each proxy host has advanced nginx configuration: ```nginx # Forward auth to Authentik auth_request /outpost.goauthentik.io/auth/nginx; # Preserve cookies auth_request_set $auth_cookie $upstream_http_set_cookie; add_header Set-Cookie $auth_cookie; # Extract user info auth_request_set $authentik_username $upstream_http_x_authentik_username; auth_request_set $authentik_groups $upstream_http_x_authentik_groups; auth_request_set $authentik_email $upstream_http_x_authentik_email; # Pass to backend proxy_set_header X-authentik-username $authentik_username; proxy_set_header X-authentik-email $authentik_email; # Redirect on auth failure error_page 401 = @authentik_proxy_signin; location @authentik_proxy_signin { return 302 /outpost.goauthentik.io/start?rd=$scheme://$http_host$request_uri; } # Auth endpoint location /outpost.goauthentik.io { proxy_pass http://authentik-server:9000/outpost.goauthentik.io; proxy_set_header X-Original-URL $scheme://$http_host$request_uri; proxy_pass_request_body off; } ``` ## Backend Application Integration Protected applications receive user information via headers: - `X-authentik-username` - Username - `X-authentik-email` - Email address - `X-authentik-groups` - Comma-separated groups - `X-authentik-name` - Full name - `X-authentik-uid` - Unique user ID Applications can use these headers for: - Displaying user info - Audit logging - Role-based access control - Personalization ## Troubleshooting ### User Can't Log In 1. **Check Authentik status**: `docker ps | grep authentik` 2. **Check Authentik logs**: `docker logs authentik-server` 3. **Verify Google OAuth**: - Go to https://auth.schweitz.net/if/admin/#/core/sources - Ensure Google source is enabled 4. **Check user exists**: - Go to https://auth.schweitz.net/if/admin/#/identity/users - Verify user account is active ### Redirect Loop If users get stuck in a redirect loop: 1. **Clear browser cookies** for `*.schweitz.net` 2. **Check NPM config**: Ensure `/outpost.goauthentik.io` location exists 3. **Restart NPM**: `docker restart npm` 4. **Check outpost**: Verify provider is assigned to outpost ### 502 Bad Gateway If auth requests fail: 1. **Check Authentik container**: `docker ps | grep authentik` 2. **Verify network**: Ensure NPM can reach `authentik-server:9000` 3. **Check NPM logs**: `docker logs npm` ### Session Expires Too Quickly If users are logged out unexpectedly: 1. **Check token validity**: Should be 480 minutes (8 hours) 2. **Verify rolling expiration**: Active use should extend session 3. **Check system time**: Ensure Docker host time is correct ## Automation ### Adding Forward Auth to New Sites When creating new proxy hosts via core-api: ```python from src.clients.npm_client import get_npm_client npm = get_npm_client() # Create proxy host proxy = await npm.create_proxy_host( domain_names=["newsite.schweitz.net"], forward_host="backend-container", forward_port=8080, ssl_enabled=True ) # Enable forward auth await npm.enable_authentik_forward_auth(proxy["id"]) ``` ### Bulk Enable/Disable To enable on all hosts: ```bash docker exec core-api /venv/bin/python /app/enable_npm_forward_auth.py ``` ## Security Considerations 1. **HTTPS Required**: Forward auth should only be used with HTTPS 2. **Secure Cookies**: HttpOnly and Secure flags prevent XSS/MITM 3. **Token Rotation**: Tokens are rotated on activity for security 4. **Audit Logging**: Authentik logs all authentication events 5. **MFA Support**: Can be enabled in Authentik for additional security ## Monitoring ### Check Authentication Status ```bash # Check Authentik health curl http://authentik-server:9000/-/health/live/ # Check active sessions (in Authentik admin) # https://auth.schweitz.net/if/admin/#/events/log ``` ### Monitor Failed Attempts Go to **System** → **Events** in Authentik admin to see: - Failed login attempts - Successful authentications - Token expirations - Policy violations ## Future Enhancements 1. **Per-Site Access Control**: Different user groups for different domains 2. **Multi-Factor Authentication**: SMS/TOTP for high-security sites 3. **Rate Limiting**: Prevent brute force attacks 4. **IP Whitelisting**: Allow certain IPs without auth 5. **API Key Support**: Service-to-service authentication ## Related Documentation - **Security Implementation Plan**: `security-implementation-plan.md` - **SSO Progress**: `SSO_IMPLEMENTATION_PROGRESS.md` - **OIDC Configuration**: `OIDC_CONFIGURATION.md` - **Authentik Docs**: https://docs.goauthentik.io/docs/providers/proxy/