This is a basic project that shows how to use the nestjs passport local strategy, along with graphql and express sessions.
npm install
- NestJS
- GraphQL
- Express-Session
- Passport
- Passport local strategy
- TypeORM
- passport
- passport-local
- express-session
- @nestjs/passport
- @types/passport-local
- @types/express-session
1.Create AuthGuard which take context from GraphQL and assign our Email and Password to req.body, because passport automatically gets your credentials from req.body but incase of graphql execution context is different so you have to manually set your args in req.body and for that getRequest method is used.
# example
getRequest(context: ExecutionContext) {
const ctx = GqlExecutionContext.create(context);
const gqlReq = ctx.getContext().req;
const {
LoginInput: { Email, Password },
} = ctx.getArgs();
gqlReq.body.Email = Email;
gqlReq.body.Password = Password;
return gqlReq;
}
2.Export the class which extends the PassportStrategy
with Strategy argument(inherited from passport-local module) and call super() method.you can even specify the usernameField and passwordField inside the super method.
#example
constructor(private readonly authService: AuthService) {
super({
usernameField: 'Email',
passwordField: 'Password',
});
}
3.After that call the validate method inside the class.
4.After that we need to call serializeUser and deserializeUser method to store the user data into the session.
5.To call serializeUser method we need to create new AuthGuard which will take request and pass it to the passport logIn method.
#example
@Injectable()
export class SessionLocalAuthGuard extends AuthGuard('local') {
async canActivate(context: ExecutionContext): Promise<boolean> {
const ctxRequest = GqlExecutionContext.create(context).getContext().req;
await super.logIn(ctxRequest);
return ctxRequest ? true : false;
}
}
6.After that we need to call both guards in the login query/mutation by adding @UseGuards() decorator.
# example
@Query(() => LoginResponse)
@UseGuards(GQLAuthGuard, SessionLocalAuthGuard)
login(
@Args('LoginInput') loginInput: LoginInput,
@User() user: UserEntity,
): LoginResponse {
return {
LoginSuccessMessage: constant.LOGIN_SUCCESSFUL,
CurrentUser: user,
};
}
7.On successful login we can retrieve the current user by req.user we can even create custom decorator for that too, for that please visit here.
8.We can even implement new Guard to authenticate the user, for that we can do something like this.
@Injectable()
export class IsAuthenticated implements CanActivate {
async canActivate(context: ExecutionContext): Promise<any> {
const ctxReq = GqlExecutionContext.create(context).getContext().req;
const AuthenticationStatus = ctxReq.isAuthenticated();
if (!AuthenticationStatus) {
throw new UnauthorizedException(constant.UNAUTHORIZED_ACCESS_MESSAGE);
}
return AuthenticationStatus;
}
}
9.And then we can call that guard on every query/mutation something like this
@UseGuards(IsAuthenticated)
@Query(() => AllUserResponseDTO)
async getAllUserData(@User() user: UserEntity): Promise<AllUserResponseDTO> {
const userData: UserEntity[] | [] = await this.userService.getAllUserData(
user.ID,
);
return { AllUserData: userData, CurrentUser: user };
}
# to check connection
query {
checkServer {
connectionStatus
}
}
# to login the user
query {
login(
LoginInput: { Email: "raj.famous009@gmail.com", Password: "123123Raj!" }
) {
LoginSuccessMessage
CurrentUser {
ID
Name
Email
}
}
}
# get all user listing after the authorization
query {
getAllUserData {
CurrentUser {
ID
Email
Name
}
AllUserData {
ID
Email
Name
}
}
}
# user register functionality
mutation {
createUser(
UserCreateObject: {
Name: "Raj Gohil"
Email: "raj.famous009@gmail.com"
Password: "123123Raj!"
}
) {
ID
Name
Email
}
}
# passport along with GraphQl
https://docs.nestjs.com/security/authentication#graphql
#create custom decorator using GraphQL
https://docs.nestjs.com/security/authentication#graphql
# session with local strategy
https://dev.to/nestjs/authentication-and-sessions-for-mvc-apps-with-nestjs-55a4
# stack overflow link if you got 401 unauthorize every single time
https://stackoverflow.com/questions/68390441/nestjs-graphql-passport-getting-unauthorised-error-from-guard
# development
npm run start
# watch mode
npm run start:dev
# production mode
npm run start:prod