Skip to content

Commit

Permalink
auth startegy impl
Browse files Browse the repository at this point in the history
  • Loading branch information
sszafGCA committed Nov 9, 2023
1 parent d6e0922 commit 175e495
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { JwtStrategy } from './strategy/jwt.strategy';
import { LdapStrategy } from './strategy/ldap.strategy';
import { LocalStrategy } from './strategy/local.strategy';
import { Oauth2Strategy } from './strategy/oauth2.strategy';
import { XApiKeyStrategy } from './strategy/x-api-key.strategy';

// values copied from Algorithm definition. Type does not exist at runtime and can't be checked anymore otherwise
const algorithms = [
Expand Down Expand Up @@ -76,6 +77,7 @@ const jwtModuleOptions: JwtModuleOptions = {
LdapService,
LdapStrategy,
Oauth2Strategy,
XApiKeyStrategy,
],
exports: [AuthenticationService],
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface IXApiKeyConfig {
ADMIN_API__ALLOWED_API_KEYS: string[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ConfigService } from '@nestjs/config';
import Strategy from 'passport-headerapikey';
import { IXApiKeyConfig } from '../config/x-api-key.config';

@Injectable()
export class XApiKeyStrategy extends PassportStrategy(Strategy, 'api-key') {
private readonly allowedApiKeys: string[];

constructor(private readonly configService: ConfigService<IXApiKeyConfig, true>) {
super(
{ header: 'X-API-KEY', prefix: '' },
true,
// eslint-disable-next-line @typescript-eslint/require-await
async (apiKey: string, done: (error: Error | null, data: boolean | null) => void) => this.validate(apiKey, done)
);
this.allowedApiKeys = this.configService.get<string[]>('ADMIN_API__ALLOWED_API_KEYS');
}

public validate = (apiKey: string, done: (error: Error | null, data: boolean | null) => void) => {
if (this.allowedApiKeys.includes(apiKey)) {
done(null, true);
}
done(new UnauthorizedException(), null);
};
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Controller, Post, Query } from '@nestjs/common';
import { Controller, Post, Query, UseGuards } from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { Authenticate } from '@src/modules/authentication/decorator/auth.decorator';
import { ForbiddenOperationError, ValidationError } from '@shared/common';
import { AuthGuard } from '@nestjs/passport';
import { DeletionRequestUc } from '../uc/deletion-request.uc';
import { DeletionExecutionParams } from './dto';

@ApiTags('DeletionExecutions')
@Authenticate('jwt')
@UseGuards(AuthGuard('api-key'))
@Controller('deletionExecutions')
export class AccountController {
export class DeletionExecutionsController {
constructor(private readonly deletionRequestUc: DeletionRequestUc) {}

@Post()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Body, Controller, Get, Param, Post } from '@nestjs/common';
import { Body, Controller, Get, Param, Post, UseGuards } from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { Authenticate } from '@src/modules/authentication/decorator/auth.decorator';
import { ForbiddenOperationError, ValidationError } from '@shared/common';
import { AuthGuard } from '@nestjs/passport';
import { DeletionRequestUc } from '../uc/deletion-request.uc';
import { DeletionRequestResponse } from './dto/deletion-request.response';
import { DeletionRequestBodyProps } from './dto/deletion-request.body.params';
import { DeletionRequestLogResponse } from './dto';

@ApiTags('DeletionRequests')
@Authenticate('jwt')
@UseGuards(AuthGuard('api-key'))
@Controller('deletionRequests')
export class DeletionRequestsController {
constructor(private readonly deletionRequestUc: DeletionRequestUc) {}
Expand Down
10 changes: 8 additions & 2 deletions apps/server/src/modules/deletion/deletion.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { Module } from '@nestjs/common';
import { LoggerModule } from '@src/core/logger';
import { ConfigService } from '@nestjs/config';
import { DeletionRequestService } from './services/deletion-request.service';
import { DeletionRequestRepo } from './repo/deletion-request.repo';
import { AuthenticationModule } from '../authentication';
import { DeletionRequestsController } from './controller/deletion-requests.controller';
import { DeletionExecutionsController } from './controller/deletion-executions.controller';
import { IXApiKeyConfig } from '../authentication/config/x-api-key.config';

@Module({
imports: [LoggerModule],
providers: [DeletionRequestService, DeletionRequestRepo],
imports: [LoggerModule, AuthenticationModule],
controllers: [DeletionRequestsController, DeletionExecutionsController],
providers: [DeletionRequestService, DeletionRequestRepo, ConfigService<IXApiKeyConfig, true>],
exports: [DeletionRequestService],
})
export class DeletionModule {}
7 changes: 6 additions & 1 deletion apps/server/src/modules/server/server.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { IFilesStorageClientConfig } from '@modules/files-storage-client';
import type { IUserConfig } from '@modules/user';
import type { ICommonCartridgeConfig } from '@modules/learnroom/common-cartridge';
import { IMailConfig } from '@src/infra/mail/interfaces/mail-config';
import { IXApiKeyConfig } from '../authentication/config/x-api-key.config';

export enum NodeEnvType {
TEST = 'test',
Expand All @@ -21,7 +22,8 @@ export interface IServerConfig
IAccountConfig,
IIdentityManagementConfig,
ICommonCartridgeConfig,
IMailConfig {
IMailConfig,
IXApiKeyConfig {
NODE_ENV: string;
SC_DOMAIN: string;
}
Expand All @@ -44,6 +46,9 @@ const config: IServerConfig = {
ADDITIONAL_BLACKLISTED_EMAIL_DOMAINS: (Configuration.get('ADDITIONAL_BLACKLISTED_EMAIL_DOMAINS') as string)
.split(',')
.map((domain) => domain.trim()),
ADMIN_API__ALLOWED_API_KEYS: (Configuration.get('ADMIN_API__ALLOWED_API_KEYS') as string)
.split(',')
.map((apiKey) => apiKey.trim()),
};

export const serverConfig = () => config;
20 changes: 20 additions & 0 deletions config/default.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1410,6 +1410,26 @@
"SECRET_ES_MERLIN_COUNTIES_CREDENTIALS"
]
}
},
"ADMIN_API": {
"type": "object",
"description": "Configuration of the schulcloud-server's admin API.",
"properties": {
"ENABLED": {
"type": "boolean",
"default": true,
"description": "Flag to turn on/off the Admin API."
},
"PORT": {
"type": "number",
"default": 4030,
"description": "Port of the exposed Admin API server."
},
"ALLOWED_API_KEYS": {
"type": "string",
"description": "Allowed Admin API keys (for accessing the Admin API)."
}
}
}
}
}
19 changes: 19 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@
"papaparse": "^5.1.1",
"passport": "^0.6.0",
"passport-custom": "^1.1.1",
"passport-headerapikey": "^1.2.2",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"prom-client": "^13.1.0",
Expand Down

0 comments on commit 175e495

Please sign in to comment.