Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JWT and api keys authentication fixes #519

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
39 changes: 18 additions & 21 deletions packages/api/src/@core/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ export class AuthService {
}
}

async validateUser(user_id: string) {
const user = await this.prisma.users.findUnique({
where: {
id_user: user_id,
},
});

return user;
}

async getApiKeys(project_id: string) {
try {
return await this.prisma.api_keys.findMany({
Expand Down Expand Up @@ -352,43 +362,30 @@ export class AuthService {

async validateApiKey(apiKey: string): Promise<boolean> {
try {
// Decode the JWT to verify if it's valid and get the payload
const decoded = this.jwtService.verify(apiKey, {
secret: process.env.JWT_SECRET,
});

//const hashed_api_key = this.hashApiKey(apiKey);
const saved_api_key = await this.prisma.api_keys.findUnique({
where: {
api_key_hash: apiKey,
},
});

if (!saved_api_key) {
throw new ReferenceError('Api Key undefined');
}
if (String(decoded.projectId) !== String(saved_api_key.id_project)) {
throw new ReferenceError(
'Failed to validate API key: projectId mismatch.',
);
return false;
}

// Validate that the JWT payload matches the provided userId and projectId
if (String(decoded.sub) !== String(saved_api_key.id_user)) {
throw new ReferenceError(
'Failed to validate API key: userId mismatch.',
);
if (
String(decoded.projectId) !== String(saved_api_key.id_project) ||
String(decoded.sub) !== String(saved_api_key.id_user)
) {
return false;
}

return true;
} catch (error) {
throwTypedError(
new AuthError({
name: 'VALIDATE_API_KEY_ERROR',
message: 'AuthService.validateApiKey() call failed',
cause: error,
}),
this.logger,
);
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HeaderAPIKeyStrategy } from 'passport-headerapikey';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { HeaderAPIKeyStrategy } from 'passport-headerapikey';
import { AuthService } from '../auth.service';

@Injectable()
Expand All @@ -18,16 +18,15 @@ export class ApiKeyStrategy extends PassportStrategy(
if (!isValid) {
return done(new UnauthorizedException('Invalid API Key'), null);
}
//console.log('validating api request... : ' + req.user);
// If the API key is valid, attach the user to the request object
req.user = { ...req.user, apiKeyValidated: true };

// If valid, we now have the user info from the API key validation process
return done(null, req.user);
} catch (error) {
return done(error, false);
if (error instanceof UnauthorizedException) {
return done(error, false);
}
return done(new UnauthorizedException('Invalid API Key'), null);
}
},
);
}
}
}
10 changes: 8 additions & 2 deletions packages/api/src/@core/auth/strategies/jwt.strategy.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import * as dotenv from 'dotenv';
import { AuthService } from '../auth.service';
dotenv.config();

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
constructor() {
constructor(private authService: AuthService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
Expand All @@ -15,6 +16,11 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
}

async validate(payload: any) {
const user = await this.authService.validateUser(payload.sub);
if (!user) {
throw new UnauthorizedException();
}

return {
id_user: payload.sub,
email: payload.email,
Expand Down
Loading