Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/plugins/meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import type { FastifyBaseLogger, FastifySchema } from 'fastify';

import type { UnionOfConst } from '@graasp/sdk';

import { bustFileCache } from '../bustCache';
import { resolveDependency } from '../di/utils';
import { db } from '../drizzle/db';
import { authenticateAdminSharedSecret } from '../services/auth/plugins/passport/preHandlers';
import { SearchService } from '../services/item/plugins/publication/published/plugins/search/search.service';
import { assertIsError } from '../utils/assertions';
import {
Expand Down Expand Up @@ -110,10 +112,12 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
};
});

fastify.get('/api/version', async (_, reply) => {
// allow request cross origin
reply.header('Access-Control-Allow-Origin', '*');
return `${APP_VERSION} @ ${BUILD_TIMESTAMP}`;
fastify.get('/api/version', async () => {
return { version: APP_VERSION, buildTimestamp: BUILD_TIMESTAMP };
});

fastify.get('/api/bust-cache', { preHandler: authenticateAdminSharedSecret }, async () => {
await bustFileCache();
});
};

Expand Down
4 changes: 4 additions & 0 deletions src/services/auth/plugins/passport/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { MemberRepository } from '../../../member/member.repository';
import { MemberPasswordService } from '../password/password.service';
import { SHORT_TOKEN_PARAM } from './constants';
import { PassportStrategy } from './strategies';
import adminSharedSecretStrategy from './strategies/adminSharedSecret';
import emailChangeStrategy from './strategies/emailChange';
import jwtAppsStrategy from './strategies/jwtApps';
import jwtChallengeVerifierStrategy from './strategies/jwtChallengeVerifier';
Expand Down Expand Up @@ -57,6 +58,9 @@ const plugin: FastifyPluginAsync = async (fastify: FastifyInstance) => {
//-- Sessions Strategies --//
strictSessionStrategy(fastifyPassport);

//-- Shared Secret Strategy (machine-to-machine) --//
adminSharedSecretStrategy(fastifyPassport);

//-- Password Strategies --//
passwordStrategy(fastifyPassport, memberPasswordService, {
propagateError: true,
Expand Down
9 changes: 9 additions & 0 deletions src/services/auth/plugins/passport/preHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ export const guestAuthenticateAppsJWT = fastifyPassport.authenticate(
},
) as RouteShorthandHook<preHandlerHookHandler>;

/**
* Shared secret authentication for machine-to-machine routes.
* Requires `Authorization: Bearer <ADMIN_SHARED_SECRET>` header.
*/
export const authenticateAdminSharedSecret = fastifyPassport.authenticate(
PassportStrategy.AdminSharedSecret,
{ session: false },
) as RouteShorthandHook<preHandlerHookHandler>;

/**
* Pre-handler function that checks if the user meets at least one of the specified access preconditions.
* @param strategies The array of role strategies to check for access.
Expand Down
3 changes: 3 additions & 0 deletions src/services/auth/plugins/passport/strategies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ export enum PassportStrategy {

//-- From Password --//
Password = 'password',

//-- Shared Secret (machine-to-machine) --//
AdminSharedSecret = 'admin-shared-secret',
}
21 changes: 21 additions & 0 deletions src/services/auth/plugins/passport/strategies/adminSharedSecret.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Strategy } from 'passport-custom';

import { Authenticator } from '@fastify/passport';

import { ADMIN_SHARED_SECRET } from '../../../../../utils/config';
import { UnauthorizedMember } from '../../../../../utils/errors';
import { PassportStrategy } from '../strategies';
import type { StrictVerifiedCallback } from '../types';

export default (passport: Authenticator) => {

Check warning on line 10 in src/services/auth/plugins/passport/strategies/adminSharedSecret.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

The arrow function should be named.

See more on https://sonarcloud.io/project/issues?id=graasp_graasp&issues=AZ5JEgPeRiG7CBVeTtUm&open=AZ5JEgPeRiG7CBVeTtUm&pullRequest=2135
passport.use(
PassportStrategy.AdminSharedSecret,
new Strategy((req, done: StrictVerifiedCallback) => {
const authHeader = req.headers.authorization;
if (ADMIN_SHARED_SECRET && authHeader === `Bearer ${ADMIN_SHARED_SECRET}`) {
return done(null, {});
}
return done(new UnauthorizedMember(), false);
}),
);
};
2 changes: 2 additions & 0 deletions src/utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export const LOG_LEVEL: string | undefined = process.env.LOG_LEVEL;
export const APP_VERSION = process.env.APP_VERSION;
export const BUILD_TIMESTAMP = process.env.BUILD_TIMESTAMP;

export const ADMIN_SHARED_SECRET = process.env.ADMIN_SHARED_SECRET;

export const CLIENT_HOST = process.env.CLIENT_HOST ?? 'http://localhost:3114';

export const LIBRARY_HOST = process.env.LIBRARY_CLIENT_HOST ?? CLIENT_HOST;
Expand Down
Loading