Appearance
Login Flow
This page documents the standard login flow in GrydAuth when the user has a default tenant configured.
Overview
When a user logs in with a default tenant, the authentication process is streamlined - no tenant selection is required. The system automatically uses the user's default tenant to generate the JWT token with the appropriate roles and permissions.
Prerequisites
- User has an active account
- User has at least one
UserTenantassociation - One of the
UserTenantrecords hasIsDefault = true - User's
AppIdmatches the application's configuredAppId
Sequence Diagram
100% 💡 Use Ctrl + Scroll para zoom | Arraste para navegar
Step-by-Step Explanation
1. Request Validation
The client sends a POST request to /api/auth/login with:
json
{
"email": "user@example.com",
"password": "SecurePassword123!",
"appId": "my-application"
}2. User Lookup
The system retrieves the user by email. If not found, returns 401 Unauthorized.
3. AppId Validation
Each user can be associated with multiple applications via UserAppId. The system validates that the user is authorized to access the requesting application.
Important
If the appId doesn't match any record in UserAppIds table, authentication fails with "Invalid application ID".
4. Password Verification
The password is verified using secure hashing (BCrypt/Argon2). Failed attempts are recorded for security monitoring.
5. Account Lockout Check
If too many failed attempts occurred, the account may be locked. The lockout duration is configurable.
6. Default Tenant Resolution
The system fetches the user's default tenant:
sql
SELECT ut.*, t.*
FROM UserTenants ut
JOIN Tenants t ON ut.TenantId = t.Id
WHERE ut.UserId = @userId AND ut.IsDefault = true7. Roles & Permissions Aggregation
For the default tenant, the system aggregates:
- Direct roles from
UserRoles - Direct permissions from
UserPermissions - Role-based permissions from
RolePermissions
8. JWT Token Generation
The JWT token includes:
| Claim | Description |
|---|---|
sub | User ID (GUID) |
email | User's email |
tenant_id | Current tenant ID |
roles | Array of role names |
permissions | Array of permission names |
token_version | For token invalidation |
9. Response
A successful login returns:
json
{
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "550e8400-e29b-41d4-a716-446655440000",
"expiresAt": "2026-02-02T15:30:00Z",
"user": {
"id": "...",
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe"
},
"tenant": {
"id": "...",
"name": "Acme Corp"
}
}Error Scenarios
| Error | HTTP Status | Cause |
|---|---|---|
| Invalid credentials | 401 | Wrong email or password |
| Invalid application ID | 401 | AppId not associated with user |
| Account locked | 401 | Too many failed attempts |
| Account inactive | 401 | User.IsActive = false |
| No default tenant | 400 | User needs to select a tenant |
Related Flows
- First Login - When user must change password
- Switch Tenant - When user has no default tenant
- Refresh Token - Refreshing expired access tokens