A reusable, secure, and scalable authentication server built with ASP.NET Core Web API for web and mobile applications.
- ✅ User Registration with email verification
- ✅ Login with JWT access tokens
- ✅ Refresh token rotation for session management
- ✅ Secure logout with token blacklisting
- ✅ Password reset via email
- ✅ Email verification
- ✅ JWT Bearer token authentication
- ✅ Password hashing with ASP.NET Identity
- ✅ Rate limiting to prevent brute force attacks
- ✅ Token blacklist for revoked tokens
- ✅ Account lockout after failed login attempts
- ✅ HTTPS enforcement
- ✅ CORS configuration for multi-platform support
- ✅ Role-based access control (RBAC)
- ✅ Admin, User, and Moderator roles
- ✅ Role management endpoints (Admin only)
- ✅ Protected routes with [Authorize] attributes
- ✅ User profile retrieval and updates
- ✅ List all users (Admin only)
- ✅ Assign/remove user roles (Admin only)
- ✅ Email service with MailKit
- ✅ Multi-app email configuration (database-driven)
- ✅ Structured logging with Serilog
- ✅ Background service for token cleanup
- ✅ Global exception handling
- ✅ Swagger UI with JWT authentication support
- ✅ Model validation
- ✅ Session management: View and revoke active sessions (refresh tokens)
- ✅ Health check endpoint:
/api/auth/healthfor monitoring - ✅ User activity tracking: Metrics for logins, logouts, failed logins (per user)
AuthServer/
├── Config/ # Configuration classes
│ └── SwaggerConfig.cs
├── Controllers/ # API endpoints
│ ├── AuthController.cs
│ └── EmailConfigController.cs
├── Data/ # Database context
│ └── ApplicationDbContext.cs
├── DTOs/ # Data Transfer Objects
│ ├── AuthResponse.cs
│ ├── LoginRequest.cs
│ ├── RegisterRequest.cs
│ ├── RefreshTokenRequest.cs
│ ├── ForgotPasswordRequest.cs
│ ├── ResetPasswordRequest.cs
│ ├── UpdateProfileRequest.cs
│ ├── UserProfileResponse.cs
│ └── AssignRoleRequest.cs
├── Middleware/ # Custom middleware
│ ├── TokenBlacklistMiddleware.cs
│ └── GlobalExceptionHandler.cs
├── Models/ # Database models
│ ├── ApplicationUser.cs
│ ├── RefreshToken.cs
│ ├── TokenBlacklist.cs
│ ├── AppEmailConfig.cs
│ └── EmailConfiguration.cs
├── Services/ # Business logic
│ ├── ITokenService.cs
│ ├── TokenService.cs
│ ├── IEmailService.cs
│ ├── EmailService.cs
│ └── TokenCleanupService.cs
├── Program.cs # Application entry point
├── appsettings.json # Configuration
└── AuthServer.csproj # Project dependencies
- Framework: ASP.NET Core 8.0 Web API
- Language: C#
- Database: SQL Server with Entity Framework Core
- Authentication: JWT Bearer Tokens
- Email: MailKit
- Logging: Serilog
- Rate Limiting: AspNetCoreRateLimit
- API Documentation: Swagger/OpenAPI
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="MailKit" Version="4.3.0" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />- .NET 8.0 SDK
- SQL Server (LocalDB, Express, or Full)
- Visual Studio 2022 or VS Code
-
Clone the repository
git clone <repository-url> cd APIs
-
Restore NuGet packages
dotnet restore
-
Update database connection string
Edit
appsettings.json:"ConnectionStrings": { "DefaultConnection": "Server=localhost;Database=AuthServerDb;Trusted_Connection=True;TrustServerCertificate=True;" }
-
Configure Email Settings (Optional for Development)
For multi-app email support, you'll configure emails via database (see step 6).
For single-app setup, update
appsettings.json:"Email": { "Default": { "From": "noreply@authserver.com", "FromName": "Auth Server", "SmtpServer": "smtp.gmail.com", "SmtpPort": "587", "Username": "application@gmail.com", "Password": "your-app-password" } }
Note: For Gmail, you need to create an App Password
-
Update JWT Secret
In
appsettings.json, change the JWT secret to a secure random string:"Jwt": { "Secret": "YOUR_SECURE_SECRET_KEY_AT_LEAST_32_CHARACTERS_LONG" }
-
Apply database migrations
dotnet ef migrations add InitialCreate dotnet ef database update
-
Seed Email Configurations (Multi-App Support)
Run the SQL script to set up email configs for different apps:
sqlcmd -S localhost\SQLEXPRESS -E -d AuthServerDb -C -i SeedEmailConfigs.sqlOr manually insert via SQL:
INSERT INTO AppEmailConfigs (AppId, AppName, FromEmail, FromName, SmtpHost, SmtpPort, SmtpUsername, SmtpPassword, IsActive, CreatedAt) VALUES ('default', 'Auth Server', 'noreply@example.com', 'Auth Server', 'smtp.gmail.com', 587, 'application@gmail.com', 'your-app-password', 1, GETUTCDATE());
-
Run the application
dotnet run
-
Access Swagger UI
Navigate to:
https://localhost:7000/swagger
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/auth/register |
Register new user | No |
| POST | /api/auth/login |
Login with credentials | No |
| POST | /api/auth/refresh |
Refresh access token | No |
| POST | /api/auth/logout |
Logout and blacklist token | Yes |
| GET | /api/auth/sessions |
List active sessions (refresh tokens) | Yes |
| POST | /api/auth/revoke-session/{tokenId} |
Revoke a specific session | Yes |
| GET | /api/auth/verify-email |
Verify email address | No |
| POST | /api/auth/forgot-password |
Request password reset | No |
| POST | /api/auth/reset-password |
Reset password | No |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /api/auth/profile |
Get current user profile | Yes |
| PUT | /api/auth/profile |
Update user profile | Yes |
| GET | /api/auth/activity |
View recent user activity (logins, logouts, failed logins) | Yes |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /api/auth/users |
List all users | Admin |
| POST | /api/auth/assign-role |
Assign role to user | Admin |
| POST | /api/auth/remove-role |
Remove role from user | Admin |
| GET | /api/auth/admin-only |
Test admin access | Admin |
| GET | /api/auth/health |
Health check endpoint | No |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /api/emailconfig |
List all email configs | Admin |
| GET | /api/emailconfig/{id} |
Get specific config | Admin |
| POST | /api/emailconfig |
Add new email config | Admin |
| PUT | /api/emailconfig/{id} |
Update email config | Admin |
| DELETE | /api/emailconfig/{id} |
Delete email config | Admin |
| POST | /api/emailconfig/{id}/toggle |
Enable/disable config | Admin |
- User registers → Email verification sent
- User verifies email via link
- User logs in → Receives access token (15 min) + refresh token (30 days)
- Client stores tokens securely
- When access token expires, use refresh token
- Server validates refresh token
- New access + refresh tokens issued
- Old refresh token revoked (rotation)
- Client sends logout request with access token
- Token added to blacklist
- All subsequent requests with that token are rejected
This auth server supports multiple applications with different branded email addresses. Perfect for when you have multiple projects (e.g., football app, gaming platform, e-commerce) all using the same authentication server.
Each application sends an X-App-ID header with requests. The server uses this to select the correct email configuration from the database.
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Football App│ │ Gaming App │ │ E-Commerce │
│ X-App-ID: │ │ X-App-ID: │ │ X-App-ID: │
│ football │ │ gaming │ │ ecommerce │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────────────────┼────────────────────────┘
│
┌────────▼─────────┐
│ Auth Server │
│ (One Instance) │
└────────┬─────────┘
│
┌────────▼─────────┐
│ AppEmailConfigs │
│ Database Table │
│ │
│ football → app1@ │
│ gaming → app2@ │
│ ecommerce→ app3@ │
└──────────────────┘
| Column | Type | Description | Example |
|---|---|---|---|
| Id | INT | Primary key (auto) | 1, 2, 3 |
| AppId | NVARCHAR(100) | Unique app identifier | football, gaming |
| AppName | NVARCHAR(200) | Display name | Football App |
| FromEmail | NVARCHAR(200) | Sender email address | application@gmail.com |
| FromName | NVARCHAR(200) | Sender name | Football Support |
| SmtpHost | NVARCHAR(200) | SMTP server | smtp.gmail.com |
| SmtpPort | INT | SMTP port | 587 |
| SmtpUsername | NVARCHAR(200) | SMTP username | application@gmail.com |
| SmtpPassword | NVARCHAR(500) | SMTP password | Gmail App Password |
| IsActive | BIT | Enable/disable | 1 (true) or 0 (false) |
| CreatedAt | DATETIME2 | Creation timestamp | Auto-set |
| UpdatedAt | DATETIME2 | Last update timestamp | Nullable |
Option 1: SQL Insert (Fastest)
INSERT INTO AppEmailConfigs
(AppId, AppName, FromEmail, FromName, SmtpHost, SmtpPort, SmtpUsername, SmtpPassword, IsActive, CreatedAt)
VALUES
('ecommerce', 'My Online Store', 'store@gmail.com', 'Store Support Team',
'smtp.gmail.com', 587, 'store@gmail.com', 'your-gmail-app-password', 1, GETUTCDATE());Option 2: Admin API
curl -X POST https://localhost:7000/api/emailconfig \
-H "Authorization: Bearer {admin-token}" \
-H "Content-Type: application/json" \
-d '{
"appId": "ecommerce",
"appName": "My Online Store",
"fromEmail": "store@gmail.com",
"fromName": "Store Support Team",
"smtpHost": "smtp.gmail.com",
"smtpPort": 587,
"smtpUsername": "store@gmail.com",
"smtpPassword": "your-gmail-app-password",
"isActive": true
}'JavaScript (React/Next.js/Vue)
// Football app - user registration
fetch('https://yourserver.com/api/auth/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-App-ID': 'football' // ← Server uses football email config
},
body: JSON.stringify({
email: 'user@example.com',
password: 'SecurePass123!',
firstName: 'John',
lastName: 'Doe'
})
});
// Email sent from: application1@gmail.com (Football App)Python
import requests
# Gaming app - password reset
response = requests.post(
'https://yourserver.com/api/auth/forgot-password',
headers={
'Content-Type': 'application/json',
'X-App-ID': 'gaming' # ← Server uses gaming email config
},
json={'email': 'user@example.com'}
)
# Email sent from: application2@gmail.com (Gaming Platform)C# / .NET / Mobile (Xamarin/MAUI)
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-App-ID", "ecommerce");
var response = await client.PostAsJsonAsync(
"https://yourserver.com/api/auth/register",
new {
email = "user@example.com",
password = "SecurePass123!",
firstName = "John",
lastName = "Doe"
}
);
// Email sent from: application3@gmail.com (E-Commerce)No X-App-ID Header (Default Behavior)
If a client doesn't send the X-App-ID header, the server uses the first active email config as default.
View all configs (SQL)
SELECT Id, AppId, AppName, FromEmail, SmtpHost, IsActive, CreatedAt
FROM AppEmailConfigs
ORDER BY AppId;Update existing config
UPDATE AppEmailConfigs
SET FromEmail = 'newemail@gmail.com',
SmtpUsername = 'newemail@gmail.com',
SmtpPassword = 'new-app-password',
UpdatedAt = GETUTCDATE()
WHERE AppId = 'football';Disable an app temporarily
UPDATE AppEmailConfigs
SET IsActive = 0,
UpdatedAt = GETUTCDATE()
WHERE AppId = 'gaming';✅ One auth server for unlimited apps
✅ Branded emails per application (professional appearance)
✅ No code changes when adding new apps
✅ Easy management via SQL or Admin API
✅ Secure (admin-only access to configs)
"Jwt": {
"AccessTokenExpirationMinutes": "15",
"RefreshTokenExpirationDays": "30"
}"IpRateLimiting": {
"GeneralRules": [
{
"Endpoint": "*/api/auth/login",
"Period": "1m",
"Limit": 5
}
]
}"AllowedOrigins": [
"http://localhost:3000",
"https://yourdomain.com"
]- Navigate to
https://localhost:7000/swagger - Register a new user via
/api/auth/register - Verify email (check logs for verification URL in development)
- Login via
/api/auth/loginto get access token - Click Authorize button in Swagger UI
- Enter:
Bearer YOUR_ACCESS_TOKEN - Test protected endpoints
- View active sessions:
GET /api/auth/sessions— Returns a list of your active refresh tokens (sessions).
- Revoke a session:
POST /api/auth/revoke-session/{tokenId}— Revoke a specific session by its ID. Useful for logging out from other devices.
GET /api/auth/health— Returns status, timestamp, and version for monitoring/uptime checks.
- View your recent activity:
GET /api/auth/activity— See your recent logins, logouts, and failed login attempts.
All these endpoints are available in Swagger UI for easy testing.
A default admin account is created on first run:
- Email: admin@authserver.com
- Password: Admin@123
- Role: Admin
⚠️ IMPORTANT: Change this password immediately in production!
- Create Azure App Service (Windows/.NET 8)
- Create Azure SQL Database
- Update connection string in Azure Configuration
- Deploy via:
dotnet publish -c Release
- Upload to Azure or use GitHub Actions
Create Dockerfile:
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY bin/Release/net8.0/publish/ .
ENTRYPOINT ["dotnet", "AuthServer.dll"]Build and run:
docker build -t authserver .
docker run -p 5000:80 authserverSet these as environment variables instead of appsettings.json:
ConnectionStrings__DefaultConnection="your-db-connection"
Jwt__Secret="your-secure-secret"Note: Email configurations are now stored in the database (
AppEmailConfigstable), not in environment variables. Manage them via SQL or the Admin API.
- Verify SQL Server is running
- Check connection string format
- Ensure database exists
- Check if email config exists in
AppEmailConfigstable - Verify SMTP credentials are correct (run:
SELECT * FROM AppEmailConfigs) - For Gmail, use App Password (not regular password)
- Check firewall/network settings
- Ensure the app's
IsActiveis set to1
- Ensure secret is at least 32 characters
- Check token expiration times
- Verify token format in Authorization header
This is a reusable authentication server designed to be integrated into multiple projects. Feel free to:
- Add new features
- Improve security
- Enhance documentation
- Report issues
This project is designed as a reusable template for authentication services.
- Two-factor authentication (2FA)
- OAuth2/OpenID Connect
- Social login (Google, Facebook, etc.)
- Multi-app email configuration (✅ Completed)
- API key authentication
- Redis caching for tokens
- PostgreSQL/MongoDB support
- Password strength meter
- Session management UI
- Email template customization per app
For issues or questions, please create an issue in the repository.
For detailed multi-app email setup, see MULTI-APP-EMAIL.md.
Built with ❤️ for secure and scalable authentication