Skip to content

Commit 9514808

Browse files
Merge pull request #13 from mauriciozanettisalomao/fear/lfxv2-498-499-user-data-consumption-req-reply-authelia-auth0
[LFXV2-498, LFXV2-499] User data consumption req/reply - Authelia and Auth0
2 parents 404912e + 6d48c78 commit 9514808

File tree

19 files changed

+1441
-584
lines changed

19 files changed

+1441
-584
lines changed

README.md

Lines changed: 12 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -162,43 +162,14 @@ To retrieve user metadata, send a NATS request to the following subject:
162162
**Subject:** `lfx.auth-service.user_metadata.read`
163163
**Pattern:** Request/Reply
164164

165-
The service supports two lookup strategies based on the input format, providing both authoritative identification and convenient username-based searches.
166-
167-
##### Input Format and Strategy Selection
168-
169-
The service automatically determines the lookup strategy based on the input format:
170-
171-
- **Canonical Lookup** (contains `|`): `<connection>|<provider_user_id>` - Subject identifier
172-
- **Search Lookup** (no `|`): `<username>` - Convenience lookup
173-
174-
##### Canonical Lookup Strategy (Recommended)
175-
176-
**Format:** `<connection>|<provider_user_id>`
177-
178-
The canonical lookup is the **authoritative, standard way to identify a user**, regardless of which provider they come from.
179-
180-
**Examples:** `auth0|123456789`, `google-oauth2|987654321`, `samlp|my-connection|user123`
181-
182-
##### Search Lookup Strategy (Convenience)
183-
184-
**Format:** `<username>`
185-
186-
Username lookups are **convenience only** and help avoid connection collisions within the Username-Password-Authentication connection.
187-
188-
**Examples:** `john.doe`, `jane.smith`, `developer123`
165+
The service takes a token and validates/retrieves user data from the target identity provider based on the `USER_REPOSITORY_TYPE` environment variable configuration.
189166

190167
##### Request Payload
191168

192-
The request payload should be a plain text identifier (no JSON wrapping required):
169+
The request payload should be a token (no JSON wrapping required):
193170

194-
**Canonical Lookup:**
195171
```
196-
auth0|123456789
197-
```
198-
199-
**Search Lookup:**
200-
```
201-
john.doe
172+
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
202173
```
203174

204175
##### Reply
@@ -236,35 +207,26 @@ The service returns a structured reply with user metadata:
236207
}
237208
```
238209

239-
**Error Reply (Invalid Input):**
210+
**Error Reply (Invalid Token):**
240211
```json
241212
{
242213
"success": false,
243-
"error": "input is required"
214+
"error": "invalid token"
244215
}
245216
```
246217

247-
##### Examples using NATS CLI
218+
##### Example using NATS CLI
248219

249220
```bash
250-
# Canonical lookup (subject identifier)
251-
# Note: Use quotes to escape the pipe character in shell commands
252-
nats request lfx.auth-service.user_metadata.read "auth0|123456789"
253-
254-
# Search lookup (convenience username lookup)
255-
nats request lfx.auth-service.user_metadata.read john.doe
256-
221+
# Retrieve user metadata using token
222+
nats request lfx.auth-service.user_metadata.read "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
257223
```
258224

259225
**Important Notes:**
260-
- **Canonical lookups** are the preferred method for system-to-system communication
261-
- **Search lookups** are provided for convenience and user-facing interfaces
262-
- The pipe character (`|`) in canonical identifiers must be escaped with quotes in shell commands
263-
- Both strategies return the same metadata format on success
264-
- The service supports **Auth0**, **Authelia**, and **mock** repositories based on configuration
265-
- When using mock or authelia mode, the service simulates Auth0 behavior for development and testing
266-
- For detailed Auth0-specific behavior and limitations, see the [Auth0 Integration Documentation](internal/infrastructure/auth0/README.md)
267-
- For detailed Authelia-specific behavior and SUB management, see the [Authelia Integration Documentation](internal/infrastructure/authelia/README.md)
226+
- The service validates the token and extracts user information from the target identity provider
227+
- The target identity provider is determined by the `USER_REPOSITORY_TYPE` environment variable
228+
- For detailed Auth0-specific behavior and limitations, see: [`internal/infrastructure/auth0/README.md`](internal/infrastructure/auth0/README.md)
229+
- For detailed Authelia-specific behavior and SUB management, see: [`internal/infrastructure/authelia/README.md`](internal/infrastructure/authelia/README.md)
268230

269231
---
270232

internal/domain/port/user.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ type UserReaderWriter interface {
1919
type UserReader interface {
2020
GetUser(ctx context.Context, user *model.User) (*model.User, error)
2121
SearchUser(ctx context.Context, user *model.User, criteria string) (*model.User, error)
22-
MetadataLookup(ctx context.Context, input string, user *model.User) bool
22+
MetadataLookup(ctx context.Context, input string) (*model.User, error)
2323
}
2424

2525
// UserWriter defines the behavior of the user writer

internal/infrastructure/auth0/README.md

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,51 +4,51 @@ This package provides Auth0 integration for the LFX v2 Auth Service, implementin
44

55
## Overview
66

7-
The Auth0 integration supports two primary lookup strategies for user metadata retrieval, providing both authoritative identification and convenient username-based searches.
7+
The Auth0 integration takes a JWT token and validates/retrieves user data from the Auth0 identity provider. The system parses the JWT token to extract user identification information and performs lookups through the Auth0 Management API.
88

9-
## User Identification Strategies
9+
## Token Support
1010

11-
### Canonical Lookup Strategy (Recommended)
11+
The Auth0 integration supports JWT (JSON Web Token) parsing to extract user identification information. When a JWT token is provided as input, the system automatically extracts the `sub` (subject) claim and uses it for user lookups.
1212

13-
**Format:** `<connection>|<provider_user_id>`
13+
### JWT Token Processing
1414

15-
The canonical lookup is the **authoritative, standard way to identify a user**, regardless of which provider they come from. The sub (subject) identifier is the authoritative identifier that uniquely identifies a user across the entire Auth0 tenant.
15+
**Token Format:** JWT tokens issued by Auth0
1616

17-
**Examples:**
18-
* `auth0|123456789` — Auth0 Database connection user
19-
* `google-oauth2|987654321` — Google OAuth2 user
20-
* `github|456789123` — GitHub OAuth2 user
21-
* `samlp|enterprise|user123` — SAML Enterprise connection user
22-
* `linkedin|789123456` — LinkedIn OAuth2 user
23-
24-
**Auth0 Management API Call:**
25-
```http
26-
GET /api/v2/users/{sub}
17+
**Token Structure:**
18+
```json
19+
{
20+
"iss": "https://{{tenant}}.auth0.com/",
21+
"sub": "auth0|user123",
22+
"aud": "https://{{tenant}}.auth0.com/api/v2/",
23+
"iat": 1759751739,
24+
"exp": 1759755339,
25+
"scope": "read:current_user",
26+
"azp": "O8sQ4Jbr3At8buVR3IkrTRlejPZFWenI"
27+
}
2728
```
2829

29-
**Benefits:**
30-
- **Authoritative**: Guaranteed unique identifier across all connections
31-
- **Fast**: Direct lookup by primary key
32-
- **Reliable**: No ambiguity about which user is being referenced
33-
- **Cross-provider**: Works regardless of authentication provider
34-
35-
### Search Lookup Strategy (Convenience)
30+
### Token Processing Flow
3631

37-
**Format:** `<username>`
32+
1. **Token Validation**: Validates the JWT token signature and expiration
33+
2. **Sub Extraction**: Extracts the `sub` claim from the token payload
34+
3. **User Lookup**: Uses the extracted `sub` value for direct user lookup via Auth0 Management API
35+
4. **Auth0 API Call**: Performs direct user lookup using the `sub` identifier
36+
5. **User Data Retrieval**: Returns user metadata from Auth0
3837

39-
Username lookups are **convenience only** and help avoid connection collisions. This strategy searches for users by their username within the Username-Password-Authentication connection.
38+
### Auth0 Management API Integration
4039

41-
**Examples:**
42-
- `john.doe`
43-
- `jane.smith`
44-
- `developer123`
40+
**Canonical Lookup (Recommended):**
41+
```http
42+
GET /api/v2/users/{sub}
43+
```
4544

46-
**Auth0 Management API Call:**
45+
**Search Lookup (Convenience):**
4746
```http
4847
GET /api/v2/users?q=identities.user_id:{username} AND identities.connection:Username-Password-Authentication
4948
```
5049

51-
**Limitations:**
52-
- **Connection-specific**: Only works within Username-Password-Authentication connection
53-
- **Slower**: Requires search query instead of direct lookup
54-
- **Limited scope**: Cannot find users from social or enterprise connections
50+
### Important Notes
51+
52+
- **JWT Signature Validation**: Full JWT signature validation is performed using Auth0's public keys
53+
- **Token Expiration**: JWT tokens are validated for expiration and freshness
54+
- **Auth0 Management API**: Uses Auth0's Management API for user data retrieval

internal/infrastructure/auth0/models.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@
33

44
package auth0
55

6-
import "github.com/linuxfoundation/lfx-v2-auth-service/internal/domain/model"
6+
import (
7+
"encoding/json"
8+
"log/slog"
9+
10+
"github.com/linuxfoundation/lfx-v2-auth-service/internal/domain/model"
11+
)
712

813
// Auth0User represents a user in Auth0
914
type Auth0User struct {
@@ -74,3 +79,29 @@ func (u *Auth0User) ToUser() *model.User {
7479
UserMetadata: meta,
7580
}
7681
}
82+
83+
// ErrorResponse represents an error response from Auth0
84+
type ErrorResponse struct {
85+
StatusCode int `json:"statusCode"`
86+
Error string `json:"error"`
87+
Message string `json:"message"`
88+
Attributes struct {
89+
Error string `json:"error"`
90+
} `json:"attributes"`
91+
}
92+
93+
// Message returns the error message from the attributes
94+
func (e *ErrorResponse) ErrorMessage(errorMessage string) string {
95+
// parse the error message from the attributes
96+
err := json.Unmarshal([]byte(errorMessage), e)
97+
if err != nil {
98+
slog.Error("failed to parse error message from attributes", "error", err)
99+
return errorMessage
100+
}
101+
return e.Message
102+
}
103+
104+
// NewErrorResponse creates a new ErrorResponse
105+
func NewErrorResponse() *ErrorResponse {
106+
return &ErrorResponse{}
107+
}

0 commit comments

Comments
 (0)