Patrick Plate 63c953d9b9 feat(w2): auth core entities + Google OAuth + JWT + NextAuth bridge
Extracted from InspectFlow Sprint 14.1-14.2, repackaged to de.platesoft.auth.*:
- Entities: User, UserIdentity, Membership, Invitation, AccessRequest, LoginEvent, RefreshToken
- Enums: Role, OrgType, MembershipRole, MembershipStatus, InvitationStatus, AccessRequestStatus, LoginProvider
- Services: JwtService, ExchangeService, MembershipService, LoginEventService
- Filter: JwtAuthenticationFilter
- Controller: OAuthController (POST /api/auth/exchange)
- Config: PlateAuthAutoConfiguration, PlateAuthProperties (plate.auth.* namespace)
- Repositories: all auth-related JPA repositories
- SPI: OrgValidator, OrgDisplayNameResolver, InvitationMailer, AccessRequestMailer, OnboardingHook
- SPI defaults: PermissiveOrgValidator (WARN per call), LoggingInvitationMailer,
  LoggingAccessRequestMailer, DefaultOrgDisplayNameResolver, NoOpOnboardingHook
- DTOs: ExchangePayload, TokenResponse
- Security: BCrypt encoder, stateless session, CORS from PlateAuthProperties
- META-INF/spring AutoConfiguration.imports registered

All @Value refs replaced with PlateAuthProperties injection.
No references to de.platesoft.inspectflow.* remain.
2026-06-24 15:46:54 +02:00
2026-06-24 15:40:17 +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%