@nestjs-cognito/graphql
v3.2.1
Published
Auth Module for NestJS, GraphQL and Cognito
Downloads
5,177
Maintainers
Readme
Overview
@nestjs-cognito/graphql brings AWS Cognito authentication and authorization to your NestJS GraphQL APIs. This package extends @nestjs-cognito/auth with GraphQL-specific decorators and guards, providing seamless integration with Apollo Server and NestJS GraphQL.
The package provides GraphQL context integration for user information, specialized decorators for resolvers, and guards that work naturally with GraphQL execution context.
Features
- GraphQL Context Integration - Automatic injection of authenticated user information into GraphQL context
- Resolver Decorators - GraphQL-specific
@GqlAuthentication()and@GqlAuthorization()decorators - User Extraction -
@GqlCognitoUser(),@GqlCognitoAccessUser(), and@GqlCognitoIdUser()decorators for accessing user data - Authorization Guards - Role-based access control with allowed, required, and prohibited groups
- Type Safety - Full TypeScript support with typed JWT payloads
- Zero Configuration - Works out-of-the-box with your existing
@nestjs-cognito/authsetup
Installation
npm install @nestjs-cognito/graphql @nestjs-cognito/authQuick Start
1. Configure Authentication Module
First, set up the @nestjs-cognito/auth module as described in the auth package documentation:
import { CognitoAuthModule } from "@nestjs-cognito/auth";
import { Module } from "@nestjs/common";
@Module({
imports: [
CognitoAuthModule.register({
jwtVerifier: {
userPoolId: "us-east-1_xxxxxx",
clientId: "your-client-id",
tokenUse: "access",
},
}),
],
})
export class AppModule {}2. Protect Your Resolvers
import { GqlAuthentication, GqlCognitoUser } from "@nestjs-cognito/graphql";
import { Query, Resolver } from "@nestjs/graphql";
import type { CognitoJwtPayload } from "@nestjs-cognito/core";
@Resolver()
@GqlAuthentication()
export class UserResolver {
@Query(() => String)
getCurrentUser(@GqlCognitoUser() user: CognitoJwtPayload): string {
return `Authenticated as ${user.username}`;
}
}3. Add Role-Based Authorization
import { GqlAuthorization, GqlCognitoUser } from "@nestjs-cognito/graphql";
import { Mutation, Args, Resolver } from "@nestjs/graphql";
@Resolver()
export class AdminResolver {
@Mutation(() => Boolean)
@GqlAuthorization(["admin", "superadmin"])
deleteUser(
@Args("userId") userId: string,
@GqlCognitoUser("username") username: string
): boolean {
console.log(`User ${username} deleted user ${userId}`);
return true;
}
}Table of Contents
Authentication
Protect your GraphQL resolvers by requiring valid AWS Cognito authentication tokens. The authentication middleware extracts the JWT from the Authorization header and adds user information to the GraphQL context.
Note: When using authorization, authentication is already checked, so there's no need to use both decorators together.
@GqlAuthentication Decorator
The @GqlAuthentication() decorator is the recommended approach for securing resolvers. It can be applied at the resolver or query/mutation level:
Resolver-level authentication:
import { GqlAuthentication, GqlCognitoUser } from "@nestjs-cognito/graphql";
import { Query, Resolver } from "@nestjs/graphql";
import type { CognitoJwtPayload } from "@nestjs-cognito/core";
@Resolver("User")
@GqlAuthentication()
export class UserResolver {
@Query(() => String)
getProfile(@GqlCognitoUser() user: CognitoJwtPayload): string {
return `Profile for ${user.email}`;
}
@Query(() => [String])
getNotifications(@GqlCognitoUser("sub") userId: string): string[] {
return [`Notification for user ${userId}`];
}
}Query/Mutation-level authentication:
import { GqlAuthentication, GqlCognitoUser } from "@nestjs-cognito/graphql";
import { Query, Mutation, Args, Resolver } from "@nestjs/graphql";
@Resolver()
export class PostResolver {
@Query(() => [String])
getAllPosts(): string[] {
return ["Public post 1", "Public post 2"];
}
@Mutation(() => String)
@GqlAuthentication()
createPost(
@Args("title") title: string,
@GqlCognitoUser("username") username: string
): string {
return `Post "${title}" created by ${username}`;
}
}AuthenticationGuard
Alternatively, you can use the AuthenticationGuard directly with @UseGuards():
import { UseGuards } from "@nestjs/common";
import { Query, Resolver } from "@nestjs/graphql";
import { AuthenticationGuard, GqlCognitoUser } from "@nestjs-cognito/graphql";
import type { CognitoJwtPayload } from "@nestjs-cognito/core";
@Resolver("Profile")
@UseGuards(AuthenticationGuard)
export class ProfileResolver {
@Query(() => String)
getMyProfile(@GqlCognitoUser() user: CognitoJwtPayload): string {
return `Profile for ${user.username}`;
}
}Authorization
Implement role-based access control (RBAC) for your GraphQL API using Cognito user groups. Authorization automatically includes authentication verification.
@GqlAuthorization Decorator
The @GqlAuthorization() decorator enforces group-based access control with three types of rules:
allowedGroups- User must belong to at least one of these groupsrequiredGroups- User must belong to all of these groupsprohibitedGroups- User must not belong to any of these groups
Resolver-level authorization:
import { GqlAuthorization, GqlCognitoUser } from "@nestjs-cognito/graphql";
import { Query, Mutation, Args, Resolver } from "@nestjs/graphql";
import type { CognitoJwtPayload } from "@nestjs-cognito/core";
@Resolver("Admin")
@GqlAuthorization({
allowedGroups: ["admin", "superadmin"],
prohibitedGroups: ["suspended"],
})
export class AdminResolver {
@Query(() => [String])
getAllUsers(@GqlCognitoUser() admin: CognitoJwtPayload): string[] {
return ["user1", "user2", "user3"];
}
@Mutation(() => Boolean)
@GqlAuthorization({ requiredGroups: ["superadmin"] })
deleteAllData(): boolean {
return true;
}
}Simplified syntax for allowed groups:
@Resolver("Content")
@GqlAuthorization(["editor", "admin"]) // shorthand for allowedGroups
export class ContentResolver {
@Mutation(() => String)
publishArticle(@Args("id") id: string): string {
return `Article ${id} published`;
}
}Mutation-level authorization:
@Resolver("Comment")
export class CommentResolver {
@Query(() => [String])
getComments(): string[] {
return ["Comment 1", "Comment 2"];
}
@Mutation(() => Boolean)
@GqlAuthorization(["moderator", "admin"])
deleteComment(@Args("id") id: string): boolean {
return true;
}
}AuthorizationGuard
You can also use the AuthorizationGuard directly with @UseGuards():
import { UseGuards } from "@nestjs/common";
import { Query, Resolver } from "@nestjs/graphql";
import { AuthorizationGuard, GqlCognitoUser } from "@nestjs-cognito/graphql";
@Resolver("Reports")
@UseGuards(
AuthorizationGuard({
allowedGroups: ["analyst", "manager"],
prohibitedGroups: ["guest"],
})
)
export class ReportsResolver {
@Query(() => String)
getFinancialReport(@GqlCognitoUser("email") email: string): string {
return `Report for ${email}`;
}
}User Decorators
Extract authenticated user information from JWT tokens in your GraphQL resolvers using specialized decorators. All decorators must be used within resolvers protected by authentication or authorization.
@GqlCognitoUser - Generic Decorator
The @GqlCognitoUser() decorator works with both access and ID tokens, providing flexible access to user information from the GraphQL context.
Inject the complete payload:
import { GqlAuthentication, GqlCognitoUser } from "@nestjs-cognito/graphql";
import { Query, Resolver } from "@nestjs/graphql";
import type { CognitoJwtPayload } from "@nestjs-cognito/core";
@Resolver()
@GqlAuthentication()
export class ProfileResolver {
@Query(() => String)
getProfile(@GqlCognitoUser() user: CognitoJwtPayload): string {
return JSON.stringify({
username: user.username,
email: user.email,
sub: user.sub,
});
}
}Extract a single property:
@Resolver()
@GqlAuthentication()
export class UserResolver {
@Query(() => String)
getEmail(@GqlCognitoUser("email") email: string): string {
return email;
}
}Extract multiple properties:
@Resolver()
@GqlAuthentication()
export class UserResolver {
@Query(() => String)
getUserInfo(
@GqlCognitoUser(["email", "username", "groups"])
user: {
email: string;
username: string;
groups: string[];
}
): string {
return `${user.username} (${user.email}) - Groups: ${user.groups.join(", ")}`;
}
}Note: The
cognito:namespace is automatically managed for properties likecognito:groupsandcognito:username. You can reference them without the prefix.
@GqlCognitoAccessUser - Access Token Decorator
The @GqlCognitoAccessUser() decorator validates that the token is an access token and provides access to access token-specific properties. It throws CognitoTokenTypeMismatchError if an ID token is provided.
When to use: When you need access token properties like scope and client_id, or want to enforce that only access tokens are accepted.
import { GqlAuthentication, GqlCognitoAccessUser } from "@nestjs-cognito/graphql";
import { Query, Resolver } from "@nestjs/graphql";
import type { CognitoAccessTokenPayload } from "@nestjs-cognito/core";
@Resolver()
@GqlAuthentication()
export class ApiResolver {
@Query(() => String)
getTokenInfo(@GqlCognitoAccessUser() token: CognitoAccessTokenPayload): string {
return JSON.stringify({
scope: token.scope,
clientId: token.client_id,
username: token.username,
});
}
}@GqlCognitoIdUser - ID Token Decorator
The @GqlCognitoIdUser() decorator validates that the token is an ID token and provides access to ID token-specific properties. It throws CognitoTokenTypeMismatchError if an access token is provided.
When to use: When you need ID token properties like email, cognito:groups, or custom attributes, or want to enforce that only ID tokens are accepted.
import { GqlAuthentication, GqlCognitoIdUser } from "@nestjs-cognito/graphql";
import { Query, Resolver } from "@nestjs/graphql";
import type { CognitoIdTokenPayload } from "@nestjs-cognito/core";
@Resolver()
@GqlAuthentication()
export class UserResolver {
@Query(() => String)
getUserDetails(@GqlCognitoIdUser() user: CognitoIdTokenPayload): string {
return JSON.stringify({
username: user["cognito:username"],
email: user.email,
groups: user["cognito:groups"],
emailVerified: user.email_verified,
});
}
}Choosing the right decorator:
@GqlCognitoAccessUser- Use when you needscope,client_id, or want to enforce access tokens@GqlCognitoIdUser- Use when you needemail,cognito:groups, custom attributes, or want to enforce ID tokens@GqlCognitoUser- Use when you don't care about token type or need to support both
Complete Example
Here's a complete example showing authentication, authorization, and user extraction in a GraphQL API:
import {
GqlAuthentication,
GqlAuthorization,
GqlCognitoUser,
} from "@nestjs-cognito/graphql";
import { Query, Mutation, Args, Resolver } from "@nestjs/graphql";
import type { CognitoJwtPayload } from "@nestjs-cognito/core";
@Resolver("Article")
export class ArticleResolver {
// Public query - no authentication required
@Query(() => [String])
getPublicArticles(): string[] {
return ["Public article 1", "Public article 2"];
}
// Authenticated query - requires valid token
@Query(() => [String])
@GqlAuthentication()
getMyArticles(@GqlCognitoUser("sub") userId: string): string[] {
return [`Article by user ${userId}`];
}
// Authorized mutation - requires specific groups
@Mutation(() => String)
@GqlAuthorization(["editor", "admin"])
createArticle(
@Args("title") title: string,
@GqlCognitoUser() user: CognitoJwtPayload
): string {
return `Article "${title}" created by ${user.username}`;
}
// Restricted mutation - requires admin role
@Mutation(() => Boolean)
@GqlAuthorization(["admin"])
deleteArticle(@Args("id") id: string): boolean {
return true;
}
}Related Packages
- @nestjs-cognito/auth - Core authentication module (required)
- @nestjs-cognito/core - Core functionality and AWS Cognito integration
- @nestjs-cognito/testing - Testing utilities for E2E and mock testing
Resources
License
@nestjs-cognito/graphql is MIT licensed.
