You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: content/security/authentication.md
+83-73Lines changed: 83 additions & 73 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -58,6 +58,7 @@ Replace the default contents of these generated files as shown below. For our sa
58
58
@@filename(users/users.service)
59
59
import { Injectable } from'@nestjs/common';
60
60
61
+
// This should be a real class/interface representing a user entity
61
62
exporttypeUser=any;
62
63
63
64
@Injectable()
@@ -73,11 +74,6 @@ export class UsersService {
73
74
},
74
75
{
75
76
userId: 2,
76
-
username: 'chris',
77
-
password: 'secret',
78
-
},
79
-
{
80
-
userId: 3,
81
77
username: 'maria',
82
78
password: 'guess',
83
79
},
@@ -102,11 +98,6 @@ export class UsersService {
102
98
},
103
99
{
104
100
userId: 2,
105
-
username: 'chris',
106
-
password: 'secret',
107
-
},
108
-
{
109
-
userId: 3,
110
101
username: 'maria',
111
102
password: 'guess',
112
103
},
@@ -262,7 +253,7 @@ export class LocalStrategy extends PassportStrategy(Strategy) {
262
253
263
254
We've followed the recipe described earlier for all Passport strategies. In our use case with passport-local, there are no configuration options, so our constructor simply calls `super()`, without an options object.
264
255
265
-
> info **Hint** We can pass an options object in the call to `super()` to customize the behavior of the passport strategy. In this example, the passport-local strategy by default expects properties called `username` and `password` in the request body. Pass an options object to specify different property names, for example: `super({{ '{' }} usernameField: 'email' {{ '}' }})`. See the [Passport documentation](http://www.passportjs.org/docs/configure/) for more information.
256
+
> info **Hint** We can pass an options object in the call to `super()` to customize the behavior of the passport strategy. In this example, the passport-local strategy by default expects properties called `username` and `password` in the request body. Pass an options object to specify different property names, for example: `super({{ '{' }} usernameField: 'email' {{ '}' }})`. See the [Passport documentation](http://www.passportjs.org/docs/configure/) for more information.
266
257
267
258
We've also implemented the `validate()` method. For each strategy, Passport will call the verify function (implemented with the `validate()` method in `@nestjs/passport`) using an appropriate strategy-specific set of parameters. For the local-strategy, Passport expects a `validate()` method with the following signature: `validate(username: string, password:string): any`.
268
259
@@ -789,35 +780,92 @@ Note that in the `AuthModule`, we configured the JWT to have an expiration of `6
789
780
790
781
We've now completed our JWT authentication implementation. JavaScript clients (such as Angular/React/Vue), and other JavaScript apps, can now authenticate and communicate securely with our API Server. You can find a complete version of the code in this chapter [here](https://github.com/nestjs/nest/tree/master/sample/19-auth-jwt).
791
782
792
-
<app-banner-enterprise></app-banner-enterprise>
783
+
#### Extending guards
784
+
785
+
In most cases, using a provided `AuthGuard` class is sufficient. However, there might be use-cases when you would like to simply extend the default error handling or authentication logic. For this, you can extend the built-in class and override methods within a sub-class.
786
+
787
+
```typescript
788
+
import {
789
+
ExecutionContext,
790
+
Injectable,
791
+
UnauthorizedException,
792
+
} from'@nestjs/common';
793
+
import { AuthGuard } from'@nestjs/passport';
794
+
795
+
@Injectable()
796
+
exportclassJwtAuthGuardextendsAuthGuard('jwt') {
797
+
canActivate(context:ExecutionContext) {
798
+
// Add your custom authentication logic here
799
+
// for example, call super.logIn(request) to establish a session.
800
+
returnsuper.canActivate(context);
801
+
}
802
+
803
+
handleRequest(err, user, info) {
804
+
// You can throw an exception based on either "info" or "err" arguments
805
+
if (err||!user) {
806
+
throwerr||newUnauthorizedException();
807
+
}
808
+
returnuser;
809
+
}
810
+
}
811
+
```
812
+
813
+
#### Enable authentication globally
793
814
794
-
#### Default strategy
815
+
If the vast of your endpoints should be protected by default, you can register the authentication guard as a [global guard](/guards#binding-guards) and instead of using `@UseGuards()` decorator on top of each controller, you could simply flag which routes should be public.
795
816
796
-
In our `AppController`, we pass the name of the strategy in the `AuthGuard()` function. We need to do this because we've introduced **two** Passport strategies (passport-local and passport-jwt), both of which supply implementations of various Passport components. Passing the name disambiguates which implementation we're linking to. When multiple strategies are included in an application, we can declare a default strategy so that we no longer have to pass the name in the `AuthGuard` function if using that default strategy. Here's how to register a default strategy when importing the `PassportModule`. This code would go in the `AuthModule`:
817
+
First, register the `JwtAuthGuard` as a global guard using the following construction (in any module):
With this in place, Nest will automatically bind `JwtAuthGuard` to all endpoints.
829
+
830
+
Now we must provide a mechanism for declaring routes as public. For this, we can create a custom decorator using the `SetMetadata` decorator factory function.
831
+
832
+
```typescript
833
+
import { SetMetadata } from'@nestjs/common';
834
+
835
+
exportconst IS_PUBLIC_KEY ='isPublic';
836
+
exportconst Public = () =>SetMetadata(IS_PUBLIC_KEY, true);
837
+
```
838
+
839
+
In the file above, we exported two constants. One being our metadata key named `IS_PUBLIC_KEY`, and the other being our new decorator itself that we’re going to call `Public` (we can alternatively name it `SkipAuth`).
840
+
841
+
Now that we have a custom `@Public()` decorator, we can use it to decorate any method, as follows:
842
+
843
+
```typescript
844
+
@Public()
845
+
@Get()
846
+
findAll() {
847
+
return [];
848
+
}
849
+
```
850
+
851
+
Lastly, we need the `JwtAuthGuard` to return `true` when the `"isPublic"` metadata is found. For this, we'll use the `Reflector` class (read more [here](/guards#putting-it-all-together)).
In the example above, the `resolve()` method will asynchronously return the request-scoped instance of the `AuthService` provider (we assumed that `AuthService` is marked as a request-scoped provider).
861
909
862
-
#### Extending guards
863
-
864
-
In most cases, using a provided `AuthGuard` class is sufficient. However, there might be use-cases when you would like to simply extend the default error handling or authentication logic. For this, you can extend the built-in class and override methods within a sub-class.
865
-
866
-
```typescript
867
-
import {
868
-
ExecutionContext,
869
-
Injectable,
870
-
UnauthorizedException,
871
-
} from'@nestjs/common';
872
-
import { AuthGuard } from'@nestjs/passport';
873
-
874
-
@Injectable()
875
-
exportclassJwtAuthGuardextendsAuthGuard('jwt') {
876
-
canActivate(context:ExecutionContext) {
877
-
// Add your custom authentication logic here
878
-
// for example, call super.logIn(request) to establish a session.
879
-
returnsuper.canActivate(context);
880
-
}
881
-
882
-
handleRequest(err, user, info) {
883
-
// You can throw an exception based on either "info" or "err" arguments
884
-
if (err||!user) {
885
-
throwerr||newUnauthorizedException();
886
-
}
887
-
returnuser;
888
-
}
889
-
}
890
-
```
891
-
892
910
#### Customize Passport
893
911
894
912
Any standard Passport customization options can be passed the same way, using the `register()` method. The available options depend on the strategy being implemented. For example:
@@ -935,14 +953,6 @@ export class GqlAuthGuard extends AuthGuard('jwt') {
935
953
}
936
954
```
937
955
938
-
To use the above construct, be sure to pass the request (`req`) object as part of the context value in the GraphQL Module settings:
939
-
940
-
```typescript
941
-
GraphQLModule.forRoot({
942
-
context: ({ req }) => ({ req }),
943
-
});
944
-
```
945
-
946
956
To get the current authenticated user in your graphql resolver, you can define a `@CurrentUser()` decorator:
0 commit comments