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

BC-8019 Switch to asymmetric signing of JWT #5294

Merged
merged 45 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
539f32e
Switch to asymmetric signing
dyedwiper Oct 15, 2024
92dbf9d
Adjust configs
dyedwiper Oct 15, 2024
2f0b221
Fix tests
dyedwiper Oct 15, 2024
35d13fb
Make secret combination of private and public key in feathers
dyedwiper Oct 16, 2024
4f906da
Add tests
dyedwiper Oct 16, 2024
c50292b
Update typ of JWT
dyedwiper Oct 16, 2024
d14c39a
Update authConfig in tests
dyedwiper Oct 16, 2024
dda6c8e
Merge branch 'main' into BC-8019-asymmetric-jwt
dyedwiper Oct 16, 2024
0747c68
Merge branch 'BC-8019-asymmetric-jwt' of github.com:hpi-schul-cloud/s…
dyedwiper Oct 16, 2024
b09f55c
Merge branch 'main' into BC-8019-asymmetric-jwt
dyedwiper Oct 17, 2024
44821a8
Handle new lines in keys
dyedwiper Oct 17, 2024
c53d5ff
Merge branch 'BC-8019-asymmetric-jwt' of github.com:hpi-schul-cloud/s…
dyedwiper Oct 17, 2024
b3bbb70
Clean up strategy tests
dyedwiper Oct 18, 2024
d7e04f8
Use JwtModuleOptionsFactory
dyedwiper Oct 18, 2024
a8353fd
Use factory method instead of class
dyedwiper Oct 18, 2024
1376f58
Remove authConfig
dyedwiper Oct 18, 2024
8f49fe2
Remove unnecessary props in AuthGuardConfig
dyedwiper Oct 18, 2024
6bbb8b1
Add AuthGuardConfig to files-storage
dyedwiper Oct 18, 2024
75daeff
Change setting of options in authn service
dyedwiper Oct 21, 2024
b665f02
Add authn test modules
dyedwiper Oct 21, 2024
f6188ff
Fix authn service test
dyedwiper Oct 21, 2024
c5515d9
Merge branch 'main' into BC-8019-asymmetric-jwt
dyedwiper Oct 21, 2024
41fe72f
Change iss and aud of JWT
dyedwiper Oct 21, 2024
1ae5dff
Merge branch 'BC-8019-asymmetric-jwt' of github.com:hpi-schul-cloud/s…
dyedwiper Oct 21, 2024
6eb471b
Fix reading of config for other apps
dyedwiper Oct 21, 2024
1f133c3
Add JWT_SIGNING_ALGORITHM as env var
dyedwiper Oct 25, 2024
36185c6
Add check of algorithm in JWT validation
dyedwiper Oct 25, 2024
23dadda
Add check of issuer and audience in JWT validation
dyedwiper Oct 25, 2024
2d0b20a
Remove unnecessary consts
dyedwiper Oct 25, 2024
68a9764
Merge branch 'main' into BC-8019-asymmetric-jwt
dyedwiper Oct 25, 2024
f44de44
Skip broken test
dyedwiper Oct 25, 2024
41565fb
Add SC_Domain to preview-generator-configmap
dyedwiper Oct 25, 2024
334a78f
Merge branch 'main' into BC-8019-asymmetric-jwt
bischofmax Oct 28, 2024
c66aff6
Add values to top-level configs where forgotten
dyedwiper Oct 28, 2024
aa04b55
Merge branch 'BC-8019-asymmetric-jwt' of github.com:hpi-schul-cloud/s…
dyedwiper Oct 28, 2024
cc7ff5b
Add factory for strategy options to satisfy SonarCloud
dyedwiper Oct 29, 2024
c768092
Merge branch 'main' into BC-8019-asymmetric-jwt
dyedwiper Oct 29, 2024
e946b82
Use getOrThrow to read values from ConfigService
dyedwiper Oct 29, 2024
937130f
Define defaultMikroOrmOptions in for AdminApiServerModule separately …
dyedwiper Oct 29, 2024
2c11a11
Merge branch 'BC-8019-asymmetric-jwt' of github.com:hpi-schul-cloud/s…
dyedwiper Oct 29, 2024
014c915
Add JWT_PUBLIC_KEY to configmap of admin-api-server
dyedwiper Oct 29, 2024
7601962
Add JWT_PUBLIC_KEY to configmap of preview-generator
dyedwiper Oct 29, 2024
0933cd2
Merge branch 'main' into BC-8019-asymmetric-jwt
dyedwiper Oct 29, 2024
5c0fa9d
Merge branch 'main' into BC-8019-asymmetric-jwt
dyedwiper Oct 30, 2024
ed0ebd6
Merge branch 'main' into BC-8019-asymmetric-jwt
bischofmax Nov 4, 2024
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
1 change: 1 addition & 0 deletions apps/server/src/infra/auth-guard/mapper/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './current-user.factory';
export * from './jwt.factory';
export * from './jwt-strategy-options.factory';
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ConfigService } from '@nestjs/config';
import { JwtFromRequestFunction, StrategyOptions } from 'passport-jwt';
import { AuthGuardConfig } from '../auth-guard.config';

export class JwtStrategyOptionsFactory {
static build(
jwtFromRequestFunction: JwtFromRequestFunction,
configService: ConfigService<AuthGuardConfig>
): StrategyOptions {
const publicKey = configService.get<string>('JWT_PUBLIC_KEY');
dyedwiper marked this conversation as resolved.
Show resolved Hide resolved
const algorithm = configService.getOrThrow<string>('JWT_SIGNING_ALGORITHM');

const options = {
jwtFromRequest: jwtFromRequestFunction,
secretOrKey: publicKey,
ignoreExpiration: false,
algorithms: [algorithm],
issuer: configService.get<string>('SC_DOMAIN'),
audience: configService.get<string>('SC_DOMAIN'),
};

return options;
}
}
15 changes: 3 additions & 12 deletions apps/server/src/infra/auth-guard/strategy/jwt.strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,21 @@ import { Injectable, UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PassportStrategy } from '@nestjs/passport';
import { extractJwtFromHeader } from '@shared/common';
import { Algorithm } from 'jsonwebtoken';
import { Strategy } from 'passport-jwt';
import { JwtValidationAdapter } from '../adapter';
import { AuthGuardConfig } from '../auth-guard.config';
import { ICurrentUser, JwtPayload } from '../interface';
import { CurrentUserBuilder } from '../mapper';
import { CurrentUserBuilder, JwtStrategyOptionsFactory } from '../mapper';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
private readonly jwtValidationAdapter: JwtValidationAdapter,
configService: ConfigService<AuthGuardConfig>
) {
const publicKey = configService.get<string>('JWT_PUBLIC_KEY');
const algorithm = configService.get<Algorithm>('JWT_SIGNING_ALGORITHM');
const strategyOptions = JwtStrategyOptionsFactory.build(extractJwtFromHeader, configService);

super({
jwtFromRequest: extractJwtFromHeader,
ignoreExpiration: false,
secretOrKey: publicKey,
algorithms: [algorithm],
issuer: configService.get<string>('SC_DOMAIN'),
audience: configService.get<string>('SC_DOMAIN'),
});
super(strategyOptions);
}

async validate(payload: JwtPayload): Promise<ICurrentUser> {
Expand Down
16 changes: 4 additions & 12 deletions apps/server/src/infra/auth-guard/strategy/ws-jwt.strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,21 @@ import { ConfigService } from '@nestjs/config';
import { PassportStrategy } from '@nestjs/passport';
import { WsException } from '@nestjs/websockets';
import { JwtExtractor } from '@shared/common';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { Strategy } from 'passport-jwt';
import { JwtValidationAdapter } from '../adapter';
import { AuthGuardConfig } from '../auth-guard.config';
import { ICurrentUser, JwtPayload, StrategyType } from '../interface';
import { CurrentUserBuilder } from '../mapper';
import { CurrentUserBuilder, JwtStrategyOptionsFactory } from '../mapper';

@Injectable()
export class WsJwtStrategy extends PassportStrategy(Strategy, StrategyType.WS_JWT) {
constructor(
private readonly jwtValidationAdapter: JwtValidationAdapter,
configService: ConfigService<AuthGuardConfig>
) {
const publicKey = configService.get<string>('JWT_PUBLIC_KEY');
const algorithm = configService.get<Algorithm>('JWT_SIGNING_ALGORITHM');
const strategyOptions = JwtStrategyOptionsFactory.build(JwtExtractor.fromCookie('jwt'), configService);

super({
jwtFromRequest: ExtractJwt.fromExtractors([JwtExtractor.fromCookie('jwt')]),
ignoreExpiration: false,
secretOrKey: publicKey,
algorithms: [algorithm],
issuer: configService.get<string>('SC_DOMAIN'),
audience: configService.get<string>('SC_DOMAIN'),
});
super(strategyOptions);
}

async validate(payload: JwtPayload): Promise<ICurrentUser> {
Expand Down
Loading