refactor(core): Move JWT support into backend services (#41089)

This commit is contained in:
Charlie Kolb 2026-10-14 12:10:59 +00:00 committed by GitHub
parent 7920e6cf6b
commit b6d39e2d30
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
65 changed files with 138 additions and 91 deletions

2
OWNERS
View File

@ -30,6 +30,7 @@ packages/@n8n/backend-network/ @n8n-io/catalysts
packages/@n8n/backend-services/ @n8n-io/catalysts
packages/@n8n/backend-services/src/services/role.service.ts @n8n-io/iam
packages/@n8n/backend-services/src/services/role-cache.service.ts @n8n-io/iam
packages/@n8n/backend-services/src/services/jwt.service.ts @n8n-io/iam
packages/@n8n/backend-test-utils/ @n8n-io/catalysts
packages/@n8n/di/ @n8n-io/catalysts
packages/@n8n/errors/ @n8n-io/catalysts
@ -154,7 +155,6 @@ packages/cli/src/controllers/dynamic-node-parameters.controller.ts @n8n-io/node
packages/cli/src/controllers/e2e.controller.ts @n8n-io/qa-dx
# CLI services
packages/cli/src/services/jwt.service.ts @n8n-io/iam
packages/cli/src/services/user.service.ts @n8n-io/iam
packages/cli/src/services/password.utility.ts @n8n-io/iam
packages/cli/src/services/public-api-key.service.ts @n8n-io/iam

View File

@ -5,6 +5,26 @@ import { backendConfig } from '@n8n/eslint-config/backend';
export default defineConfig(
globalIgnores(['coverage/**', 'vitest.config.ts']),
backendConfig,
{
files: ['./src/**/*.ts'],
ignores: ['./src/services/jwt.service.ts', './src/**/__tests__/**'],
rules: {
'@typescript-eslint/no-restricted-imports': [
'error',
{
paths: [
{
name: 'jsonwebtoken',
allowImportNames: ['JsonWebTokenError', 'TokenExpiredError', 'NotBeforeError'],
allowTypeImports: true,
message: 'Sign and verify through JwtService.',
},
],
patterns: [{ group: ['jsonwebtoken/*'], message: 'Sign and verify through JwtService.' }],
},
],
},
},
{
rules: {
'n8n-local-rules/no-guardrail-disable': [

View File

@ -6,6 +6,30 @@ export default defineConfig({
extends: [backendConfig],
options: { typeAware: true },
ignorePatterns: ['coverage/**'],
overrides: [
{
files: ['./src/**/*.ts'],
excludeFiles: ['./src/services/jwt.service.ts', './src/**/__tests__/**'],
rules: {
'no-restricted-imports': [
'error',
{
paths: [
{
name: 'jsonwebtoken',
allowImportNames: ['JsonWebTokenError', 'TokenExpiredError', 'NotBeforeError'],
allowTypeImports: true,
message: 'Sign and verify through JwtService.',
},
],
patterns: [
{ group: ['jsonwebtoken/*'], message: 'Sign and verify through JwtService.' },
],
},
],
},
},
],
rules: {
'n8n-local-rules/no-guardrail-disable': [
'error',

View File

@ -28,14 +28,16 @@
"@n8n/backend-network": "workspace:*",
"@n8n/config": "workspace:*",
"@n8n/constants": "workspace:*",
"@n8n/decorators": "workspace:*",
"@n8n/db": "workspace:*",
"@n8n/decorators": "workspace:*",
"@n8n/di": "workspace:*",
"@n8n/errors": "workspace:*",
"@n8n/permissions": "workspace:*",
"@n8n/utils": "workspace:*",
"cache-manager": "catalog:",
"ioredis": "5.3.2",
"jsonwebtoken": "catalog:",
"n8n-core": "workspace:*",
"n8n-workflow": "workspace:*"
},
"peerDependencies": {
@ -47,6 +49,7 @@
"@n8n/oxlint-config": "workspace:*",
"@n8n/typescript-config": "workspace:*",
"@n8n/vitest-config": "workspace:*",
"@types/jsonwebtoken": "catalog:",
"@types/lodash": "catalog:",
"@vitest/coverage-v8": "catalog:",
"eslint": "catalog:",

View File

@ -55,3 +55,16 @@ export {
type Jwk,
type SkippedJwk,
} from './services/oauth-discovery-client';
export {
type PurposedSignOptions,
type PurposedVerifyOptions,
JwtService,
type JwtPayload,
} from './services/jwt.service';
export {
TOKEN_PURPOSES,
type TokenPurpose,
API_KEY_PURPOSES,
LEGACY_UNBOUND_PURPOSES,
} from './services/token-purposes';

View File

@ -5,7 +5,7 @@ import type { InstanceSettings } from 'n8n-core';
import { generateKeyPairSync } from 'node:crypto';
import { mock } from 'vitest-mock-extended';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '../jwt.service';
const getJwtSecret = (svc: JwtService) => (svc as unknown as { jwtSecret: string }).jwtSecret;

View File

@ -6,11 +6,7 @@ import { createHash, type KeyObject } from 'crypto';
import jwt from 'jsonwebtoken';
import { InstanceSettings, type DeploymentStateRepo } from 'n8n-core';
import {
LEGACY_UNBOUND_PURPOSES,
TOKEN_PURPOSES,
type TokenPurpose,
} from '@/services/token-purposes';
import { LEGACY_UNBOUND_PURPOSES, TOKEN_PURPOSES, type TokenPurpose } from './token-purposes';
/**
* `audience` is omitted on purpose: it is derived from the token's purpose, so

View File

@ -0,0 +1,12 @@
import { mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
const testFolder = mkdtempSync(join(tmpdir(), 'n8n-backend-services-'));
process.env.N8N_USER_FOLDER = testFolder;
process.env.N8N_ENCRYPTION_KEY = 'test-key';
afterAll(() => {
rmSync(testFolder, { recursive: true, force: true });
});

View File

@ -3,6 +3,7 @@ import { configDefaults, mergeConfig } from 'vitest/config';
export default mergeConfig(createVitestConfigWithDecorators(), {
test: {
setupFiles: ['./test/setup-test-folder.ts'],
// One fork per file: tests register mocks in the shared `@n8n/di` Container.
pool: 'forks',
// Vitest's default exclude does not cover dist; stale compiled tests there fail as CJS.

View File

@ -208,8 +208,6 @@ export default defineConfig(
// JwtService itself: verifying tokens signed by a foreign key, which JwtService cannot
// verify. Do NOT add a file for any other reason.
files: [
// Owns the signing key and derives every audience from a purpose.
'./src/services/jwt.service.ts',
// Verifies subject tokens with a foreign key from the trusted-key store,
// against the audience that key is registered for.
'./src/modules/token-exchange/services/token-exchange.service.ts',

View File

@ -210,8 +210,6 @@ export default defineConfig({
// JwtService itself: verifying tokens signed by a foreign key, which JwtService cannot
// verify. Do NOT add a file for any other reason.
files: [
// Owns the signing key and derives every audience from a purpose.
'./src/services/jwt.service.ts',
// Verifies subject tokens with a foreign key from the trusted-key store,
// against the audience that key is registered for.
'./src/modules/token-exchange/services/token-exchange.service.ts',

View File

@ -4,8 +4,7 @@ import { mock } from 'vitest-mock-extended';
import { AuthService } from '@/auth/auth.service';
import type { MfaService } from '@/mfa/mfa.service';
import type { JwtService } from '@/services/jwt.service';
import type { UrlService } from '@n8n/backend-services';
import type { JwtService, UrlService } from '@n8n/backend-services';
describe('AuthService Browser ID Whitelist', () => {
let authService: AuthService;

View File

@ -16,8 +16,7 @@ import { AuthService } from '@/auth/auth.service';
import { AUTH_COOKIE_NAME } from '@/constants';
import type { License } from '@/license';
import type { MfaService } from '@/mfa/mfa.service';
import { JwtService } from '@/services/jwt.service';
import type { UrlService } from '@n8n/backend-services';
import { JwtService, type UrlService } from '@n8n/backend-services';
describe('AuthService', () => {
const browserId = 'test-browser-id';

View File

@ -15,8 +15,7 @@ import { AUTH_COOKIE_NAME, RESPONSE_ERROR_MESSAGES } from '@/constants';
import { AuthError, ForbiddenError } from '@n8n/errors';
import { License } from '@/license';
import { MfaService } from '@/mfa/mfa.service';
import { JwtService } from '@/services/jwt.service';
import { UrlService } from '@n8n/backend-services';
import { JwtService, UrlService } from '@n8n/backend-services';
interface AuthJwtPayload {
/** User Id */

View File

@ -32,8 +32,7 @@ import { OtelService } from '@/modules/otel/otel.service';
import { NodeTypes } from '@/node-types';
import { PostHogClient } from '@/posthog';
import { PollJobProvider } from '@/scheduling/poll-trigger-node/poll-job-provider';
import { JwtService } from '@/services/jwt.service';
import { RoleCacheService } from '@n8n/backend-services';
import { JwtService, RoleCacheService } from '@n8n/backend-services';
import { ShutdownService } from '@/shutdown/shutdown.service';
import { TaskRunnerModule } from '@/task-runners/task-runner-module';

View File

@ -11,8 +11,7 @@ import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
import { PubSubRegistry } from '@/scaling/pubsub/pubsub.registry';
import { Subscriber } from '@/scaling/pubsub/subscriber.service';
import { SystemTaskRunner } from '@/scheduling/system-tasks/system-task-runner';
import { JwtService } from '@/services/jwt.service';
import { RedisClientService } from '@n8n/backend-services';
import { JwtService, RedisClientService } from '@n8n/backend-services';
import { WebhookServer } from '@/webhooks/webhook-server';
import { BaseCommand } from '../base-command';

View File

@ -1,6 +1,6 @@
import type { Logger } from '@n8n/backend-common';
import { uninstallGlobalProxyAgent } from '@n8n/backend-network/testing';
import type { EventService } from '@n8n/backend-services';
import { type EventService, JwtService, RedisClientService } from '@n8n/backend-services';
import { mockInstance } from '@n8n/backend-test-utils';
import type { ExecutionsConfig } from '@n8n/config';
import { GlobalConfig } from '@n8n/config';
@ -33,8 +33,6 @@ import { Subscriber } from '@/scaling/pubsub/subscriber.service';
import { WorkerServer } from '@/scaling/worker-server';
import { WorkerStatusService } from '@/scaling/worker-status.service.ee';
import { SystemTaskRunner } from '@/scheduling/system-tasks/system-task-runner';
import { JwtService } from '@/services/jwt.service';
import { RedisClientService } from '@n8n/backend-services';
import { ShutdownService } from '@/shutdown/shutdown.service';
import { TaskRunnerModule } from '@/task-runners/task-runner-module';

View File

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { EventService, UrlService, RoleCacheService } from '@n8n/backend-services';
import { EventService, UrlService, RoleCacheService, JwtService } from '@n8n/backend-services';
import { HTML_NONCE_PLACEHOLDER, LICENSE_FEATURES } from '@n8n/constants';
import {
AuthRolesService,
@ -39,7 +39,6 @@ import { DurableScheduler } from '@/scheduling/durable-scheduler';
import { PollJobProvider } from '@/scheduling/poll-trigger-node/poll-job-provider';
import { mainSystemTasks } from '@/scheduling/system-tasks/main-system-tasks';
import { Server } from '@/server';
import { JwtService } from '@/services/jwt.service';
import { WaitTracker } from '@/wait-tracker';

View File

@ -11,7 +11,7 @@ import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
import { Publisher } from '@/scaling/pubsub/publisher.service';
import { PubSubRegistry } from '@/scaling/pubsub/pubsub.registry';
import { Subscriber } from '@/scaling/pubsub/subscriber.service';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import { WebhookServer } from '@/webhooks/webhook-server';
import { BaseCommand } from './base-command';

View File

@ -21,7 +21,7 @@ import { resolveQueueName, resolveWorkerPoolName } from '@/scaling/queue-name';
import type { ScalingService } from '@/scaling/scaling.service';
import type { WorkerServer, WorkerServerEndpointsConfig } from '@/scaling/worker-server';
import { WorkerStatusService } from '@/scaling/worker-status.service.ee';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import { BaseCommand } from './base-command';

View File

@ -4,8 +4,7 @@ import { mock } from 'vitest-mock-extended';
import { NotFoundError } from '@n8n/errors';
import type { UserRequest } from '@/requests';
import type { JwtService } from '@/services/jwt.service';
import type { UrlService } from '@n8n/backend-services';
import type { JwtService, UrlService } from '@n8n/backend-services';
import type { UserService } from '@/services/user.service';
import { UsersController } from '../users.controller';

View File

@ -32,8 +32,7 @@ import { Response } from 'express';
import { AuthService } from '@/auth/auth.service';
import { ForbiddenError, NotFoundError } from '@n8n/errors';
import { UserRequest } from '@/requests';
import { JwtService } from '@/services/jwt.service';
import { UrlService } from '@n8n/backend-services';
import { JwtService, UrlService } from '@n8n/backend-services';
import { UserService } from '@/services/user.service';
@RestController('/users')

View File

@ -2,8 +2,7 @@ import { mock } from 'vitest-mock-extended';
import type { GlobalConfig } from '@n8n/config';
import type { InstanceSettings } from 'n8n-core';
import { JwtService } from '@/services/jwt.service';
import type { UrlService } from '@n8n/backend-services';
import { JwtService, type UrlService } from '@n8n/backend-services';
import { TeamsArmTemplateService } from '../teams-arm-template.service';

View File

@ -4,10 +4,9 @@ import type { GlobalConfig } from '@n8n/config';
import type { User } from '@n8n/db';
import type { InstanceSettings } from 'n8n-core';
import { JwtService } from '@/services/jwt.service';
import { JwtService, type UrlService } from '@n8n/backend-services';
import type { CredentialsService } from '@/credentials/credentials.service';
import type { UrlService } from '@n8n/backend-services';
import type { Agent } from '../../../../entities/agent.entity';
import { AgentCredentialLookupService } from '../../../agent-credential-lookup.service';

View File

@ -2,8 +2,7 @@ import { Service } from '@n8n/di';
import { UserError } from 'n8n-workflow';
import { createHmac } from 'node:crypto';
import { JwtService } from '@/services/jwt.service';
import { UrlService } from '@n8n/backend-services';
import { JwtService, UrlService } from '@n8n/backend-services';
import { sanitiseAppName } from '../../integration-helpers';

View File

@ -9,7 +9,7 @@ import { ScopedJwtStrategy } from '@/modules/token-exchange/services/scoped-jwt.
import { TOKEN_EXCHANGE_ISSUER } from '@/modules/token-exchange/token-exchange.types';
import { ApiKeyAuthStrategy } from '@/services/api-key-auth.strategy';
import { AuthStrategyRegistry } from '@/services/auth-strategy.registry';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import { SessionCookieAuthStrategy } from '@/services/session-cookie-auth.strategy';
import { createMember, createOwner, createOwnerWithApiKey } from '@test-integration/db/users';

View File

@ -3,7 +3,7 @@ import type { ApiKeyRepository, User, TokenGrant } from '@n8n/db';
import { mock } from 'vitest-mock-extended';
import type { AuthStrategyRegistry } from '@/services/auth-strategy.registry';
import type { JwtService } from '@/services/jwt.service';
import type { JwtService } from '@n8n/backend-services';
import { McpServerApiKeyService } from '../mcp-api-key.service';

View File

@ -7,7 +7,7 @@ import { generateKeyPairSync } from 'node:crypto';
import { mock, mockDeep } from 'vitest-mock-extended';
import type { InstanceSettings } from 'n8n-core';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import type { McpCallerAuth } from '@/services/oauth-token-verifier-proxy.service';
import { OAuthTokenVerifierProxy } from '@/services/oauth-token-verifier-proxy.service';
import { Telemetry } from '@/telemetry';

View File

@ -6,7 +6,7 @@ import { ensureError } from '@n8n/utils/errors/ensure-error';
import { ApiKeyAudience } from 'n8n-workflow';
import { AuthStrategyRegistry } from '@/services/auth-strategy.registry';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import { UserWithContext } from '@/services/oauth-token-verifier-proxy.service';
const API_KEY_AUDIENCE: ApiKeyAudience = 'mcp-server-api';

View File

@ -4,7 +4,7 @@ import { NextFunction, Response, Request } from 'express';
import { ensureError } from '@n8n/utils/errors/ensure-error';
import { AuthError } from '@n8n/errors';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import {
OAuthTokenVerifierProxy,
type TelemetryAuthContext,

View File

@ -3,9 +3,8 @@ import type { User } from '@n8n/db';
import { Container } from '@n8n/di';
import { McpSettingsService } from '@/modules/mcp/mcp.settings.service';
import { JwtService } from '@/services/jwt.service';
import { JwtService, UrlService } from '@n8n/backend-services';
import { ProtectedResourceRegistry } from '@/services/protected-resource.registry';
import { UrlService } from '@n8n/backend-services';
import { createOwner, createMember } from '@test-integration/db/users';
import { setupTestServer } from '@test-integration/utils';

View File

@ -3,7 +3,7 @@ import { JsonWebTokenError, TokenExpiredError } from 'jsonwebtoken';
import { mock } from 'vitest-mock-extended';
import { ZodError } from 'zod';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import { OAuthSessionService, type OAuthSessionPayload } from '../oauth-session.service';

View File

@ -7,7 +7,7 @@ import { createLocalJWKSet, jwtVerify } from 'jose';
import { Cipher, InstanceSettings } from 'n8n-core';
import { generateKeyPairSync } from 'node:crypto';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import {
OAUTH_SIGNING_ALGORITHM,

View File

@ -11,7 +11,7 @@ import type { InstanceSettings } from 'n8n-core';
import type { KeyObject } from 'node:crypto';
import { createHmac, createPublicKey, generateKeyPairSync } from 'node:crypto';
import { JwtService } from '@/services/jwt.service';
import { JwtService, type UrlService } from '@n8n/backend-services';
import type { AccessToken } from '../database/entities/oauth-access-token.entity';
import type { RefreshToken } from '../database/entities/oauth-refresh-token.entity';
@ -31,7 +31,6 @@ import { McpProtectedResource } from '@/modules/mcp/mcp-protected-resource';
import type { McpConfig } from '@/modules/mcp/mcp.config';
import type { McpSettingsService } from '@/modules/mcp/mcp.settings.service';
import { ProtectedResourceRegistry } from '@/services/protected-resource.registry';
import type { UrlService } from '@n8n/backend-services';
import type { WorkflowFinderService } from '@/workflows/workflow-finder.service';
const LEGACY_HMAC_SECRET = 'legacy-hmac-secret';

View File

@ -5,7 +5,7 @@ import type { JsonWebKey, KeyObject } from 'node:crypto';
import { createPrivateKey, sign as cryptoSign } from 'node:crypto';
import { mock } from 'vitest-mock-extended';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import { OAUTH_SIGNING_KEY_TYPE } from '../oauth-signing-key.constants';
import { OAuthSigningKeyService } from '../oauth-signing-key.service';

View File

@ -16,9 +16,7 @@ import { setupTestServer } from '@test-integration/utils';
import { MCP_TRIGGER_NODE_TYPE } from '@/constants';
import { OAuthTokenService } from '@/modules/oauth-server/oauth-token.service';
import { CacheService } from '@n8n/backend-services';
import { UrlService } from '@n8n/backend-services';
import { JwtService } from '@/services/jwt.service';
import { CacheService, UrlService, JwtService } from '@n8n/backend-services';
import { OAuthClientRepository } from '../database/repositories/oauth-client.repository';
import type { OAuthSessionPayload } from '../oauth-session.service';

View File

@ -3,7 +3,7 @@ import { Service } from '@n8n/di';
import { Response } from 'express';
import { z } from 'zod';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
const oauthSessionPayloadSchema = z.object({
clientId: z.string(),

View File

@ -12,7 +12,7 @@ import type { JsonWebKey, KeyObject } from 'node:crypto';
import { createPrivateKey, createPublicKey, generateKeyPair } from 'node:crypto';
import { promisify } from 'node:util';
import { JwtService, type JwtPayload } from '@/services/jwt.service';
import { JwtService, type JwtPayload } from '@n8n/backend-services';
import {
ACCESS_TOKEN_TYPES,

View File

@ -15,14 +15,13 @@ import { UnexpectedError } from 'n8n-workflow';
import { randomBytes, randomUUID } from 'node:crypto';
import { authorizeAgainstGrant } from '@/modules/inbound-auth-core/grant-authorization';
import { JwtService } from '@/services/jwt.service';
import { JwtService, UrlService } from '@n8n/backend-services';
import type {
OAuthTokenVerifier,
UserWithContext,
} from '@/services/oauth-token-verifier-proxy.service';
import type { ProtectedResource } from '@/services/protected-resource.registry';
import { ProtectedResourceRegistry } from '@/services/protected-resource.registry';
import { UrlService } from '@n8n/backend-services';
import { WorkflowFinderService } from '@/workflows/workflow-finder.service';
import { AccessTokenRepository } from './database/repositories/oauth-access-token.repository';

View File

@ -2,8 +2,7 @@ import type { ApiKey, User } from '@n8n/db';
import type { Mocked } from 'vitest';
import { mock } from 'vitest-mock-extended';
import type { JwtService } from '@/services/jwt.service';
import type { UrlService } from '@n8n/backend-services';
import type { JwtService, UrlService } from '@n8n/backend-services';
import type { ScimApiKeyRepository } from '../database/scim-api-key.repository';
import { ScimTokenService } from '../scim-token.service';

View File

@ -2,7 +2,7 @@ import { ApiKey, BaseRepository, TransactionRunner, type OperationContext } from
import { Service } from '@n8n/di';
import { DataSource } from '@n8n/typeorm';
import { TOKEN_PURPOSES } from '@/services/token-purposes';
import { TOKEN_PURPOSES } from '@n8n/backend-services';
/**
* SCIM provisioning keys are ordinary API keys reserved by their audience.

View File

@ -2,8 +2,7 @@ import { type OperationContext, type User } from '@n8n/db';
import { Service } from '@n8n/di';
import { randomUUID } from 'crypto';
import { JwtService } from '@/services/jwt.service';
import { UrlService } from '@n8n/backend-services';
import { JwtService, UrlService } from '@n8n/backend-services';
import { ScimApiKeyRepository } from './database/scim-api-key.repository';

View File

@ -31,8 +31,7 @@ vi.mock('openid-client', async (importOriginal) => {
import { BadRequestError, ForbiddenError } from '@n8n/errors';
import { type ProvisioningService } from '@/modules/provisioning.ee/provisioning.service.ee';
import { Publisher } from '@/scaling/pubsub/publisher.service';
import type { JwtService } from '@/services/jwt.service';
import type { UrlService } from '@n8n/backend-services';
import type { JwtService, UrlService } from '@n8n/backend-services';
import * as ssoHelpers from '@/sso.ee/sso-helpers';
import { OIDC_PREFERENCES_DB_KEY } from '../constants';

View File

@ -22,8 +22,7 @@ import { inspect } from 'util';
import { BadRequestError, ForbiddenError } from '@n8n/errors';
import { buildOidcClaimsContext } from '@/modules/provisioning.ee/claims-context.builder';
import { ProvisioningService } from '@/modules/provisioning.ee/provisioning.service.ee';
import { JwtService } from '@/services/jwt.service';
import { UrlService } from '@n8n/backend-services';
import { JwtService, UrlService } from '@n8n/backend-services';
import {
assertAuthenticationMethodCanBeEnabled,
getCurrentAuthenticationMethod,

View File

@ -5,7 +5,7 @@ import { Container } from '@n8n/di';
import type { InstanceSettings } from 'n8n-core';
import { mock } from 'vitest-mock-extended';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import { createMember, createOwner } from '@test-integration/db/users';
import { TOKEN_EXCHANGE_ISSUER } from '../../token-exchange.types';

View File

@ -4,7 +4,7 @@ import type { InstanceSettings } from 'n8n-core';
import type { Mocked } from 'vitest';
import { mock } from 'vitest-mock-extended';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import { TOKEN_EXCHANGE_ISSUER, type IssuedJwtPayload } from '../../token-exchange.types';
import { ScopedJwtStrategy } from '../scoped-jwt.strategy';

View File

@ -4,7 +4,7 @@ import jwt from 'jsonwebtoken';
import { mock } from 'vitest-mock-extended';
import { AuthError, BadRequestError } from '@n8n/errors';
import type { JwtService } from '@/services/jwt.service';
import type { JwtService } from '@n8n/backend-services';
import type { TokenExchangeConfig } from '../../token-exchange.config';
import type { ResolvedTrustedKey } from '../../token-exchange.schemas';

View File

@ -5,7 +5,7 @@ import { getApiKeyScopesForRole } from '@n8n/permissions';
import { JsonWebTokenError, TokenExpiredError } from 'jsonwebtoken';
import type { AuthStrategy, AuthStrategyOptions } from '@/services/auth-strategy.types';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import { TOKEN_EXCHANGE_ISSUER, type IssuedJwtPayload } from '../token-exchange.types';

View File

@ -4,7 +4,7 @@ import { Service } from '@n8n/di';
import { randomUUID } from 'crypto';
import jwt from 'jsonwebtoken';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import { TokenExchangeConfig } from '../token-exchange.config';
import { TokenExchangeAuthError, TokenExchangeRequestError } from '../token-exchange.errors';

View File

@ -14,7 +14,7 @@ import { createOwnerWithApiKey } from '@test-integration/db/users';
import { retryUntil } from '@test-integration/retry-until';
import { ApiKeyAuthStrategy } from '../api-key-auth.strategy';
import { JwtService } from '../jwt.service';
import { JwtService } from '@n8n/backend-services';
import { API_KEY_ISSUER } from '../public-api-key.service';
const mockReqWith = (apiKey: string): AuthenticatedRequest =>

View File

@ -7,7 +7,7 @@ import jsonwebtoken from 'jsonwebtoken';
import { Cipher, InstanceSettings } from 'n8n-core';
import { mock } from 'vitest-mock-extended';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
const INSTANCE_ENCRYPTION_KEY = 'signing-secrets-instance-key';

View File

@ -11,7 +11,7 @@ import { mock } from 'vitest-mock-extended';
import { createAdminWithApiKey, createOwnerWithApiKey } from '@test-integration/db/users';
import { JwtService } from '../jwt.service';
import { JwtService } from '@n8n/backend-services';
import { PublicApiKeyService } from '../public-api-key.service';
const instanceSettings = mock<InstanceSettings>({ encryptionKey: 'test-key' });

View File

@ -6,7 +6,7 @@ import { mock } from 'vitest-mock-extended';
import { BadRequestError, NotFoundError } from '@n8n/errors';
import type { UserManagementMailer } from '@/user-management/email';
import type { JwtService } from '../jwt.service';
import type { JwtService } from '@n8n/backend-services';
import { PublicApiKeyService } from '../public-api-key.service';
vi.mock('@n8n/permissions', async () => ({

View File

@ -1,5 +1,5 @@
import { InviteUsersRequestDto } from '@n8n/api-types';
import { type EventService, UrlService, type RoleService } from '@n8n/backend-services';
import { type EventService, UrlService, type RoleService, JwtService } from '@n8n/backend-services';
import { mockInstance } from '@n8n/backend-test-utils';
import { GlobalConfig } from '@n8n/config';
import {
@ -30,7 +30,6 @@ import { UserService } from '@/services/user.service';
import * as ssoHelpers from '@/sso.ee/sso-helpers';
import type { UserManagementMailer } from '@/user-management/email';
import { JwtService } from '../jwt.service';
import type { OwnershipTransferService } from '../ownership-transfer/ownership-transfer.service';
import type { OwnershipService } from '../ownership.service';
import type { ProjectService } from '../project.service.ee';

View File

@ -8,8 +8,7 @@ import { TokenExpiredError } from 'jsonwebtoken';
import { isApiKeyAuthEnabled } from '@/public-api';
import type { AuthStrategy, AuthStrategyOptions } from './auth-strategy.types';
import { JwtService } from './jwt.service';
import { API_KEY_PURPOSES } from './token-purposes';
import { JwtService, API_KEY_PURPOSES } from '@n8n/backend-services';
import { API_KEY_AUDIENCE, API_KEY_ISSUER, PREFIX_LEGACY_API_KEY } from './public-api-key.service';
const API_KEY_HEADER = 'x-n8n-api-key';

View File

@ -24,7 +24,7 @@ import { randomUUID } from 'crypto';
import { BadRequestError, NotFoundError } from '@n8n/errors';
import { UserManagementMailer } from '@/user-management/email';
import { JwtService } from './jwt.service';
import { JwtService } from '@n8n/backend-services';
export const API_KEY_AUDIENCE: ApiKeyAudience = 'public-api';
export const API_KEY_ISSUER = 'n8n';

View File

@ -1,6 +1,6 @@
import type { RoleChangeRequestDto } from '@n8n/api-types';
import { Logger } from '@n8n/backend-common';
import { EventService, UrlService, RoleService } from '@n8n/backend-services';
import { EventService, UrlService, RoleService, JwtService } from '@n8n/backend-services';
import { GlobalConfig } from '@n8n/config';
import type { PublicUser } from '@n8n/db';
import {
@ -30,7 +30,6 @@ import type { IUserSettings } from 'n8n-workflow';
import { UserError } from 'n8n-workflow';
import { validate as uuidValidate } from 'uuid';
import { JwtService } from './jwt.service';
import { OwnershipService } from './ownership.service';
import { ProjectService } from './project.service.ee';
import { PublicApiKeyService } from './public-api-key.service';

View File

@ -1,4 +1,4 @@
import { EventService } from '@n8n/backend-services';
import { EventService, JwtService } from '@n8n/backend-services';
import { randomValidPassword, testDb } from '@n8n/backend-test-utils';
import type { User } from '@n8n/db';
import { GLOBAL_MEMBER_ROLE, GLOBAL_OWNER_ROLE, UserRepository } from '@n8n/db';
@ -9,7 +9,6 @@ import config from '@/config';
import { AUTH_COOKIE_NAME } from '@/constants';
import type { RelayEventMap } from '@/events/maps/relay.event-map';
import { MfaService } from '@/mfa/mfa.service';
import { JwtService } from '@/services/jwt.service';
import { LOGGED_OUT_RESPONSE_BODY } from './shared/constants';
import { createUser, createUserShell } from './shared/db/users';

View File

@ -1,4 +1,4 @@
import { EventService } from '@n8n/backend-services';
import { EventService, JwtService } from '@n8n/backend-services';
import {
mockInstance,
randomEmail,
@ -18,7 +18,6 @@ import { PROJECT_OWNER_ROLE_SLUG } from '@n8n/permissions';
import { Not } from '@n8n/typeorm';
import { ExternalHooks } from '@/external-hooks';
import { JwtService } from '@/services/jwt.service';
import { PasswordUtility } from '@/services/password.utility';
import { UserManagementMailer } from '@/user-management/email';

View File

@ -28,7 +28,7 @@ import { License } from '@/license';
import { ProvisioningService } from '@/modules/provisioning.ee/provisioning.service.ee';
import { OIDC_CLIENT_SECRET_REDACTED_VALUE } from '@/modules/sso-oidc/constants';
import { OidcService } from '@/modules/sso-oidc/oidc.service.ee';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import { createCustomRoleWithScopes, createScope } from '@test-integration/db/roles';
import { createUser } from '@test-integration/db/users';

View File

@ -18,7 +18,7 @@ import { AuthService } from '@/auth/auth.service';
import config from '@/config';
import { ExternalHooks } from '@/external-hooks';
import { License } from '@/license';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import { PasswordUtility } from '@/services/password.utility';
import { setCurrentAuthenticationMethod } from '@/sso.ee/sso-helpers';
import { UserManagementMailer } from '@/user-management/email';

View File

@ -23,7 +23,7 @@ import { mock } from 'vitest-mock-extended';
import { TOKEN_EXCHANGE_ISSUER } from '@/modules/token-exchange/token-exchange.types';
import { CredentialsTester } from '@/services/credentials-tester.service';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import { affixRoleToSaveCredential, createCredentials } from '@test-integration/db/credentials';
import {
createAnnotationTags,

View File

@ -14,7 +14,7 @@ import {
type IssuedJwtPayload,
type TokenExchangeSuccessResponse,
} from '@/modules/token-exchange/token-exchange.types';
import { JwtService } from '@/services/jwt.service';
import { JwtService } from '@n8n/backend-services';
import { createUser } from '../shared/db/users';
import * as utils from '../shared/utils';

View File

@ -1883,6 +1883,12 @@ importers:
ioredis:
specifier: 5.3.2
version: 5.3.2(supports-color@8.1.1)
jsonwebtoken:
specifier: 'catalog:'
version: 9.0.3
n8n-core:
specifier: workspace:*
version: link:../../core
n8n-workflow:
specifier: workspace:*
version: link:../../workflow
@ -1902,6 +1908,9 @@ importers:
'@n8n/vitest-config':
specifier: workspace:*
version: link:../vitest-config
'@types/jsonwebtoken':
specifier: 'catalog:'
version: 9.0.10
'@types/lodash':
specifier: 'catalog:'
version: 4.17.17