Authentication
Authentication implementation using Microsoft Identity Framework (ASP.NET Core Identity).
Authentication Endpoints
User Login
Endpoint: POST /login
Request Body:
{
"email": "user@example.com",
"password": "SecurePassword123!",
"useCookies": true,
"useSessionCookies": false
}
Response: 200 OK
{
"tokenType": "Bearer",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 3600,
"refreshToken": "refresh-token-here",
"user": {
"id": "uuid-here",
"email": "user@example.com",
"name": "John Doe",
"roles": ["client"]
}
}
Roles:
client- Regular user with access to create requests and view their own dataadmin- Administrator with access to backoffice, user management, and all client data
User Registration (Deprecated)
Endpoint: POST /register
This endpoint is deprecated and will return 404 Not Found. Use the Client Registration endpoints instead.
Response: 404 Not Found
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "Not Found",
"status": 404,
"detail": "Endpoint not found. Please use POST /client/register for client registration."
}
Client Registration
For complete client registration documentation, including the registration endpoint, email confirmation flow, password requirements, and registration process, see Client Registration.
Quick Reference:
- Registration Endpoint:
POST /client/register - Email Confirmation:
GET /confirmEmail - Resend Confirmation:
POST /resendConfirmationEmail
Related Pages:
- Client Registration - Complete registration process and flow
- Client Management - Client account management after registration
Refresh Token
Endpoint: POST /refresh
Request Body:
{
"refreshToken": "refresh-token-here"
}
Response: 200 OK
{
"tokenType": "Bearer",
"accessToken": "new-access-token",
"expiresIn": 3600,
"refreshToken": "new-refresh-token"
}
Forgot Password
Endpoint: POST /forgotPassword
Request Body:
{
"email": "user@example.com"
}
Response: 200 OK
{
"message": "Password reset email sent"
}
Reset Password
Endpoint: POST /resetPassword
Request Body:
{
"email": "user@example.com",
"resetCode": "reset-code-from-email",
"newPassword": "NewSecurePassword123!"
}
Response: 200 OK
{
"message": "Password reset successfully"
}
User Logout
Endpoint: POST /logout
Headers:
Authorization: Bearer {access-token}
Request Body: Empty or
{}
Response: 200 OK
{
"message": "Logged out successfully"
}
Error Responses
All endpoints may return the following error responses:
400 Bad Request
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"Email": ["The Email field is required."],
"Password": ["The Password field is required."]
}
}
401 Unauthorized
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.2",
"title": "Unauthorized",
"status": 401,
"detail": "Invalid email or password."
}
404 Not Found
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "Not Found",
"status": 404,
"detail": "User not found."
}
Roles and Authorization
User Roles
The MicDots platform has two primary user roles:
Client Role (role: "client"):
- Regular users who create text-to-audio requests
- Can view and manage their own requests
- Can view their own profile and statistics
- Can update their own account information
- Cannot access admin endpoints or other users' data
Admin Role (role: "admin"):
- Platform administrators with elevated privileges
- Can view and manage all client accounts
- Can view and process all text-to-audio requests
- Can access the admin backoffice dashboard
- Can update request statuses and upload audio files
- Full access to platform analytics and reports
Role-Based Access Control
How Roles Work:
- Role is assigned during user creation (registration or admin invitation)
- Role is included in the JWT access token claims
- Backend validates role on each API request
- Frontend shows/hides UI elements based on user role
JWT Token Claims:
{
"sub": "uuid-here",
"email": "user@example.com",
"name": "John Doe",
"roles": ["client"],
"exp": 1706025600,
"iss": "https://micdots.com",
"aud": "https://micdots.com"
}
Authorization Examples
Client Access:
// Client can only access their own data
GET /client/THEIR_OWN_ID // ✅ Allowed
GET /client/ANOTHER_USER_ID // ❌ 403 Forbidden
// Client can create requests
POST /api/v1/text-to-speech // ✅ Allowed
// Client can view own requests
GET /api/v1/text-to-speech // ✅ Allowed (filtered to own requests)
GET /api/v1/text-to-speech/:id // ✅ Allowed (if owns the request)
// Client cannot update others' requests
PUT /api/v1/text-to-speech/OTHER_USER_ID // ❌ 403 Forbidden
Admin Access:
// Admin can access any client data
GET /client/ANY_CLIENT_ID // ✅ Allowed
GET /client // ✅ Allowed (list all clients)
// Admin can access all requests
GET /api/v1/text-to-speech // ✅ Allowed (sees all requests)
GET /api/v1/text-to-speech/:id // ✅ Allowed (any request)
// Admin can update any request
PUT /api/v1/text-to-speech/:id // ✅ Allowed (update status, audioUrl, etc.)
POST /api/v1/text-to-speech/upload-url // ✅ Allowed (get pre-signed S3 URL)
Error Responses for Authorization
403 Forbidden (Insufficient Permissions):
{
"success": false,
"error": {
"code": "FORBIDDEN",
"message": "You do not have permission to access this resource.",
"detail": "This endpoint requires admin role."
}
}
Example Scenarios:
- Client trying to access admin endpoints → 403 Forbidden
- Client trying to view another client's data → 403 Forbidden
- Unauthenticated user trying to access protected endpoint → 401 Unauthorized
Authentication Flow
Login Flow
For the complete client registration and email confirmation flow, see Client Registration.
Token Management
Access Token
- Type: JWT (JSON Web Token)
- Expiration: 1 hour (3600 seconds)
- Storage: Memory or secure HTTP-only cookie
- Usage: Include in
Authorization: Bearer {token}header for all protected endpoints
Refresh Token
- Type: Opaque token
- Expiration: 7 days (configurable)
- Storage: Secure HTTP-only cookie (recommended) or secure storage
- Usage: Use to obtain new access tokens via
POST /refreshwhen access token expires
Security Best Practices
Password Requirements
- Minimum 8 characters
- At least one uppercase letter (A-Z)
- At least one lowercase letter (a-z)
- At least one digit (0-9)
- At least one special character (!@#$%^&*)
Token Security
- Store tokens securely (HTTP-only cookies recommended)
- Never expose tokens in URLs or logs
- Implement token rotation on refresh
- Revoke refresh tokens on logout
Rate Limiting
- Login attempts: 5 per 15 minutes per IP
- Registration: 3 per hour per IP
- Password reset: 3 per hour per email
HTTPS Only
- All authentication endpoints must use HTTPS in production
- Set
Secureflag on cookies - Enable HSTS (HTTP Strict Transport Security)
Configuration
appsettings.json
{
"Authentication": {
"Schemes": {
"Bearer": {
"ValidAudiences": [
"http://localhost:5000",
"https://localhost:5001",
"https://micdots.com"
],
"ValidIssuer": "https://micdots.com"
}
}
},
"IdentityOptions": {
"Password": {
"RequireDigit": true,
"RequireLowercase": true,
"RequireUppercase": true,
"RequireNonAlphanumeric": true,
"RequiredLength": 8
},
"Lockout": {
"DefaultLockoutTimeSpan": "00:15:00",
"MaxFailedAccessAttempts": 5,
"AllowedForNewUsers": true
},
"User": {
"RequireUniqueEmail": true
},
"SignIn": {
"RequireConfirmedEmail": true
}
},
"JwtSettings": {
"SecretKey": "your-secret-key-here-min-32-chars",
"Issuer": "https://micdots.com",
"Audience": "https://micdots.com",
"ExpiryMinutes": 60
}
}
Database Schema
AspNetUsers Table
| Column | Type | Constraints |
|---|---|---|
| Id | string (GUID) | Primary Key |
| UserName | string(256) | Unique, Not Null |
| NormalizedUserName | string(256) | Unique, Indexed |
| string(256) | Unique, Not Null | |
| NormalizedEmail | string(256) | Unique, Indexed |
| EmailConfirmed | boolean | Not Null, Default: false |
| PasswordHash | string | Not Null |
| SecurityStamp | string | Not Null |
| ConcurrencyStamp | string | Not Null |
| PhoneNumber | string | Nullable |
| PhoneNumberConfirmed | boolean | Not Null, Default: false |
| TwoFactorEnabled | boolean | Not Null, Default: false |
| LockoutEnd | DateTimeOffset | Nullable |
| LockoutEnabled | boolean | Not Null, Default: true |
| AccessFailedCount | int | Not Null, Default: 0 |
Additional Identity Tables
AspNetRoles- User rolesAspNetUserRoles- User-role mappingAspNetUserClaims- Custom user claimsAspNetUserLogins- External login providersAspNetUserTokens- User tokens (refresh, reset, etc.)
Testing Endpoints
Using cURL
Login:
curl -X POST http://localhost:5000/login \
-H "Content-Type: application/json" \
-d '{
"email": "client@example.com",
"password": "Test123!@#",
"useCookies": false
}'
Access Protected Endpoint:
curl -X GET http://localhost:5000/manage/info \
-H "Authorization: Bearer {your-access-token}"
Related Documentation
- Client Registration - Client registration process and flow
- Client Management - Client CRUD operations
- Request Management - Text-to-audio requests
- Epic 1 Overview - Feature overview
- User Flow - Complete workflow
- Sample Pages - Login - Login page design