A robust, enterprise-grade authentication and authorization service designed for modern distributed applications. Built with security, flexibility, and multi-tenancy at its core.
- OAuth2/OpenID Connect implementation with OpenIddict for secure token-based authentication
- Multi-tenant architecture with hierarchical organization units
- Fine-grained permission system with role-based access control
- API key management for secure service-to-service communication
- Complete user onboarding flow with identity verification integration
- Email verification and account management
- Robust security features including token revocation, refresh token rotation, and brute force protection
- Architecture
- Tech Stack
- Key Components
- Getting Started
- API Documentation
- Configuration
- Deployment
- Security Considerations
- Contributing
- License
The service follows a clean, layered architecture:
βββββββββββββββββββ
β API Layer β β REST controllers, middleware, authentication handlers
βββββββββββββββββββ€
β Core Layer β β Domain entities, interfaces, business logic
βββββββββββββββββββ€
β Infrastructure β β Data access, external service integration
βββββββββββββββββββ
The service is designed to be deployed as a microservice providing centralized identity and access management to all components in your application ecosystem.
- Framework: ASP.NET Core 8.0
- Authentication: OpenIddict (OAuth2/OpenID Connect)
- Database: PostgreSQL with Entity Framework Core
- Caching: Redis for token and session caching
- Identity Verification: Pluggable provider system (Smile Identity integration included)
- Messaging: Event-driven architecture
- Containerization: Docker with Kubernetes orchestration
The service supports multiple isolated tenants sharing the same infrastructure, with each tenant having its own users, organization units, and permission settings.
// Example of tenant-aware query
var userQuery = _dbContext.Users.AsQueryable();
if (!string.IsNullOrEmpty(tenantId))
{
userQuery = userQuery.Where(u => u.TenantId == tenantId);
}Each tenant can define its own organizational hierarchy, with inheritance of permissions through the tree structure.
// Example of getting effective permissions through org unit hierarchy
public async Task<IEnumerable<Permission>> GetEffectivePermissionsForUserAsync(string userId)
{
var user = await _userManager.FindByIdAsync(userId);
var permissions = new List<Permission>();
// Get org unit permissions including ancestors
if (!string.IsNullOrEmpty(user.OrganizationUnitId))
{
var orgUnitPermissions = await _orgUnitService.GetEffectivePermissionsForOrgUnitAsync(user.OrganizationUnitId);
permissions.AddRange(orgUnitPermissions);
}
// Add role-based permissions
var rolePermissions = await GetRolePermissionsForUserAsync(userId);
permissions.AddRange(rolePermissions);
return permissions.Distinct();
}The service uses OpenIddict to implement OAuth2/OpenID Connect standards, providing secure token-based authentication.
// Example token generation
var principal = await CreateClaimsPrincipalAsync(user, roles, customClaims);
var authorization = await _authorizationManager.CreateAsync(
principal: principal,
subject: await _applicationManager.GetIdAsync(application),
client: await _applicationManager.GetIdAsync(application),
type: OpenIddictConstants.AuthorizationTypes.Permanent,
scopes: principal.GetScopes());
var accessToken = await _tokenManager.CreateAsync(
type: OpenIddictConstants.TokenTypeHints.AccessToken,
authorizationId: await _authorizationManager.GetIdAsync(authorization));The service provides API key-based authentication for service-to-service communication, with full lifecycle management.
// Example API key validation middleware
public class ApiKeyAuthenticationHandler : AuthenticationHandler<ApiKeyAuthenticationOptions>
{
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.TryGetValue("X-API-Key", out var apiKeyHeaderValues))
{
return AuthenticateResult.NoResult();
}
var providedApiKey = apiKeyHeaderValues.FirstOrDefault();
var clientIpAddress = Context.Connection.RemoteIpAddress;
var validationResult = await _apiKeyService.ValidateApiKeyAsync(providedApiKey, clientIpAddress);
if (!validationResult.IsValid)
{
return AuthenticateResult.Fail("Invalid API key.");
}
// Create claims principal with permissions from API key
// ...
}
}The service includes a pluggable identity verification system, with built-in integration for Smile Identity and other KYC providers.
// Example identity verification flow
public async Task<VerificationInitResult> InitiateVerificationAsync(string userId, VerificationType verificationType)
{
// Create verification session with the configured provider
var client = _httpClientFactory.CreateClient("IdentityVerification");
var jobParams = new
{
partner_id = _options.PartnerId,
job_type = GetJobTypeFromVerificationType(verificationType),
user_id = userId,
job_id = Guid.NewGuid().ToString()
};
// Initiate verification and handle response
// ...
return new VerificationInitResult
{
Success = true,
JobId = jobParams.job_id,
RedirectUrl = result.RedirectUrl
};
}- .NET 8.0 SDK
- PostgreSQL Database
- Redis (optional, recommended for production)
- SMTP Server for emails
-
Clone the repository
git clone https://github.com/your-org/auth-service.git cd auth-service -
Configure the service
cp appsettings.example.json appsettings.Development.json # Edit the appsettings.Development.json with your configuration -
Run database migrations
dotnet ef database update
-
Run the service
dotnet run
docker build -t auth-service:latest .
docker run -d \
--name auth-service \
-p 5000:80 \
-e ConnectionStrings__DefaultConnection="Host=postgres;Database=authservice;Username=postgres;Password=yourpassword" \
-e ASPNETCORE_ENVIRONMENT="Production" \
auth-service:latestFull API documentation is available via Swagger when running the service:
http://localhost:5000/swagger
- Authentication:
/api/auth/*- Login, register, token refresh - Tenants:
/api/tenants/*- Tenant management - Organization Units:
/api/tenants/{tenantId}/organization-units/*- Organization structure - Permissions:
/api/permissions/*- Permission management - API Keys:
/api/apikeys/*- API key management - Onboarding:
/api/onboarding/*- User onboarding and identity verification
Configuration is managed through appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Host=postgres;Database=authservice;Username=postgres;Password=yourpassword"
},
"Jwt": {
"Issuer": "https://auth.your-app.com",
"Audience": "your-app-api",
"Key": "[Your secret key here]",
"TokenExpirationInMinutes": 60
},
"EmailSettings": {
"SenderEmail": "noreply@your-app.com",
"SenderName": "Your Application",
"SmtpServer": "smtp.example.com"
},
"IdentityVerification": {
"Provider": "SmileIdentity",
"ApiUrl": "https://api.provider.com/v1/",
"PartnerId": "[Your partner ID]"
}
}Example Kubernetes deployment manifest:
apiVersion: apps/v1
kind: Deployment
metadata:
name: auth-service
spec:
replicas: 3
selector:
matchLabels:
app: auth-service
template:
metadata:
labels:
app: auth-service
spec:
containers:
- name: auth-service
image: auth-service:latest
ports:
- containerPort: 80
env:
- name: ASPNETCORE_ENVIRONMENT
value: "Production"
# Add other environment variables or config maps- Secrets Management: Use a secure vault for storing secrets in production
- HTTPS: Always configure HTTPS in production environments
- Token Security: Keep token lifetime short and implement proper revocation
- API Key Management: Rotate API keys regularly
- Permission Reviews: Regularly audit permission assignments
We welcome contributions to the Auth Service! Please see our Contributing Guide for more details.
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.