An OAuth2 Authorization Server built with Gin and github.com/tniah/authlib.
- Authorization Code flow with PKCE (RFC 7636)
- Token Introspection (RFC 7662)
- REST API for managing OAuth2 clients (CRUD)
- PostgreSQL-backed storage
- Go 1.21+
- PostgreSQL
- golang-migrate
Create a .env file at the project root:
# Server
RELEASE_MODE=debug
REST_SERVER_PORT=8080
REST_SERVER_ADDRESS=0.0.0.0
LOG_LEVEL=info
# PostgreSQL
POSTGRES_HOST=127.0.0.1
POSTGRES_PORT=5432
POSTGRES_USERNAME=postgres
POSTGRES_PASSWORD=secret
POSTGRES_DATABASE=oauth2
POSTGRES_SSLMODE=disable
# Error metadata
DOMAIN=example.com
SERVICE=oauth2.example.commake migrate-upgo run ./cmd/server| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/oauth2Clients |
List clients (paginated) |
POST |
/api/v1/oauth2Clients |
Create a new client |
GET |
/api/v1/oauth2Clients/:clientID |
Get client by ID |
PUT |
/api/v1/oauth2Clients/:clientID |
Update client |
DELETE |
/api/v1/oauth2Clients/:clientID |
Delete client |
curl -X POST http://localhost:8080/api/v1/oauth2Clients \
-H "Content-Type: application/json" \
-d '{
"clientName": "My App",
"grantTypes": ["authorization_code"],
"redirectUris": ["https://myapp.com/callback"],
"scopes": ["openid", "profile", "email"],
"tokenEndpointAuthMethod": "client_secret_basic"
}'Response:
{
"code": 201,
"message": "success",
"data": {
"clientId": "658b8c02bc4446789c7a1360523d42f6",
"clientSecret": ".r71mu5mrgfPm0098rvoKQ_nCKdE...",
"clientName": "My App",
"grantTypes": ["authorization_code"],
"responseTypes": ["code"],
"redirectUris": ["https://myapp.com/callback"],
"scopes": ["openid", "profile", "email"],
"tokenEndpointAuthMethod": "client_secret_basic",
"createdAt": "2026-07-13T10:54:17Z",
"updatedAt": "2026-07-13T10:54:17Z"
}
}curl "http://localhost:8080/api/v1/oauth2Clients?page=1&page_size=20"| Field | Allowed values |
|---|---|
grantTypes |
authorization_code |
tokenEndpointAuthMethod |
client_secret_basic, client_secret_post, none |
responseTypesis derived automatically fromgrantTypesand should not be included in the request.Public clients (
tokenEndpointAuthMethod: none) do not exposeclientSecretin responses.
make migrate-up # Apply all pending migrations
make migrate-down # Roll back the last migration
make migrate-create name=<migration> # Create a new migration fileInstall golang-migrate on Linux:
make install-golang-migrate-linuxcmd/server/main.go — Entry point
internal/
config/ — Singleton config loaded from environment
domain/ — Core types (OAuth2Client, Pagination, errors)
oauth2_client/ — Use case layer (business logic)
repository/postgres/ — PostgreSQL repository implementations
rest/ — HTTP server, routing, constants
rest/v1_api/ — HTTP handlers and response helpers
migrations/postgres/ — SQL migration files
scripts/migrate-db — Migration helper script
MIT