Files
pos-system/services/iam-service-net
..

IAM Service .NET

Identity and Access Management Service built with .NET 10, ASP.NET Core Identity, and OpenIddict.

Overview

IAM Service provides OAuth2/OpenID Connect authentication and authorization capabilities:

  • User Management: Registration, profile management, account locking
  • Role-Based Access Control (RBAC): Role assignment, permission management
  • OAuth2 Token Endpoints: Password, Refresh Token, Client Credentials grants
  • JWT Tokens: Access tokens (15 min), Refresh tokens (7 days)

Tech Stack

Technology Purpose
.NET 10 Runtime
ASP.NET Core Identity User/Role management
OpenIddict OAuth2/OIDC server
EF Core + PostgreSQL Data persistence
MediatR CQRS pattern
FluentValidation Request validation
Serilog Structured logging

Quick Start

1. Prerequisites

  • .NET SDK 10.0.101+
  • Docker (for PostgreSQL)

2. Setup Environment

cp .env.example .env
# Edit DATABASE_URL in .env

3. Run with Docker Compose

docker-compose up -d

Service available at: http://localhost:5001

4. Run Locally

dotnet restore
dotnet build
dotnet run --project src/IamService.API

Database Migrations

Prerequisites

# Install EF Core tools (one-time)
dotnet tool install --global dotnet-ef

Create Migration

dotnet ef migrations add <MigrationName> \
  --project src/IamService.Infrastructure \
  --startup-project src/IamService.API

Apply Migration

dotnet ef database update \
  --project src/IamService.Infrastructure \
  --startup-project src/IamService.API

Neon Database Setup

  1. Create database on Neon Console
  2. Copy connection string
  3. Update appsettings.Development.json:
{
  "ConnectionStrings": {
    "DefaultConnection": "Host=<host>;Port=5432;Database=<db>;Username=<user>;Password=<pass>;SSL Mode=Require"
  }
}
  1. Run migrations: dotnet ef database update ...

API Endpoints

Authentication (/api/v1/auth)

Method Endpoint Description Auth
POST /api/v1/auth/register Register new user
POST /connect/token OAuth2 token endpoint (login, refresh)
POST /api/v1/auth/change-password Change password
POST /api/v1/auth/logout Logout (revoke tokens)

User Management (/api/v1/users)

Method Endpoint Description Auth
GET /api/v1/users List users (paginated)
GET /api/v1/users/me Get current user
GET /api/v1/users/{id} Get user by ID
PUT /api/v1/users/{id} Update user
DELETE /api/v1/users/{id} Delete user (soft delete)

Authentication Flow

Step 1: Register a New User

curl -X POST http://localhost:5001/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "Password123!",
    "firstName": "John",
    "lastName": "Doe"
  }'

Response:

{
  "success": true,
  "data": {
    "userId": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com"
  }
}

Step 2: Login (Password Grant)

curl -X POST http://localhost:5001/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password" \
  -d "username=user@example.com" \
  -d "password=Password123!" \
  -d "scope=openid profile email offline_access"

Response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9...",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9...",
  "scope": "openid profile email offline_access"
}

Step 3: Use Access Token

Use the access_token in Authorization header for protected APIs:

curl http://localhost:5001/api/v1/users/me \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9..."

Step 4: Refresh Token (When Access Token Expires)

curl -X POST http://localhost:5001/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9..."

Step 5: Logout

curl -X POST http://localhost:5001/api/v1/auth/logout \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Client Credentials (Service-to-Service)

curl -X POST http://localhost:5001/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=goodgo-service" \
  -d "client_secret=service-secret" \
  -d "scope=api"

Health Checks

Endpoint Purpose
/health Full health status
/health/live Liveness probe
/health/ready Readiness probe

Swagger UI

After running the service, access Swagger UI at:

Project Structure

iam-service-net/
├── src/
│   ├── IamService.API/              # Controllers, CQRS
│   │   ├── Controllers/             # AuthController, UsersController
│   │   └── Application/             # Commands, Queries, Validations
│   ├── IamService.Domain/           # Domain entities
│   │   ├── AggregatesModel/         # UserAggregate, RoleAggregate
│   │   ├── Events/                  # Domain events
│   │   └── Exceptions/              # Domain exceptions
│   └── IamService.Infrastructure/   # Data access
│       ├── IamServiceContext.cs     # DbContext with Identity
│       └── Repositories/            # Repository implementations
├── tests/
│   ├── IamService.UnitTests/
│   └── IamService.FunctionalTests/
├── Dockerfile
└── docker-compose.yml

Configuration

Environment Variables

Variable Description Default
ASPNETCORE_ENVIRONMENT Environment Development
DATABASE_URL PostgreSQL connection -
JWT_SECRET JWT signing secret (32+ chars) -
REDIS_URL Redis connection -

Password Policy

  • Minimum 8 characters
  • Requires uppercase, lowercase, digit, special character

Token Lifetimes

Token Lifetime
Access Token 15 minutes
Refresh Token 7 days

Development

# Restore dependencies
dotnet restore

# Build
dotnet build

# Run tests
dotnet test

# Run API
dotnet run --project src/IamService.API

Docker

# Build image
docker build -t iam-service:latest .

# Run container
docker run -p 5001:8080 --env-file .env iam-service:latest

Resources

License

Proprietary - GoodGo Platform