Skip to content

feat: add JWT auth guard with Stellar signature verification (Closes #6) - #21

Merged
Mona-i merged 1 commit into
coopfinance:mainfrom
ney9320:feat/issue-6-jwt-auth-guard
Jul 24, 2026
Merged

feat: add JWT auth guard with Stellar signature verification (Closes #6)#21
Mona-i merged 1 commit into
coopfinance:mainfrom
ney9320:feat/issue-6-jwt-auth-guard

Conversation

@ney9320

@ney9320 ney9320 commented Jul 11, 2026

Copy link
Copy Markdown

/claim

Summary

Add JWT authentication guard with Stellar wallet-based signature verification. Write endpoints are now protected; read endpoints remain public.

Closes #6

Authentication Flow

1. GET /api/auth/nonce?address=G...    → { nonce, message }
2. Client signs `message` with Stellar private key (base64)
3. POST /api/auth/login { address, signature }  → { accessToken }
4. Subsequent requests: Authorization: Bearer <accessToken>

Files Created

src/modules/auth/

File Purpose
auth.service.ts Nonce generation, Stellar Keypair.verify() signature check, JWT issuance, in-memory nonce store (5min TTL, auto-purge)
auth.controller.ts GET /api/auth/nonce, POST /api/auth/login
jwt.strategy.ts Passport JWT strategy — extracts Bearer token, validates expiry
jwt-auth.guard.ts NestJS AuthGuard('jwt') wrapper
auth.module.ts JwtModule.registerAsync + PassportModule

Protected Endpoints

Method Endpoint Before After
POST /api/groups Open 🔒 Requires JWT
POST /api/loans Open 🔒 Requires JWT
PATCH /api/loans/:id/status Open 🔒 Requires JWT
POST /api/governance/proposals Open 🔒 Requires JWT
POST /api/groups/:groupId/members Open 🔒 Requires JWT

All GET endpoints remain publicly accessible.

Design Decisions

  • In-memory nonce store: 5-min TTL with automatic purge. Production should use Redis.
  • JWT expiry: Configurable via JWT_EXPIRES_IN env var (default 24h).
  • JWT secret: Configurable via JWT_SECRET env var.
  • Signature format: Base64-encoded Stellar Ed25519 signature of the UTF-8 challenge message.
  • @ApiBearerAuth(): Added to all protected routes for Swagger documentation.

Verification

  • nest build: Auth module files compile with zero errors
  • Pre-existing TS errors in stellar.service.ts and groups.service.ts are unrelated to this PR

…oopfinance#6)

Create auth module with Stellar wallet-based authentication:

Auth flow:
  1. GET /api/auth/nonce?address=G... — returns challenge message
  2. Client signs message with Stellar private key
  3. POST /api/auth/login — verifies signature, issues JWT
  4. Subsequent write requests include Authorization: Bearer <jwt>

Files created (src/modules/auth/):
  - auth.service.ts — nonce generation, signature verification via
    Stellar Keypair, JWT issuance, in-memory nonce store with TTL
  - auth.controller.ts — GET /api/auth/nonce, POST /api/auth/login
  - jwt.strategy.ts — Passport JWT strategy (Bearer token extraction)
  - jwt-auth.guard.ts — NestJS guard wrapping Passport auth
  - auth.module.ts — JwtModule + PassportModule async config

Write endpoints now protected with @UseGuards(JwtAuthGuard):
  - POST /api/groups
  - POST /api/loans
  - PATCH /api/loans/:id/status
  - POST /api/governance/proposals
  - POST /api/groups/:groupId/members

Read endpoints (GET) remain public.
Swagger docs updated with @ApiBearerAuth on protected routes.
@Mona-i
Mona-i merged commit 195e016 into coopfinance:main Jul 24, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add JWT authentication guard to admin-only endpoints

2 participants