fix: config service precedence
This commit is contained in:
@@ -80,7 +80,7 @@ import { loadInfraConfiguration } from './infra-config/helper';
|
|||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
UserModule,
|
UserModule,
|
||||||
AuthModule,
|
AuthModule.register(),
|
||||||
AdminModule,
|
AdminModule,
|
||||||
UserSettingsModule,
|
UserSettingsModule,
|
||||||
UserEnvironmentsModule,
|
UserEnvironmentsModule,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import {
|
|||||||
Body,
|
Body,
|
||||||
Controller,
|
Controller,
|
||||||
Get,
|
Get,
|
||||||
InternalServerErrorException,
|
|
||||||
Post,
|
Post,
|
||||||
Query,
|
Query,
|
||||||
Request,
|
Request,
|
||||||
@@ -31,11 +30,15 @@ import { MicrosoftSSOGuard } from './guards/microsoft-sso-.guard';
|
|||||||
import { ThrottlerBehindProxyGuard } from 'src/guards/throttler-behind-proxy.guard';
|
import { ThrottlerBehindProxyGuard } from 'src/guards/throttler-behind-proxy.guard';
|
||||||
import { SkipThrottle } from '@nestjs/throttler';
|
import { SkipThrottle } from '@nestjs/throttler';
|
||||||
import { AUTH_PROVIDER_NOT_SPECIFIED } from 'src/errors';
|
import { AUTH_PROVIDER_NOT_SPECIFIED } from 'src/errors';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
|
||||||
@UseGuards(ThrottlerBehindProxyGuard)
|
@UseGuards(ThrottlerBehindProxyGuard)
|
||||||
@Controller({ path: 'auth', version: '1' })
|
@Controller({ path: 'auth', version: '1' })
|
||||||
export class AuthController {
|
export class AuthController {
|
||||||
constructor(private authService: AuthService) {}
|
constructor(
|
||||||
|
private authService: AuthService,
|
||||||
|
private configService: ConfigService,
|
||||||
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Route to initiate magic-link auth for a users email
|
** Route to initiate magic-link auth for a users email
|
||||||
@@ -45,8 +48,14 @@ export class AuthController {
|
|||||||
@Body() authData: SignInMagicDto,
|
@Body() authData: SignInMagicDto,
|
||||||
@Query('origin') origin: string,
|
@Query('origin') origin: string,
|
||||||
) {
|
) {
|
||||||
if (!authProviderCheck(AuthProvider.EMAIL))
|
if (
|
||||||
|
!authProviderCheck(
|
||||||
|
AuthProvider.EMAIL,
|
||||||
|
this.configService.get('INFRA.VITE_ALLOWED_AUTH_PROVIDERS'),
|
||||||
|
)
|
||||||
|
) {
|
||||||
throwHTTPErr({ message: AUTH_PROVIDER_NOT_SPECIFIED, statusCode: 404 });
|
throwHTTPErr({ message: AUTH_PROVIDER_NOT_SPECIFIED, statusCode: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
const deviceIdToken = await this.authService.signInMagicLink(
|
const deviceIdToken = await this.authService.signInMagicLink(
|
||||||
authData.email,
|
authData.email,
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { GithubStrategy } from './strategies/github.strategy';
|
|||||||
import { MicrosoftStrategy } from './strategies/microsoft.strategy';
|
import { MicrosoftStrategy } from './strategies/microsoft.strategy';
|
||||||
import { AuthProvider, authProviderCheck } from './helper';
|
import { AuthProvider, authProviderCheck } from './helper';
|
||||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
|
import { loadInfraConfiguration } from 'src/infra-config/helper';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -28,14 +29,29 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [AuthService, JwtStrategy, RTJwtStrategy],
|
||||||
AuthService,
|
|
||||||
JwtStrategy,
|
|
||||||
RTJwtStrategy,
|
|
||||||
...(authProviderCheck(AuthProvider.GOOGLE) ? [GoogleStrategy] : []),
|
|
||||||
...(authProviderCheck(AuthProvider.GITHUB) ? [GithubStrategy] : []),
|
|
||||||
...(authProviderCheck(AuthProvider.MICROSOFT) ? [MicrosoftStrategy] : []),
|
|
||||||
],
|
|
||||||
controllers: [AuthController],
|
controllers: [AuthController],
|
||||||
})
|
})
|
||||||
export class AuthModule {}
|
export class AuthModule {
|
||||||
|
static async register() {
|
||||||
|
const env = await loadInfraConfiguration();
|
||||||
|
const allowedAuthProviders = env.INFRA.VITE_ALLOWED_AUTH_PROVIDERS;
|
||||||
|
|
||||||
|
const providers = [
|
||||||
|
...(authProviderCheck(AuthProvider.GOOGLE, allowedAuthProviders)
|
||||||
|
? [GoogleStrategy]
|
||||||
|
: []),
|
||||||
|
...(authProviderCheck(AuthProvider.GITHUB, allowedAuthProviders)
|
||||||
|
? [GithubStrategy]
|
||||||
|
: []),
|
||||||
|
...(authProviderCheck(AuthProvider.MICROSOFT, allowedAuthProviders)
|
||||||
|
? [MicrosoftStrategy]
|
||||||
|
: []),
|
||||||
|
];
|
||||||
|
|
||||||
|
return {
|
||||||
|
module: AuthModule,
|
||||||
|
providers,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,14 +3,25 @@ import { AuthGuard } from '@nestjs/passport';
|
|||||||
import { AuthProvider, authProviderCheck, throwHTTPErr } from '../helper';
|
import { AuthProvider, authProviderCheck, throwHTTPErr } from '../helper';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { AUTH_PROVIDER_NOT_SPECIFIED } from 'src/errors';
|
import { AUTH_PROVIDER_NOT_SPECIFIED } from 'src/errors';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GithubSSOGuard extends AuthGuard('github') implements CanActivate {
|
export class GithubSSOGuard extends AuthGuard('github') implements CanActivate {
|
||||||
|
constructor(private readonly configService: ConfigService) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
canActivate(
|
canActivate(
|
||||||
context: ExecutionContext,
|
context: ExecutionContext,
|
||||||
): boolean | Promise<boolean> | Observable<boolean> {
|
): boolean | Promise<boolean> | Observable<boolean> {
|
||||||
if (!authProviderCheck(AuthProvider.GITHUB))
|
if (
|
||||||
|
!authProviderCheck(
|
||||||
|
AuthProvider.GITHUB,
|
||||||
|
this.configService.get('INFRA.VITE_ALLOWED_AUTH_PROVIDERS'),
|
||||||
|
)
|
||||||
|
) {
|
||||||
throwHTTPErr({ message: AUTH_PROVIDER_NOT_SPECIFIED, statusCode: 404 });
|
throwHTTPErr({ message: AUTH_PROVIDER_NOT_SPECIFIED, statusCode: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
return super.canActivate(context);
|
return super.canActivate(context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,25 @@ import { AuthGuard } from '@nestjs/passport';
|
|||||||
import { AuthProvider, authProviderCheck, throwHTTPErr } from '../helper';
|
import { AuthProvider, authProviderCheck, throwHTTPErr } from '../helper';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { AUTH_PROVIDER_NOT_SPECIFIED } from 'src/errors';
|
import { AUTH_PROVIDER_NOT_SPECIFIED } from 'src/errors';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GoogleSSOGuard extends AuthGuard('google') implements CanActivate {
|
export class GoogleSSOGuard extends AuthGuard('google') implements CanActivate {
|
||||||
|
constructor(private readonly configService: ConfigService) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
canActivate(
|
canActivate(
|
||||||
context: ExecutionContext,
|
context: ExecutionContext,
|
||||||
): boolean | Promise<boolean> | Observable<boolean> {
|
): boolean | Promise<boolean> | Observable<boolean> {
|
||||||
if (!authProviderCheck(AuthProvider.GOOGLE))
|
if (
|
||||||
|
!authProviderCheck(
|
||||||
|
AuthProvider.GOOGLE,
|
||||||
|
this.configService.get('INFRA.VITE_ALLOWED_AUTH_PROVIDERS'),
|
||||||
|
)
|
||||||
|
) {
|
||||||
throwHTTPErr({ message: AUTH_PROVIDER_NOT_SPECIFIED, statusCode: 404 });
|
throwHTTPErr({ message: AUTH_PROVIDER_NOT_SPECIFIED, statusCode: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
return super.canActivate(context);
|
return super.canActivate(context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,20 +3,31 @@ import { AuthGuard } from '@nestjs/passport';
|
|||||||
import { AuthProvider, authProviderCheck, throwHTTPErr } from '../helper';
|
import { AuthProvider, authProviderCheck, throwHTTPErr } from '../helper';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { AUTH_PROVIDER_NOT_SPECIFIED } from 'src/errors';
|
import { AUTH_PROVIDER_NOT_SPECIFIED } from 'src/errors';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MicrosoftSSOGuard
|
export class MicrosoftSSOGuard
|
||||||
extends AuthGuard('microsoft')
|
extends AuthGuard('microsoft')
|
||||||
implements CanActivate
|
implements CanActivate
|
||||||
{
|
{
|
||||||
|
constructor(private readonly configService: ConfigService) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
canActivate(
|
canActivate(
|
||||||
context: ExecutionContext,
|
context: ExecutionContext,
|
||||||
): boolean | Promise<boolean> | Observable<boolean> {
|
): boolean | Promise<boolean> | Observable<boolean> {
|
||||||
if (!authProviderCheck(AuthProvider.MICROSOFT))
|
if (
|
||||||
|
!authProviderCheck(
|
||||||
|
AuthProvider.MICROSOFT,
|
||||||
|
this.configService.get('INFRA.VITE_ALLOWED_AUTH_PROVIDERS'),
|
||||||
|
)
|
||||||
|
) {
|
||||||
throwHTTPErr({
|
throwHTTPErr({
|
||||||
message: AUTH_PROVIDER_NOT_SPECIFIED,
|
message: AUTH_PROVIDER_NOT_SPECIFIED,
|
||||||
statusCode: 404,
|
statusCode: 404,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return super.canActivate(context);
|
return super.canActivate(context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import * as cookie from 'cookie';
|
|||||||
import { AUTH_PROVIDER_NOT_SPECIFIED, COOKIES_NOT_FOUND } from 'src/errors';
|
import { AUTH_PROVIDER_NOT_SPECIFIED, COOKIES_NOT_FOUND } from 'src/errors';
|
||||||
import { throwErr } from 'src/utils';
|
import { throwErr } from 'src/utils';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
import { loadInfraConfiguration } from 'src/infra-config/helper';
|
||||||
|
|
||||||
enum AuthTokenType {
|
enum AuthTokenType {
|
||||||
ACCESS_TOKEN = 'access_token',
|
ACCESS_TOKEN = 'access_token',
|
||||||
@@ -117,18 +118,18 @@ export const subscriptionContextCookieParser = (rawCookies: string) => {
|
|||||||
* @param provider Provider we want to check the presence of
|
* @param provider Provider we want to check the presence of
|
||||||
* @returns Boolean if provider specified is present or not
|
* @returns Boolean if provider specified is present or not
|
||||||
*/
|
*/
|
||||||
export function authProviderCheck(provider: string) {
|
export function authProviderCheck(
|
||||||
const configService = new ConfigService();
|
provider: string,
|
||||||
|
VITE_ALLOWED_AUTH_PROVIDERS: string,
|
||||||
|
) {
|
||||||
if (!provider) {
|
if (!provider) {
|
||||||
throwErr(AUTH_PROVIDER_NOT_SPECIFIED);
|
throwErr(AUTH_PROVIDER_NOT_SPECIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
const envVariables = configService.get('VITE_ALLOWED_AUTH_PROVIDERS')
|
const envVariables = VITE_ALLOWED_AUTH_PROVIDERS
|
||||||
? configService
|
? VITE_ALLOWED_AUTH_PROVIDERS.split(',').map((provider) =>
|
||||||
.get('VITE_ALLOWED_AUTH_PROVIDERS')
|
provider.trim().toUpperCase(),
|
||||||
.split(',')
|
)
|
||||||
.map((provider) => provider.trim().toUpperCase())
|
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
if (!envVariables.includes(provider.toUpperCase())) return false;
|
if (!envVariables.includes(provider.toUpperCase())) return false;
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ export class GithubStrategy extends PassportStrategy(Strategy) {
|
|||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
) {
|
) {
|
||||||
super({
|
super({
|
||||||
clientID: configService.get('GITHUB_CLIENT_ID'),
|
clientID: configService.get('INFRA.GITHUB_CLIENT_ID'),
|
||||||
clientSecret: configService.get('GITHUB_CLIENT_SECRET'),
|
clientSecret: configService.get('INFRA.GITHUB_CLIENT_SECRET'),
|
||||||
callbackURL: configService.get('GITHUB_CALLBACK_URL'),
|
callbackURL: configService.get('GITHUB_CALLBACK_URL'),
|
||||||
scope: [configService.get('GITHUB_SCOPE')],
|
scope: [configService.get('GITHUB_SCOPE')],
|
||||||
store: true,
|
store: true,
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ export class GoogleStrategy extends PassportStrategy(Strategy) {
|
|||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
) {
|
) {
|
||||||
super({
|
super({
|
||||||
clientID: configService.get('GOOGLE_CLIENT_ID'),
|
clientID: configService.get('INFRA.GOOGLE_CLIENT_ID'),
|
||||||
clientSecret: configService.get('GOOGLE_CLIENT_SECRET'),
|
clientSecret: configService.get('INFRA.GOOGLE_CLIENT_SECRET'),
|
||||||
callbackURL: configService.get('GOOGLE_CALLBACK_URL'),
|
callbackURL: configService.get('GOOGLE_CALLBACK_URL'),
|
||||||
scope: configService.get('GOOGLE_SCOPE').split(','),
|
scope: configService.get('GOOGLE_SCOPE').split(','),
|
||||||
passReqToCallback: true,
|
passReqToCallback: true,
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ export class MicrosoftStrategy extends PassportStrategy(Strategy) {
|
|||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
) {
|
) {
|
||||||
super({
|
super({
|
||||||
clientID: configService.get('MICROSOFT_CLIENT_ID'),
|
clientID: configService.get('INFRA.MICROSOFT_CLIENT_ID'),
|
||||||
clientSecret: configService.get('MICROSOFT_CLIENT_SECRET'),
|
clientSecret: configService.get('INFRA.MICROSOFT_CLIENT_SECRET'),
|
||||||
callbackURL: configService.get('MICROSOFT_CALLBACK_URL'),
|
callbackURL: configService.get('MICROSOFT_CALLBACK_URL'),
|
||||||
scope: [configService.get('MICROSOFT_SCOPE')],
|
scope: [configService.get('MICROSOFT_SCOPE')],
|
||||||
tenant: configService.get('MICROSOFT_TENANT'),
|
tenant: configService.get('MICROSOFT_TENANT'),
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export async function loadInfraConfiguration() {
|
|||||||
environmentObject[infraConfig.name] = infraConfig.value;
|
environmentObject[infraConfig.name] = infraConfig.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
return environmentObject;
|
return { INFRA: environmentObject };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,7 +24,10 @@ export async function loadInfraConfiguration() {
|
|||||||
* (Docker will re-start the app)
|
* (Docker will re-start the app)
|
||||||
*/
|
*/
|
||||||
export function stopApp() {
|
export function stopApp() {
|
||||||
|
console.log('Stopping app in 5 seconds...');
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
console.log('Stopping app now...');
|
||||||
process.exit();
|
process.exit();
|
||||||
}, 5000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ async function bootstrap() {
|
|||||||
console.log(`Running in production: ${configService.get('PRODUCTION')}`);
|
console.log(`Running in production: ${configService.get('PRODUCTION')}`);
|
||||||
console.log(`Port: ${configService.get('PORT')}`);
|
console.log(`Port: ${configService.get('PORT')}`);
|
||||||
|
|
||||||
checkEnvironmentAuthProvider();
|
checkEnvironmentAuthProvider(
|
||||||
|
configService.get('VITE_ALLOWED_AUTH_PROVIDERS'),
|
||||||
|
);
|
||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
session({
|
session({
|
||||||
|
|||||||
@@ -162,24 +162,23 @@ export function isValidLength(title: string, length: number) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is called by bootstrap() in main.ts
|
* This function is called by bootstrap() in main.ts
|
||||||
* It checks if the "VITE_ALLOWED_AUTH_PROVIDERS" environment variable is properly set or not.
|
* It checks if the "VITE_ALLOWED_AUTH_PROVIDERS" environment variable is properly set or not.
|
||||||
* If not, it throws an error.
|
* If not, it throws an error.
|
||||||
*/
|
*/
|
||||||
export function checkEnvironmentAuthProvider() {
|
export function checkEnvironmentAuthProvider(
|
||||||
const configService = new ConfigService();
|
VITE_ALLOWED_AUTH_PROVIDERS: string,
|
||||||
|
) {
|
||||||
if (!configService.get('VITE_ALLOWED_AUTH_PROVIDERS')) {
|
if (!VITE_ALLOWED_AUTH_PROVIDERS) {
|
||||||
throw new Error(ENV_NOT_FOUND_KEY_AUTH_PROVIDERS);
|
throw new Error(ENV_NOT_FOUND_KEY_AUTH_PROVIDERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (configService.get('VITE_ALLOWED_AUTH_PROVIDERS') === '') {
|
if (VITE_ALLOWED_AUTH_PROVIDERS === '') {
|
||||||
throw new Error(ENV_EMPTY_AUTH_PROVIDERS);
|
throw new Error(ENV_EMPTY_AUTH_PROVIDERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
const givenAuthProviders = configService
|
const givenAuthProviders = VITE_ALLOWED_AUTH_PROVIDERS.split(',').map(
|
||||||
.get('VITE_ALLOWED_AUTH_PROVIDERS')
|
(provider) => provider.toLocaleUpperCase(),
|
||||||
.split(',')
|
);
|
||||||
.map((provider) => provider.toLocaleUpperCase());
|
|
||||||
const supportedAuthProviders = Object.values(AuthProvider).map(
|
const supportedAuthProviders = Object.values(AuthProvider).map(
|
||||||
(provider: string) => provider.toLocaleUpperCase(),
|
(provider: string) => provider.toLocaleUpperCase(),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user