Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Look up users by their email addresses to retrieve usernames or subject identifi
- `lfx.auth-service.email_to_username` - Look up username by email
- `lfx.auth-service.email_to_sub` - Look up subject identifier by email

**[View Email Lookup Documentation](docs/email_lookups.md)**
**[View Email Lookup Documentation](docs/subjects/email_lookups.md)**

---

Expand All @@ -77,7 +77,7 @@ Retrieve and update user profile metadata using various input types (JWT tokens,
- `lfx.auth-service.user_metadata.read` - Retrieve user metadata
- `lfx.auth-service.user_metadata.update` - Update user profile

**[View User Metadata Documentation](docs/user_metadata.md)**
**[View User Metadata Documentation](docs/subjects/user_metadata.md)**

---

Expand All @@ -87,7 +87,7 @@ Retrieve user email addresses (primary and alternate emails) using various input
**Subjects:**
- `lfx.auth-service.user_emails.read` - Retrieve user email addresses

**[View User Emails Documentation](docs/user_emails.md)** - **Note:** Currently only supported for Authelia
**[View User Emails Documentation](docs/subjects/user_emails.md)** - **Note:** Currently only supported for Authelia

---

Expand All @@ -98,7 +98,7 @@ Two-step verification flow for verifying ownership of alternate email addresses.
- `lfx.auth-service.email_linking.send_verification` - Send OTP to email
- `lfx.auth-service.email_linking.verify` - Verify email with OTP

**[View Email Verification Documentation](docs/email_verification.md)** - Includes complete flow diagram
**[View Email Verification Documentation](docs/subjects/email_verification.md)** - Includes complete flow diagram

---

Expand All @@ -108,7 +108,7 @@ Link verified identities (such as verified email addresses) to user accounts.
**Subjects:**
- `lfx.auth-service.user_identity.link` - Link verified identity to user

**[View Identity Linking Documentation](docs/identity_linking.md)**
**[View Identity Linking Documentation](docs/subjects/identity_linking.md)**

---

Expand Down
34 changes: 34 additions & 0 deletions docs/auth-flows/A-auth-service-m2m-profile-lookup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Flow A: Auth Service M2M Sequence Diagram

## Description
Auth Service M2M for reading profiles and checking email->username mappings.

## Sequence Diagram

```mermaid
sequenceDiagram
participant SSR as LFX One SSR
participant NATS as NATS
participant AuthSvc as Auth Service
participant Auth0 as Auth0 Authentication API

Note over SSR,Auth0: Flow A: Auth Service M2M for reading profiles,<br/>checking email->username mappings

SSR->>NATS: Request email mapping/<br/>profile information
Note over NATS,AuthSvc: Auth Service subscribed to NATS subject
NATS->>AuthSvc: Deliver request

Note over AuthSvc: Auth Service uses cached token<br/>or requests new one if expired

alt Token not in cache or expired
AuthSvc->>Auth0: A1: POST /oauth2/token<br/>[client_credentials grant]<br/>w/ Auth Service M2M client credentials<br/>aud=auth0_mgmt

Auth0-->>AuthSvc: A2: access_token_m2m_read<br/>(read:users)<br/>*NOT update:users*
end

AuthSvc->>Auth0: A3: Check emails,<br/>read profiles using<br/>access_token_m2m_read

Auth0-->>AuthSvc: User profile data
AuthSvc->>NATS: Publish response
NATS->>SSR: Deliver response
```
40 changes: 40 additions & 0 deletions docs/auth-flows/B-lfx-one-login-ssr-oidc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Flow B: LFX One Login SSR OIDC Sequence Diagram

## Description
LFX One login using SSR (server-side rendering) with privileged OIDC flow. This flow authenticates the user and obtains access tokens for the LFX v2 API (Traefik/Heimdall).

## Sequence Diagram

```mermaid
sequenceDiagram
participant User as User Browser
participant SSR as LFX One SSR
participant Auth0 as Auth0 Authentication API
participant LFXv2 as LFX v2 API<br/>(Traefik/Heimdall)

Note over User,LFXv2: Flow B: LFX One login - SSR [privileged] OIDC,<br/>with LFX v2 API audience

User->>SSR: Initiate login

SSR->>Auth0: B1: GET /authorize<br/>w/ "LFX One" client<br/>response_type=code<br/>aud=lfxv2<br/>redirect_uri=SSR_callback

Auth0->>User: Present login page/<br/>authentication challenge

User->>Auth0: Enter credentials/<br/>authenticate

Auth0->>SSR: B2: Redirect with auth_code

SSR->>Auth0: B3: POST /oauth2/token<br/>[authorization_code grant]<br/>w/ "LFX One" client credentials<br/>+ auth_code<br/>aud=lfxv2

Auth0-->>SSR: B4: id_token_user + access_token_lfxv2<br/>(for LFX v2 API audience)

Note over SSR: SSR stores tokens in session

SSR->>LFXv2: B5: API request with<br/>access_token_lfxv2

LFXv2-->>SSR: API response

SSR-->>User: Render authenticated page

Note over User,LFXv2: access_token_lfxv2 is used for all LFX v2 API calls
```
49 changes: 49 additions & 0 deletions docs/auth-flows/C-profile-update.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Flow C: Self-Service Profile Update via Regular Web Client

## Description
Flow for the Auth0 Management API audience, allowing users to manage their own profiles ("self" Auth0 access). This flow uses the LFX One Profile Client (regular web application) and implements a dual authentication pattern where users first authenticate with the main LFX One client, then obtain additional access tokens for Management API access.

## Sequence Diagram

```mermaid
sequenceDiagram
participant User as User Browser
participant SSR as LFX One SSR
participant NATS as NATS
participant AuthSvc as Auth Service
participant Auth0 as Auth0 Authentication API
participant Auth0Mgmt as Auth0 Management API

Note over User,Auth0Mgmt: Flow C: Secondary authentication flow for Management API audience<br/>("self" Auth0 access)

User->>SSR: Request to update own profile

SSR->>Auth0: C1: GET /authorize<br/>w/ "LFX One Profile" client<br/>response_type=code<br/>aud=auth0_mgmt<br/>redirect_uri=SSR_callback

Auth0->>User: Present consent/authentication<br/>(if needed)

User->>Auth0: Grant consent/authenticate

Auth0->>SSR: C2: Redirect with auth_code

SSR->>Auth0: C3: POST /oauth2/token<br/>[authorization_code grant]<br/>w/ "LFX One Profile" client credentials<br/>+ auth_code<br/>aud=auth0_mgmt

Auth0-->>SSR: C4: id_token_mgmt (IGNORE) +<br/>access_token_mgmt_self

SSR->>SSR: C5: Validate that<br/>id_token_user (from Flow B).sub<br/>== access_token_mgmt_self.sub

SSR->>NATS: C6: Publish update request<br/>with access_token_mgmt_self
Note over NATS,AuthSvc: Auth Service subscribed to NATS subject
NATS->>AuthSvc: Deliver request

AuthSvc->>Auth0Mgmt: Update user profile<br/>using access_token_mgmt_self<br/>(user can only update self)

Auth0Mgmt-->>AuthSvc: Updated profile data
AuthSvc->>NATS: Publish response
NATS->>SSR: Deliver response

SSR-->>User: Render success/updated page

Note over User,Auth0Mgmt: Auth Service abstracts all Auth0 Management API calls
```

52 changes: 52 additions & 0 deletions docs/auth-flows/D-social-identity-linking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Flow D: Link Social Identity via Regular Web Client (No Audience)

## Description
Regular web client flow for linking social identities by authenticating with the social provider. Uses the LFX One Profile Client and access_token_mgmt_self from Flow C (Management API token) to perform the actual linking operation. This flow uses server-side redirects instead of popup/webmessage pattern.

## Sequence Diagram

```mermaid
sequenceDiagram
participant Browser as User Browser
participant SSR as LFX One SSR
participant Auth0 as Auth0 Authentication API
participant NATS as NATS
participant AuthSvc as Auth Service
participant Auth0Mgmt as Auth0 Management API

Note over Browser,Auth0Mgmt: Flow D: Link social identity via regular web client<br/>(no audience - just authenticate with social provider)

Browser->>SSR: User clicks "Link Google"<br/>(or other social provider)

SSR->>Auth0: D1: GET /authorize<br/>w/ "LFX One Profile" client<br/>response_type=code<br/>[NO audience]<br/>connection=google-oauth2<br/>redirect_uri=SSR_callback

Auth0->>Browser: Present social provider<br/>authentication

Browser->>Auth0: User authenticates with<br/>social provider

Auth0->>SSR: D2: Redirect with auth_code

SSR->>Auth0: D3: POST /oauth2/token<br/>[authorization_code grant]<br/>w/ "LFX One Profile" client credentials<br/>+ auth_code<br/>[NO audience]

Auth0-->>SSR: D4: access_token_social<br/>for /userinfo (IGNORE) +<br/>id_token_social

alt id_token_social sub starts with "auth0|" (database user, not a social identity)
SSR-->>Browser: Error: cannot link two LFID accounts
else id_token_social sub is a social identity (e.g. google-oauth2|, github|)
Note over SSR: SSR uses<br/>access_token_mgmt_self from Flow C<br/>(Management API token)

SSR->>NATS: D5: Publish link request<br/>with access_token_mgmt_self + id_token_social
Note over NATS,AuthSvc: Auth Service subscribed to NATS subject
NATS->>AuthSvc: Deliver request

AuthSvc->>Auth0Mgmt: Link social identity<br/>using access_token_mgmt_self<br/>w/ id_token_social claims

Auth0Mgmt-->>AuthSvc: Identity linked successfully
AuthSvc->>NATS: Publish response
NATS->>SSR: Deliver response

SSR-->>Browser: Update UI with<br/>newly linked identity
end

Note over Browser,Auth0Mgmt: Auth Service abstracts all Auth0 Management API calls
```
59 changes: 59 additions & 0 deletions docs/auth-flows/E-passwordless-email-linking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Flow E: Link Email Identity via Passwordless

## Description
SSR flow for linking additional email addresses to a user's account using passwordless authentication. Uses the LFX One Profile Client for the passwordless OTP flow. All Auth0 API calls (both passwordless and Management API) are made by Auth Service, with SSR communicating via NATS pub/sub pattern. Uses access_token_mgmt_self from Flow C (Management API token) to perform the actual linking operation. The user verifies ownership of the email by entering a one-time verification code in LFX One.

## Sequence Diagram

```mermaid
sequenceDiagram
participant Browser as User Browser
participant SSR as LFX One SSR
participant NATS as NATS
participant AuthSvc as Auth Service
participant Auth0 as Auth0 Authentication API
participant MUA as Mail User Agent
participant Auth0Mgmt as Auth0 Management API

Note over Browser,Auth0Mgmt: Flow E: Link email identity via passwordless<br/>(email verification with OTP code using LFX One Profile Client)

Browser->>SSR: User clicks "Add Email"<br/>and enters new email address

SSR->>NATS: E1: Publish passwordless<br/>start request with email
Note over NATS,AuthSvc: Auth Service subscribed to NATS subject
NATS->>AuthSvc: Deliver request

AuthSvc->>Auth0: E2: POST /passwordless/start<br/>w/ "LFX One Profile" client credentials<br/>email=new_email@example.com<br/>connection=email<br/>send=code

Auth0->>MUA: Send verification code

MUA->>Browser: User receives code<br/>in their inbox

Auth0-->>AuthSvc: Code sent confirmation
AuthSvc->>NATS: Publish response
NATS->>SSR: Deliver response
SSR-->>Browser: Show "Enter code" UI

Browser->>SSR: User enters code from email<br/>in LFX One

Note over SSR: SSR already has<br/>access_token_mgmt_self from Flow C<br/>(Management API token)

SSR->>NATS: E3: Publish verification request<br/>with code + access_token_mgmt_self
NATS->>AuthSvc: Deliver request

AuthSvc->>Auth0: E4: POST /oauth2/token<br/>[passwordless grant]<br/>w/ "LFX One Profile" client credentials<br/>username=new_email@example.com<br/>otp=verification_code<br/>[NO audience]

Auth0-->>AuthSvc: E5: access_token_pwdless<br/>for /userinfo (IGNORE) +<br/>id_token_pwdless

AuthSvc->>AuthSvc: E6: Validate email from<br/>id_token_pwdless matches<br/>the requested email

AuthSvc->>Auth0Mgmt: E7: Link email identity<br/>using access_token_mgmt_self<br/>w/ id_token_pwdless claims

Auth0Mgmt-->>AuthSvc: Identity linked successfully
AuthSvc->>NATS: Publish response
NATS->>SSR: Deliver response

SSR-->>Browser: Update UI with<br/>newly linked email

Note over Browser,Auth0Mgmt: Auth Service abstracts all Auth0 API calls via NATS
```
75 changes: 75 additions & 0 deletions docs/auth-flows/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# LFX One Authentication Flows

This directory contains sequence diagrams documenting the authentication flows used in LFX One.

## Overview

The authentication architecture uses multiple Auth0 clients and flows to support different use cases:

- **LFX One Client**: Regular web application used for server-side rendering authentication with LFX v2 API access
- **LFX One Profile Client**: Regular web application used for social account linking, self-service Auth0 access (user profile updates), and passwordless email linking. This client supports both Authorization Code flow for Management API access and OTP grant type for passwordless flows.
- **LFX V2 Auth Service Client**: Machine-to-machine client used by Auth Service for reading user profiles

## Authentication Flows

| Flow | Description | Client Used | Audience | Purpose |
|------|-------------|-------------|----------|---------|
| [Flow A](A-auth-service-m2m-profile-lookup.md) | Auth Service M2M | Auth Service M2M | `auth0_mgmt` | Read user profiles and check email-to-username mappings |
| [Flow B](B-lfx-one-login-ssr-oidc.md) | LFX One Login (SSR OIDC) | LFX One | `lfxv2` | Authenticate users and obtain access tokens for LFX v2 API |
| [Flow C](C-profile-update.md) | Self-Service Profile Updates | LFX One Profile | `auth0_mgmt` | Allow users to update their own profiles via Management API |
| [Flow D](D-social-identity-linking.md) | Social Identity Linking | LFX One Profile | None | Link social identities (Google, GitHub, etc.) to user accounts |
| [Flow E](E-passwordless-email-linking.md) | Email Identity Linking | LFX One Profile | None | Link additional email addresses using passwordless OTP verification |

## Client Descriptions

### LFX One Client
The main server-side rendering client used for user authentication. This is a regular web application client that implements the authorization code flow with grant types `authorization_code` and `refresh_token` (plus `password-realm` in dev environments for Cypress testing). It obtains access tokens with the `lfxv2` audience for accessing the LFX v2 API (Traefik/Heimdall). This client is used exclusively in Flow B for the initial user login.

### LFX One Profile Client
A **regular web application** client (`app_type: regular_web`) used for Auth0 Management API access and passwordless flows. This client uses the authorization code flow for obtaining Management API access tokens that allow users to update their own profiles and link identities. It also supports the passwordless OTP grant type (`http://auth0.com/oauth/grant-type/passwordless/otp`) for email verification flows. This client implements a dual authentication pattern where users first authenticate with the main LFX One client, then use this client to obtain additional access tokens for specific audiences (Management API) or perform passwordless verification. Used in Flows C, D, and E.

### LFX V2 Auth Service M2M Client
A **machine-to-machine (M2M)** client named "LFX V2 Auth Service" that uses the client credentials grant type. This client has restricted permissions with only `read:users` scope (but **not** `update:users`) for the Auth0 Management API. It is used exclusively by the Auth Service to perform read-only operations such as profile lookups and checking email-to-username mappings. Used exclusively in Flow A.

## Token Overview

| Token | Audience | Scope | Used For |
|-------|----------|-------|----------|
| `access_token_m2m_read` | `auth0_mgmt` | `read:users` | Auth Service reading user profiles (Flow A) |
| `access_token_lfxv2` | `lfxv2` | LFX v2 API | Calling LFX v2 API endpoints (Flow B) |
| `access_token_mgmt_self` | `auth0_mgmt` | `update:users`* | User updating their own profile (Flow C, D, E) |
| `access_token_social` | (default) | N/A | Ignored - returned from social auth (Flow D) |
| `access_token_pwdless` | (default) | N/A | Ignored - returned from passwordless (Flow E) |
| `id_token_user` | N/A | N/A | User identity from main login (Flow B) |
| `id_token_mgmt` | N/A | N/A | Ignored - returned from mgmt flow (Flow C) |
| `id_token_social` | N/A | N/A | Social provider identity (Flow D) |
| `id_token_pwdless` | N/A | N/A | Passwordless email identity (Flow E) |

## Key Architecture Patterns

### NATS Pub/Sub
Auth Service uses NATS for communication with LFX One SSR, subscribing to subjects for:
- Profile lookup requests
- Profile update requests
- Email linking requests
- Social identity linking requests

### Auth Service Abstraction
All Auth0 Management API calls are abstracted through the Auth Service, which communicates with LFX One via NATS. This provides:
- Centralized token management
- Simplified client-side code
- Better security (Management API credentials stay in Auth Service)

## Flow Dependencies

- **Flow C, D, E** all depend on **Flow B** (user must be logged in first)
- **Flow D and E** both use `access_token_mgmt_self` from **Flow C** to perform identity linking operations
- **Flow A** is independent and used by Auth Service for background operations

## Security Considerations

1. **Principle of Least Privilege**: Auth Service M2M client only has `read:users`, not `update:users`
2. **Subject Validation**: Flow C validates token subjects match before allowing profile updates
3. **Email Verification**: Flow E validates the email in `id_token_pwdless` matches the requested email before linking
4. **Token Scoping**: Each access token is scoped to specific audiences and permissions
5. **Abstraction Layer**: Management API calls go through Auth Service, not directly from client
2 changes: 1 addition & 1 deletion docs/email_lookups.md → docs/subjects/email_lookups.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,5 @@ nats request lfx.auth-service.email_to_sub zephyr.stormwind@mythicaltech.io
- Linked/alternate email addresses are **not** supported for lookup
- The service works with Auth0, Authelia, and mock repositories based on configuration
- The returned subject identifier is the canonical user identifier used throughout the system
- For Authelia-specific SUB identifier details and how they are populated, see: [`../internal/infrastructure/authelia/README.md`](../internal/infrastructure/authelia/README.md)
- For Authelia-specific SUB identifier details and how they are populated, see: [`../../internal/infrastructure/authelia/README.md`](../../internal/infrastructure/authelia/README.md)

Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,6 @@ nats request lfx.auth-service.email_linking.verify '{
- OTP codes are time-sensitive and available for a valid time period
- The service prevents linking an email that is already verified and linked to another user
- The returned token (ID token) can be used to link the verified email to the user account using the identity linking operation (see [Identity Linking Documentation](identity_linking.md))
- For detailed Auth0-specific implementation details and technical information about the passwordless flow, see: [`../internal/infrastructure/auth0/README.md`](../internal/infrastructure/auth0/README.md)
- For detailed Auth0-specific implementation details and technical information about the passwordless flow, see: [`../../internal/infrastructure/auth0/README.md`](../../internal/infrastructure/auth0/README.md)


File renamed without changes.
Loading