@appneurox/authentication-service
v0.2.0
Published
Authentication Service: NestJS module that runs as its own microservice or inside a modular monolith.
Readme
@appneurox/authentication-service
Authentication Service as one NestJS module. The same code runs in two ways:
| Mode | How | Routes |
| --- | --- | --- |
| Microservice | node dist/standalone.js, deployed at https://authentication-service.appneurox.com | /v1/module, /v1/execute |
| Inside a brand API | servicePackage() mounted by a modular monolith | /authentication-service/v1/module, /authentication-service/v1/execute |
// Brand API (modular monolith)
import { bootstrapMonolith } from '@appneurox/service-composition';
import { servicePackage } from '@appneurox/authentication-service';
await bootstrapMonolith({ services: [servicePackage()] });// Another module in the same process can inject the application directly
import { AuthenticationServiceApplication } from '@appneurox/authentication-service';servicePackage(options) passes options (extra providers, imports, controllers) to
AuthenticationServiceModule.register(), which is how a brand configures this service without forking it.
The host owns HTTP, authentication, tenant context, validation, errors, logging and shutdown
through @appneurox/service-runtime. Importing this package opens no listener.
Status: boilerplate. GET /v1/module works; authorized POST /v1/execute returns
501 NOT_IMPLEMENTED until the business code is written in src/.
Verifying tokens in another API (0.2.0)
Any API built on @appneurox/service-runtime can accept tokens issued by the native
authentication-service (ES256, typ: at+jwt, ≤ 15 minutes, keys from /.well-known/jwks.json):
import { AccessTokenVerifier, ServiceTokenProvider, createTokenIntrospector, parseServiceCredentials,
verifiedSession } from '@appneurox/authentication-service';
const tokens = new ServiceTokenProvider({ issuer: 'https://auth.appneurox.com',
credentials: parseServiceCredentials(process.env.SERVICE_CREDENTIALS_JSON!) });
const verifier = new AccessTokenVerifier({
issuer: 'https://auth.appneurox.com',
audience: 'techlyup-api', // the audience your client is registered with
introspect: createTokenIntrospector({ authorityUrl: 'https://auth.appneurox.com', tokens }),
memberships: async (subjectId, tenantId) => /* tenant-service resolve-membership, or null */ null,
});
await bootstrapMonolith({ services, authVerifier: verifier });
// In a handler: verifiedSession(request.serviceContext) has sid, AAL, amr, auth time, membership.| Export | Does |
| --- | --- |
| AccessTokenVerifier | The runtime's AuthVerifier. Rejects forged, expired, wrong-issuer and wrong-audience tokens and anything but ES256 at+jwt; introspects when configured, so revoked sessions stop working; honours X-Tenant-ID only for a membership your resolver confirms; throws (the request gets 503) when the authority cannot be reached. |
| ServiceTokenProvider | SERVICE tokens via client_credentials + private_key_jwt, one cached token per audience, each verified before use. Credentials use the same JSON shape as the native owners' credential files. |
| createTokenIntrospector | POST /oauth/introspect with the caller's SERVICE token (audience authentication-service). |
| ServiceTokenProvider.exchange(subjectToken, audience) | RFC 8693 token exchange with the authentication-service credential, whose client must carry a tokenExchange allowlist. Returns a verified token for audience that acts for the person (act names this service, same sid), cached per subject token and target. See the authority's docs/sessions.md. |
npm test builds and runs the tests in test/ (real ES256 keys, local authority stand-in).
