Patrick Plate bfcfe83199 feat(w8): backend extraction completion — all missing services + controllers
W8 closes the B3 plan↔code gap (the biggest blocker from Review v3).

New services:
- AuthService: password login/register/refresh/getCurrentUser with audit
- InvitationService: create (SHA-256 hashed token), accept, revoke, list
- AccessRequestService: submit (rate-limited 3/user), approve, deny, list

New controllers:
- AuthController: POST /api/auth/{login,register,refresh}, GET /api/auth/{me,config}
- InvitationController: POST /api/invitations, POST /api/invitations/accept, DELETE/GET
- AccessRequestController: POST /api/access-requests, POST /{id}/{approve,deny}, GET
- AdminAuditController: GET /api/admin/login-events (paginated, admin-only)

New filter:
- OrgContextResolver: reads X-Org-Id/X-Org-Type headers, validates membership,
  sets OrgContext thread-local (cleared in finally block)

New DTOs: LoginRequest, RegisterRequest, RefreshRequest, UserResponse,
AuthConfigResponse, CreateInvitationRequest, CreateAccessRequestRequest,
ReviewAccessRequestRequest

Updated:
- PlateAuthAutoConfiguration: @Import list now includes all 7 new classes
- SecurityConfig: OrgContextResolver bean + filter chain; access-requests
  permitAll scoped to POST only (approve/deny now require auth)

mvn -pl plate-auth-starter compile PASSES.
2026-06-24 22:09:28 +02:00
2026-06-24 15:40:17 +02:00

plate-auth

Reusable authentication + multi-tenancy library for Spring Boot 4 + NextAuth v5.

Two artifacts, one contract

Artifact Registry Purpose
de.platesoft:plate-auth-starter Gitea Maven Spring Boot auto-config: JWT, OAuth, memberships, invitations, access requests
@platesoft/auth Gitea npm NextAuth v5 config factory, HMAC exchange, proxy helpers, React hooks

The wire contract between them is an HMAC-SHA256 signed exchange envelope + JWT bearer tokens.

Quick start (5 lines)

Backend (Spring Boot 4)

<dependency>
  <groupId>de.platesoft</groupId>
  <artifactId>plate-auth-starter</artifactId>
  <version>0.1.0</version>
</dependency>
plate:
  auth:
    jwt:
      secret: ${PLATE_AUTH_JWT_SECRET}      # ≥32 chars
    exchange:
      secret: ${PLATE_AUTH_EXCHANGE_SECRET}  # ≥32 chars, shared with frontend

Frontend (Next.js 15 + NextAuth v5)

pnpm add @platesoft/auth@0.1.0 --registry=https://git.plate-software.de/api/packages/pplate/npm/
// app/api/auth/[...nextauth]/route.ts
import NextAuth from 'next-auth';
import { createAuthConfig } from '@platesoft/auth/config';

const config = createAuthConfig({
  providers: { google: { clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET! } },
  exchange:  { backendUrl: process.env.NEXT_PUBLIC_BACKEND_URL!, secret: process.env.NEXTAUTH_EXCHANGE_SECRET! },
});
export const { handlers, auth, signIn, signOut } = NextAuth(config);
export const { GET, POST } = handlers;

SPI Extension Points

Interface Default Purpose
OrgValidator PermissiveOrgValidator (WARN per call) Validate (org_type, org_id) exists
OrgDisplayNameResolver Returns type:id Pretty-print org
InvitationMailer Logs accept URL Send invite emails
AccessRequestMailer Logs notifications Notify on access requests
OnboardingHook No-op First sign-in hook

Override any bean with @ConditionalOnMissingBean — register your own to replace.

Documentation

Full docs live in the plate-auth wiki.

License

Apache-2.0 — see LICENSE.

S
Description
No description provided
Readme 101 KiB
Languages
Java 95.5%
TypeScript 4.5%