Closed okonon closed 10 months ago
Good question, simple answer :D
You have two ways to apply the protection logic.
@Authentication
or @Authorization
For your use case, you should have to remove the @Authentication
class decorator, that's all ;)
import { Authentication, AuthenticationGuard, CognitoUser } from '@nestjs-cognito/auth';
// @Authentication() just don't use this class decorator
@Controller(URL)
export class AuthController {
constructor(
private readonly authService: AuthService,
private userActivityService: UserActivityService
) {}
/**
* Returns the user object based on the JWT token.
*
* @param {User} authUser
* @returns {Promise<UserResponse>}
* @memberof AuthController
*/
@ApiBearerAuth()
@UseGuards(AuthenticationGuard) // Perfectly fine, you don't need Authentication or Authorization to use it
@Get()
async getUserWithToken(@CognitoUser() authUser: User): Promise<UserWithFavorites> {
const favorites = await this.userActivityService.getUserFavorites(authUser.id);
return {
...authUser,
favorites
};
}
//////////////////////////////////////////////////////////
// is there a way to make this public?
//////////////////////////////////////////////////////////
@ApiBearerAuth()
@Get('config')
async getConfig(): Promise<ConfigResponse> {
return this.authService.getConfig();
}
}
@Lokicoule thanks a lot for your answer. Actually i am using a guard for all routes and i list it in providers
section of app module:
@Module({
imports: [
AuthModule,
CommonModule,
UserModule
],
providers: [
{ provide: APP_GUARD, useClass: AuthenticationGuard }
],
controllers: []
})
export class AppModule {}
As a result i have authorization guard applied to all routes. The reason i do that because i only have a few routes that are public (health-check, config etc) and it is easy for me to forget to apply guards on individual route level and leave one leaking sensitive info :)
Just wondering if i had many many routes how would i set all routes to private first and then "whitelist" public ones?
Thanks a lot
@okonon, @nestjs-cognito
doesn't have this feature. In my opinion, it's more of a structural issue and you should organize your modules differently.
You can group your modules into two distinct 'mid-root' modules instead of one (AppModule). Let's say PublicAppModule and PrivateAppModule.
At this point, you should have something like this:
AppModule (root level)
Inject(
1. PublicModule
inject(
- PublicModuleOne
- PublicModuleTwo
)
2. PrivateModule
provide: APP_GUARD
inject(
- PrivateModuleOne
- PrivateModuleTwo
)
)
When I talk about Module, it's also valid for Controller, etc... To depends on your organization's workflow.
@Lokicoule totally make sense thanks for your help.
@Lokicoule i tried to import moduels like this:
import { Module } from '@nestjs/common';
import { CommonModule } from './private/common/common.module';
import { PrivateModule } from './private/private.module';
import { PublicModule } from './public/public.module';
@Module({
imports: [CommonModule, PublicModule, PrivateModule],
providers: [],
controllers: []
})
export class AppModule {}
Public module:
import { Module } from '@nestjs/common';
import { HealthcheckModule } from './healthcheck/healthcheck.module';
import { SettingsModule } from './settings/settings.module';
@Module({
imports: [HealthcheckModule, SettingsModule],
providers: [],
controllers: []
})
export class PublicModule {}
and my private module has APP_GUARD and still public routes require auth:
@Module({
imports: [
UserModule,
],
providers: [
// this actually makes this module 'private'
{ provide: APP_GUARD, useClass: AuthenticationGuard }
],
controllers: []
})
export class PrivateModule {}
I know i am close but missing something. Would you be able to point me to right direction @Lokicoule ?
I really appreciate your help
My bad sorry, according to the doc the APP_GUARD
is global.
A naive solution for this requirement is to inject metadata inside the request context and retrieve it when the guard performs.
I will do my best to do it this week but if you don't want to be blocked you can override https://github.com/Lokicoule/nestjs-cognito/blob/main/packages/auth/lib/abstract.guard.ts and create a new decorator which will inject the metadata.
Please update to version: @nestjs-cognito/auth
version 1.1.1.
Method decorator @PublicRoute
is introduced to fit your needs.
@Get("iampublic")
@PublicRoute()
getPublic() {
return "public";
}
I didn't test it outside the e2e test scope so I count on you to let me know if you encounter some issues.
@Lokicoule thanks a lot tested and works like a charm ! thank you very much again!
@Lokicoule Is there a way to define public routes if whole controller uses
@Authentication()
decorator? basically i would like/config
endpoint to not require JWT token.for example i have following code:
Thank you!