add ability to auth using api key
This commit is contained in:
parent
c68360c81f
commit
db7b02b629
|
@ -41,6 +41,7 @@
|
||||||
"ms": "^2.1.3",
|
"ms": "^2.1.3",
|
||||||
"p-timeout": "^6.0.0",
|
"p-timeout": "^6.0.0",
|
||||||
"passport": "^0.6.0",
|
"passport": "^0.6.0",
|
||||||
|
"passport-headerapikey": "^1.2.2",
|
||||||
"passport-jwt": "^4.0.0",
|
"passport-jwt": "^4.0.0",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
"passport-strategy": "^1.0.0",
|
"passport-strategy": "^1.0.0",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { JwtModule } from '@nestjs/jwt';
|
import { JwtModule } from '@nestjs/jwt';
|
||||||
import { PassportModule } from '@nestjs/passport';
|
import { PassportModule } from '@nestjs/passport';
|
||||||
|
import { ApiKeyDbModule } from '../../collections/apikey-db/apikey-db.module';
|
||||||
import { PreferenceDbModule } from '../../collections/preference-db/preference-db.module';
|
import { PreferenceDbModule } from '../../collections/preference-db/preference-db.module';
|
||||||
import { UserDbModule } from '../../collections/user-db/user-db.module';
|
import { UserDbModule } from '../../collections/user-db/user-db.module';
|
||||||
import {
|
import {
|
||||||
|
@ -9,6 +10,7 @@ import {
|
||||||
} from '../../config/late/jwt.config.service';
|
} from '../../config/late/jwt.config.service';
|
||||||
import { LateConfigModule } from '../../config/late/late-config.module';
|
import { LateConfigModule } from '../../config/late/late-config.module';
|
||||||
import { AuthManagerService } from './auth.service';
|
import { AuthManagerService } from './auth.service';
|
||||||
|
import { ApiKeyStrategy } from './guards/apikey.strategy';
|
||||||
import { GuestStrategy } from './guards/guest.strategy';
|
import { GuestStrategy } from './guards/guest.strategy';
|
||||||
import { JwtStrategy } from './guards/jwt.strategy';
|
import { JwtStrategy } from './guards/jwt.strategy';
|
||||||
import { LocalAuthStrategy } from './guards/local-auth.strategy';
|
import { LocalAuthStrategy } from './guards/local-auth.strategy';
|
||||||
|
@ -19,6 +21,7 @@ import { GuestService } from './guest.service';
|
||||||
UserDbModule,
|
UserDbModule,
|
||||||
PassportModule,
|
PassportModule,
|
||||||
PreferenceDbModule,
|
PreferenceDbModule,
|
||||||
|
ApiKeyDbModule,
|
||||||
LateConfigModule,
|
LateConfigModule,
|
||||||
JwtModule.registerAsync({
|
JwtModule.registerAsync({
|
||||||
useExisting: JwtConfigService,
|
useExisting: JwtConfigService,
|
||||||
|
@ -31,6 +34,7 @@ import { GuestService } from './guest.service';
|
||||||
JwtStrategy,
|
JwtStrategy,
|
||||||
GuestStrategy,
|
GuestStrategy,
|
||||||
JwtSecretProvider,
|
JwtSecretProvider,
|
||||||
|
ApiKeyStrategy,
|
||||||
GuestService,
|
GuestService,
|
||||||
],
|
],
|
||||||
exports: [UserDbModule, AuthManagerService],
|
exports: [UserDbModule, AuthManagerService],
|
||||||
|
|
62
backend/src/managers/auth/guards/apikey.strategy.ts
Normal file
62
backend/src/managers/auth/guards/apikey.strategy.ts
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
import { PassportStrategy } from '@nestjs/passport';
|
||||||
|
import { HeaderAPIKeyStrategy } from 'passport-headerapikey';
|
||||||
|
import { EUser, EUserSchema } from 'picsur-shared/dist/entities/user.entity';
|
||||||
|
import { HasFailed } from 'picsur-shared/dist/types';
|
||||||
|
import { IsApiKey } from 'picsur-shared/dist/validators/api-key.validator';
|
||||||
|
import { ApiKeyDbService } from '../../../collections/apikey-db/apikey-db.service';
|
||||||
|
import { EUserBackend2EUser } from '../../../models/transformers/user.transformer';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ApiKeyStrategy extends PassportStrategy(
|
||||||
|
HeaderAPIKeyStrategy,
|
||||||
|
'apikey',
|
||||||
|
) {
|
||||||
|
private readonly logger = new Logger(ApiKeyStrategy.name);
|
||||||
|
|
||||||
|
constructor(private readonly apikeyDB: ApiKeyDbService) {
|
||||||
|
super(
|
||||||
|
{
|
||||||
|
header: 'Authorization',
|
||||||
|
prefix: 'Api-Key ',
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
(
|
||||||
|
apikey: string,
|
||||||
|
verified: (err: Error | null, user?: Object, info?: Object) => void,
|
||||||
|
) => {
|
||||||
|
this.validate(apikey)
|
||||||
|
.then((user) => {
|
||||||
|
verified(null, user === false ? undefined : user);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
verified(err, undefined);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async validate(apikey: string): Promise<EUser | false> {
|
||||||
|
const apiValidation = await IsApiKey().safeParseAsync(apikey);
|
||||||
|
if (!apiValidation.success) {
|
||||||
|
this.logger.warn('Invalid apikey format: ' + apikey);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const apikeyResult = await this.apikeyDB.resolve(apikey);
|
||||||
|
if (HasFailed(apikeyResult)) {
|
||||||
|
this.logger.warn('Invalid apikey: ' + apikey);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = EUserBackend2EUser(apikeyResult.user);
|
||||||
|
|
||||||
|
const userValidation = await EUserSchema.safeParseAsync(user);
|
||||||
|
if (!userValidation.success) {
|
||||||
|
this.logger.error('Invalid user: ' + JSON.stringify(user));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return userValidation.data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ import { isPermissionsArray } from '../../../models/validators/permissions.valid
|
||||||
// This way a user will get his own account when logged in, but received guest permissions when not
|
// This way a user will get his own account when logged in, but received guest permissions when not
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MainAuthGuard extends AuthGuard(['jwt', 'guest']) {
|
export class MainAuthGuard extends AuthGuard(['apikey', 'jwt', 'guest']) {
|
||||||
private readonly logger = new Logger(MainAuthGuard.name);
|
private readonly logger = new Logger(MainAuthGuard.name);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
|
@ -20,10 +20,6 @@ export class ExperimentController {
|
||||||
@Request() req: AuthFasityRequest,
|
@Request() req: AuthFasityRequest,
|
||||||
@ReqUserID() thing: string,
|
@ReqUserID() thing: string,
|
||||||
): Promise<UserInfoResponse> {
|
): Promise<UserInfoResponse> {
|
||||||
const key = await this.apikeyDB.findOne("0SB7nCIkfhnAmf3Glejf0naUbI7dimhh", undefined);
|
|
||||||
|
|
||||||
console.log(key);
|
|
||||||
|
|
||||||
return req.user;
|
return req.user;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
yarn.lock
11
yarn.lock
|
@ -8741,6 +8741,16 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"passport-headerapikey@npm:^1.2.2":
|
||||||
|
version: 1.2.2
|
||||||
|
resolution: "passport-headerapikey@npm:1.2.2"
|
||||||
|
dependencies:
|
||||||
|
lodash: ^4.17.15
|
||||||
|
passport-strategy: ^1.0.0
|
||||||
|
checksum: 509b0d72225845fcb4d6a95acd76f98042bdee256bf11731ece2c8be8341235013f2150207148d7e8ed939e28857dea18503969842ad40bba7a9724396b94481
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"passport-jwt@npm:^4.0.0":
|
"passport-jwt@npm:^4.0.0":
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
resolution: "passport-jwt@npm:4.0.0"
|
resolution: "passport-jwt@npm:4.0.0"
|
||||||
|
@ -8991,6 +9001,7 @@ __metadata:
|
||||||
ms: ^2.1.3
|
ms: ^2.1.3
|
||||||
p-timeout: ^6.0.0
|
p-timeout: ^6.0.0
|
||||||
passport: ^0.6.0
|
passport: ^0.6.0
|
||||||
|
passport-headerapikey: ^1.2.2
|
||||||
passport-jwt: ^4.0.0
|
passport-jwt: ^4.0.0
|
||||||
passport-local: ^1.0.0
|
passport-local: ^1.0.0
|
||||||
passport-strategy: ^1.0.0
|
passport-strategy: ^1.0.0
|
||||||
|
|
Loading…
Reference in a new issue