add ability to auth using api key

This commit is contained in:
rubikscraft 2022-09-03 14:46:39 +02:00
parent c68360c81f
commit db7b02b629
No known key found for this signature in database
GPG key ID: 1463EBE9200A5CD4
6 changed files with 79 additions and 5 deletions

View file

@ -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",

View file

@ -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],

View 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;
}
}

View file

@ -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(

View file

@ -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;
} }
} }

View file

@ -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