Skip to content

Commit

Permalink
feat(api): add guard and decorator for authentication external integr…
Browse files Browse the repository at this point in the history
…ations
  • Loading branch information
Jozwiaczek committed Aug 9, 2021
1 parent d86674a commit 211c676
Show file tree
Hide file tree
Showing 11 changed files with 60 additions and 34 deletions.
4 changes: 4 additions & 0 deletions packages/api/src/interfaces/headers.types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface ExternalIntegrationsHeaders {
from?: string;
authorization?: string;
}
7 changes: 5 additions & 2 deletions packages/api/src/modules/auth/decorators/auth.decorator.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { applyDecorators, SetMetadata, UseGuards } from '@nestjs/common';

import { Role } from '../../../enums/role.enum';
import { constants } from '../../../utils';
import { OnlyAuthenticatedGuard } from '../guards/only-authenticated.guard';
import { RolesGuard } from '../guards/roles.guard';
import { ROLES_KEY } from './roles.decorator';

export const Auth = (...roles: Role[]) =>
applyDecorators(SetMetadata(ROLES_KEY, roles), UseGuards(OnlyAuthenticatedGuard, RolesGuard));
applyDecorators(
SetMetadata(constants.roles_key, roles),
UseGuards(OnlyAuthenticatedGuard, RolesGuard),
);
6 changes: 0 additions & 6 deletions packages/api/src/modules/auth/decorators/roles.decorator.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as Sentry from '@sentry/node';

import { CookieResponse } from '../../../interfaces/cookie-types';
import { TokenPayload } from '../../../interfaces/token-types';
import { constants } from '../../../utils';
import { UserRepository } from '../../repository/user.repository';
import { TokenService } from '../token/token.service';
import { TokenCookieService } from '../token/token-cookie.service';
Expand Down Expand Up @@ -30,7 +31,7 @@ export class OnlyAuthenticatedGuard implements CanActivate {
id: payload.sub,
email: payload.email,
});
scope.setTag('roles', String(payload.roles));
scope.setTag(constants.roles_key, String(payload.roles));
});

const { exp: accessTokenExp, sub: accessTokenSub, keepMeLoggedIn } = payload;
Expand Down
4 changes: 2 additions & 2 deletions packages/api/src/modules/auth/guards/roles.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { Reflector } from '@nestjs/core';

import { Role } from '../../../enums/role.enum';
import { TokenPayload } from '../../../interfaces/token-types';
import { ROLES_KEY } from '../decorators/roles.decorator';
import { constants } from '../../../utils';

@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}

canActivate(context: ExecutionContext): boolean {
const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [
const requiredRoles = this.reflector.getAllAndOverride<Role[]>(constants.roles_key, [
context.getHandler(),
context.getClass(),
]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { UseGuards } from '@nestjs/common';

import { ExternalIntegrationsAuthGuard } from '../guards/external-integrations-auth.guard';

export const ExternalIntegrationsAuth = () => UseGuards(ExternalIntegrationsAuthGuard);
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import { Controller, Get, Headers, Post } from '@nestjs/common';
import { Controller, Get, Post } from '@nestjs/common';

import { Auth } from '../auth/decorators/auth.decorator';
import { CookiePayload } from '../auth/decorators/cookiePayload.decorator';
import { UserFromCookiePayloadPipe } from '../auth/pipes/user-from-cookie-payload.pipe';
import { UserEntity } from '../database/entities/user.entity';
import { ExternalIntegrationsAuth } from './decorators/external-integrations-auth.decorator';
import { ExternalIntegrationsService } from './external-integrations.service';

interface ToggleGateHeaders {
from: string;
authorization: string;
}

@Controller('external-integrations')
export class ExternalIntegrationsController {
constructor(private readonly externalIntegrationsService: ExternalIntegrationsService) {}
Expand All @@ -31,8 +27,9 @@ export class ExternalIntegrationsController {
return this.externalIntegrationsService.removeToken(id, email);
}

@ExternalIntegrationsAuth()
@Get('toggle-gate')
toggleGate(@Headers() { authorization, from }: ToggleGateHeaders): Promise<string> {
return this.externalIntegrationsService.toggleGate(authorization, from);
toggleGate(): string {
return this.externalIntegrationsService.toggleGate();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,5 @@ import { ExternalIntegrationsService } from './external-integrations.service';
controllers: [ExternalIntegrationsController],
providers: [ExternalIntegrationsService],
imports: [WebsocketModule, UsersModule, AuthModule, RepositoryModule, TokenModule],
exports: [ExternalIntegrationsService],
})
export class ExternalIntegrationsModule {}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable, Logger, UnauthorizedException } from '@nestjs/common';
import { Injectable, Logger } from '@nestjs/common';
import { v4 as uuidV4 } from 'uuid';

import { UsersService } from '../users/users.service';
Expand Down Expand Up @@ -31,18 +31,7 @@ export class ExternalIntegrationsService {
this.logger.log(`External integrations token removed for user: ${email}`);
}

private async validateToken(token: string, email: string): Promise<true> {
const foundUser = await this.usersService.findOneByEmail(email);

if (!foundUser || token !== foundUser.externalIntegrationsToken) {
throw new UnauthorizedException();
}

return true;
}

async toggleGate(token: string, email: string): Promise<string> {
await this.validateToken(token, email);
toggleGate(): string {
// this.websocketGateway.toggleGate();
return 'Successfully open';
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {
BadRequestException,
CanActivate,
ExecutionContext,
Injectable,
UnauthorizedException,
} from '@nestjs/common';

import { UsersService } from '../../users/users.service';

@Injectable()
export class ExternalIntegrationsAuthGuard implements CanActivate {
constructor(private readonly usersService: UsersService) {}

public async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest<{ headers: ExternalIntegrationsHeaders }>();
const { authorization, from } = request.headers;

if (!authorization || !from) {
throw new BadRequestException();
}

const foundUser = await this.usersService.findOneByEmail(from);

if (!foundUser || authorization !== foundUser.externalIntegrationsToken) {
throw new UnauthorizedException();
}

return true;
}
}
5 changes: 4 additions & 1 deletion packages/api/src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ const clientEndpoints = {
passwordMagicLink: '/passwordRecovery/magicLink',
registrationMagicLink: '/registration',
};
export default { authTokens, clientEndpoints };

const roles_key = 'roles';

export default { authTokens, clientEndpoints, roles_key };

0 comments on commit 211c676

Please sign in to comment.