diff --git a/v2/emailpassword/nestjs/guide.mdx b/v2/emailpassword/nestjs/guide.mdx index 9ee3efbee..6fcd78d7d 100644 --- a/v2/emailpassword/nestjs/guide.mdx +++ b/v2/emailpassword/nestjs/guide.mdx @@ -106,7 +106,7 @@ export class AuthModule implements NestModule { } ``` -In the provided code sample, we convert this to a [dynamic module](https://docs.nestjs.com/modules#dynamic-modules) so we can configure parts of the SuperTokens setup within the App module. This approach allows for centralized configuration, which can be particularly beneficial when managing settings such as using distinct connection URIs for different environments, such as testing or production. +In the provided code sample, we convert `AuthModule` to a [dynamic module](https://docs.nestjs.com/modules#dynamic-modules) so we can configure parts of the SuperTokens setup within the App module. This approach allows for centralized configuration, which can be particularly beneficial when managing settings such as using distinct connection URIs for different environments, such as testing or production. :::info The middleware is registered using the `configure` method in the `AuthModule` class. @@ -290,9 +290,6 @@ export class SupertokensExceptionFilter implements ExceptionFilter { const ctx = host.switchToHttp(); const resp = ctx.getResponse(); - if (resp.headersSent) { - return; - } this.handler( exception, @@ -308,6 +305,9 @@ export class SupertokensExceptionFilter implements ExceptionFilter { We need to add this filter as a global exception filter. You can do this in `main.ts`, right after the updated CORS settings. + + ```ts title="./src/main.ts" import { NestFactory } from '@nestjs/core'; // @ts-ignore @@ -320,7 +320,7 @@ import { SupertokensExceptionFilter } from './auth/auth.filter'; async function bootstrap() { const app = await NestFactory.create(AuthModule); app.enableCors({ - origin: ['http://localhost:3001'], // TODO: URL of the website domain + origin: ['^{form_websiteDomain}'], allowedHeaders: ['content-type', ...supertokens.getAllCORSHeaders()], credentials: true, }); @@ -334,6 +334,7 @@ async function bootstrap() { bootstrap(); ``` + ## Add a session verification guard @@ -343,40 +344,25 @@ In the newly created `auth.guard.ts` file, implement session verification: ```ts title="./src/auth/auth.guard.ts" import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; -import { Error as STError } from "supertokens-node"; - -import { verifySession } from 'supertokens-node/recipe/session/framework/express'; -import { VerifySessionOptions } from 'supertokens-node/recipe/session'; +import { getSession, VerifySessionOptions } from 'supertokens-node/recipe/session'; @Injectable() export class AuthGuard implements CanActivate { - constructor(private readonly verifyOptions?: VerifySessionOptions) {} + constructor(private readonly getSessionOptions?: VerifySessionOptions) {} - async canActivate(context: ExecutionContext): Promise { + public async canActivate(context: ExecutionContext): Promise { const ctx = context.switchToHttp(); - let err = undefined; + const req = ctx.getRequest(); const resp = ctx.getResponse(); - // You can create an optional version of this by passing {sessionRequired: false} to verifySession - await verifySession(this.verifyOptions)( - ctx.getRequest(), - resp, - (res: any) => { - err = res; - }, - ); - if (resp.headersSent) { - throw new STError({ - message: "RESPONSE_SENT", - type: "RESPONSE_SENT", - }); - } - - if (err) { - throw err; - } + // If the session doesn't exist and {sessionRequired: true} is passed to the AuthGuard constructor (default is true), + // getSession will throw an error, that will be handled by the exception filter, returning a 401 response. + // To avoid an error when the session doesn't exist, pass {sessionRequired: false} to the AuthGuard constructor. + // In this case, req.session will be undefined if the session doesn't exist. + const session = await getSession(req, resp, this.getSessionOptions); + req.session = session; return true; } } @@ -414,11 +400,17 @@ import { Session } from './auth/session/session.decorator'; @Controller() export class AppController { // ... - @Get('test') + // Test endpoint for session verification; not part of the Supertokens setup. + @Get('/test') @UseGuards(new AuthGuard()) - async getTest(@Session() session: SessionContainer): Promise { - // TODO: magic - return "magic"; + getSessionInfo( + @Session() session: SessionContainer, + ): Record { + return { + sessionHandle: session.getHandle(), + userId: session.getUserId(), + accessTokenPayload: session.getAccessTokenPayload(), + }; } } ``` diff --git a/v2/passwordless/nestjs/guide.mdx b/v2/passwordless/nestjs/guide.mdx index b298b47f2..30066a2cc 100644 --- a/v2/passwordless/nestjs/guide.mdx +++ b/v2/passwordless/nestjs/guide.mdx @@ -106,7 +106,7 @@ export class AuthModule implements NestModule { } ``` -In the provided code sample, we convert this to a [dynamic module](https://docs.nestjs.com/modules#dynamic-modules) so we can configure parts of the SuperTokens setup within the App module. This approach allows for centralized configuration, which can be particularly beneficial when managing settings such as using distinct connection URIs for different environments, such as testing or production. +In the provided code sample, we convert `AuthModule` to a [dynamic module](https://docs.nestjs.com/modules#dynamic-modules) so we can configure parts of the SuperTokens setup within the App module. This approach allows for centralized configuration, which can be particularly beneficial when managing settings such as using distinct connection URIs for different environments, such as testing or production. :::info The middleware is registered using the `configure` method in the `AuthModule` class. @@ -309,9 +309,6 @@ export class SupertokensExceptionFilter implements ExceptionFilter { const ctx = host.switchToHttp(); const resp = ctx.getResponse(); - if (resp.headersSent) { - return; - } this.handler( exception, @@ -327,6 +324,9 @@ export class SupertokensExceptionFilter implements ExceptionFilter { We need to add this filter as a global exception filter. You can do this in `main.ts`, right after the updated CORS settings. + + ```ts title="./src/main.ts" import { NestFactory } from '@nestjs/core'; // @ts-ignore @@ -339,7 +339,7 @@ import { SupertokensExceptionFilter } from './auth/auth.filter'; async function bootstrap() { const app = await NestFactory.create(AuthModule); app.enableCors({ - origin: ['http://localhost:3001'], // TODO: URL of the website domain + origin: ['^{form_websiteDomain}'], allowedHeaders: ['content-type', ...supertokens.getAllCORSHeaders()], credentials: true, }); @@ -353,6 +353,7 @@ async function bootstrap() { bootstrap(); ``` + ## Add a session verification guard @@ -362,40 +363,25 @@ In the newly created `auth.guard.ts` file, implement session verification: ```ts title="./src/auth/auth.guard.ts" import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; -import { Error as STError } from "supertokens-node"; - -import { verifySession } from 'supertokens-node/recipe/session/framework/express'; -import { VerifySessionOptions } from 'supertokens-node/recipe/session'; +import { getSession, VerifySessionOptions } from 'supertokens-node/recipe/session'; @Injectable() export class AuthGuard implements CanActivate { - constructor(private readonly verifyOptions?: VerifySessionOptions) {} + constructor(private readonly getSessionOptions?: VerifySessionOptions) {} - async canActivate(context: ExecutionContext): Promise { + public async canActivate(context: ExecutionContext): Promise { const ctx = context.switchToHttp(); - let err = undefined; + const req = ctx.getRequest(); const resp = ctx.getResponse(); - // You can create an optional version of this by passing {sessionRequired: false} to verifySession - await verifySession(this.verifyOptions)( - ctx.getRequest(), - resp, - (res: any) => { - err = res; - }, - ); - if (resp.headersSent) { - throw new STError({ - message: "RESPONSE_SENT", - type: "RESPONSE_SENT", - }); - } - - if (err) { - throw err; - } + // If the session doesn't exist and {sessionRequired: true} is passed to the AuthGuard constructor (default is true), + // getSession will throw an error, that will be handled by the exception filter, returning a 401 response. + // To avoid an error when the session doesn't exist, pass {sessionRequired: false} to the AuthGuard constructor. + // In this case, req.session will be undefined if the session doesn't exist. + const session = await getSession(req, resp, this.getSessionOptions); + req.session = session; return true; } } @@ -433,11 +419,17 @@ import { Session } from './auth/session/session.decorator'; @Controller() export class AppController { // ... - @Get('test') + // Test endpoint for session verification; not part of the Supertokens setup. + @Get('/test') @UseGuards(new AuthGuard()) - async getTest(@Session() session: SessionContainer): Promise { - // TODO: magic - return "magic"; + getSessionInfo( + @Session() session: SessionContainer, + ): Record { + return { + sessionHandle: session.getHandle(), + userId: session.getUserId(), + accessTokenPayload: session.getAccessTokenPayload(), + }; } } ``` diff --git a/v2/thirdparty/nestjs/guide.mdx b/v2/thirdparty/nestjs/guide.mdx index 4df35f871..e186c4251 100644 --- a/v2/thirdparty/nestjs/guide.mdx +++ b/v2/thirdparty/nestjs/guide.mdx @@ -104,7 +104,7 @@ export class AuthModule implements NestModule { } ``` -In the provided code sample, we convert this to a [dynamic module](https://docs.nestjs.com/modules#dynamic-modules) so we can configure parts of the SuperTokens setup within the App module. This approach allows for centralized configuration, which can be particularly beneficial when managing settings such as using distinct connection URIs for different environments, such as testing or production. +In the provided code sample, we convert `AuthModule` to a [dynamic module](https://docs.nestjs.com/modules#dynamic-modules) so we can configure parts of the SuperTokens setup within the App module. This approach allows for centralized configuration, which can be particularly beneficial when managing settings such as using distinct connection URIs for different environments, such as testing or production. :::info The middleware is registered using the `configure` method in the `AuthModule` class. @@ -367,9 +367,6 @@ export class SupertokensExceptionFilter implements ExceptionFilter { const ctx = host.switchToHttp(); const resp = ctx.getResponse(); - if (resp.headersSent) { - return; - } this.handler( exception, @@ -385,6 +382,9 @@ export class SupertokensExceptionFilter implements ExceptionFilter { We need to add this filter as a global exception filter. You can do this in `main.ts`, right after the updated CORS settings. + + ```ts title="./src/main.ts" import { NestFactory } from '@nestjs/core'; // @ts-ignore @@ -397,7 +397,7 @@ import { SupertokensExceptionFilter } from './auth/auth.filter'; async function bootstrap() { const app = await NestFactory.create(AuthModule); app.enableCors({ - origin: ['http://localhost:3001'], // TODO: URL of the website domain + origin: ['^{form_websiteDomain}'], allowedHeaders: ['content-type', ...supertokens.getAllCORSHeaders()], credentials: true, }); @@ -411,6 +411,7 @@ async function bootstrap() { bootstrap(); ``` + ## Add a session verification guard @@ -420,40 +421,25 @@ In the newly created `auth.guard.ts` file, implement session verification: ```ts title="./src/auth/auth.guard.ts" import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; -import { Error as STError } from "supertokens-node"; - -import { verifySession } from 'supertokens-node/recipe/session/framework/express'; -import { VerifySessionOptions } from 'supertokens-node/recipe/session'; +import { getSession, VerifySessionOptions } from 'supertokens-node/recipe/session'; @Injectable() export class AuthGuard implements CanActivate { - constructor(private readonly verifyOptions?: VerifySessionOptions) {} + constructor(private readonly getSessionOptions?: VerifySessionOptions) {} - async canActivate(context: ExecutionContext): Promise { + public async canActivate(context: ExecutionContext): Promise { const ctx = context.switchToHttp(); - let err = undefined; + const req = ctx.getRequest(); const resp = ctx.getResponse(); - // You can create an optional version of this by passing {sessionRequired: false} to verifySession - await verifySession(this.verifyOptions)( - ctx.getRequest(), - resp, - (res: any) => { - err = res; - }, - ); - if (resp.headersSent) { - throw new STError({ - message: "RESPONSE_SENT", - type: "RESPONSE_SENT", - }); - } - - if (err) { - throw err; - } + // If the session doesn't exist and {sessionRequired: true} is passed to the AuthGuard constructor (default is true), + // getSession will throw an error, that will be handled by the exception filter, returning a 401 response. + // To avoid an error when the session doesn't exist, pass {sessionRequired: false} to the AuthGuard constructor. + // In this case, req.session will be undefined if the session doesn't exist. + const session = await getSession(req, resp, this.getSessionOptions); + req.session = session; return true; } } @@ -491,11 +477,17 @@ import { Session } from './auth/session/session.decorator'; @Controller() export class AppController { // ... - @Get('test') + // Test endpoint for session verification; not part of the Supertokens setup. + @Get('/test') @UseGuards(new AuthGuard()) - async getTest(@Session() session: SessionContainer): Promise { - // TODO: magic - return "magic"; + getSessionInfo( + @Session() session: SessionContainer, + ): Record { + return { + sessionHandle: session.getHandle(), + userId: session.getUserId(), + accessTokenPayload: session.getAccessTokenPayload(), + }; } } ``` diff --git a/v2/thirdpartyemailpassword/nestjs/guide.mdx b/v2/thirdpartyemailpassword/nestjs/guide.mdx index c8b98b970..e086573d1 100644 --- a/v2/thirdpartyemailpassword/nestjs/guide.mdx +++ b/v2/thirdpartyemailpassword/nestjs/guide.mdx @@ -104,7 +104,7 @@ export class AuthModule implements NestModule { } ``` -In the provided code sample, we convert this to a [dynamic module](https://docs.nestjs.com/modules#dynamic-modules) so we can configure parts of the SuperTokens setup within the App module. This approach allows for centralized configuration, which can be particularly beneficial when managing settings such as using distinct connection URIs for different environments, such as testing or production. +In the provided code sample, we convert `AuthModule` to a [dynamic module](https://docs.nestjs.com/modules#dynamic-modules) so we can configure parts of the SuperTokens setup within the App module. This approach allows for centralized configuration, which can be particularly beneficial when managing settings such as using distinct connection URIs for different environments, such as testing or production. :::info The middleware is registered using the `configure` method in the `AuthModule` class. @@ -369,9 +369,6 @@ export class SupertokensExceptionFilter implements ExceptionFilter { const ctx = host.switchToHttp(); const resp = ctx.getResponse(); - if (resp.headersSent) { - return; - } this.handler( exception, @@ -387,6 +384,9 @@ export class SupertokensExceptionFilter implements ExceptionFilter { We need to add this filter as a global exception filter. You can do this in `main.ts`, right after the updated CORS settings. + + ```ts title="./src/main.ts" import { NestFactory } from '@nestjs/core'; // @ts-ignore @@ -399,7 +399,7 @@ import { SupertokensExceptionFilter } from './auth/auth.filter'; async function bootstrap() { const app = await NestFactory.create(AuthModule); app.enableCors({ - origin: ['http://localhost:3001'], // TODO: URL of the website domain + origin: ['^{form_websiteDomain}'], allowedHeaders: ['content-type', ...supertokens.getAllCORSHeaders()], credentials: true, }); @@ -413,6 +413,7 @@ async function bootstrap() { bootstrap(); ``` + ## Add a session verification guard @@ -422,40 +423,25 @@ In the newly created `auth.guard.ts` file, implement session verification: ```ts title="./src/auth/auth.guard.ts" import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; -import { Error as STError } from "supertokens-node"; - -import { verifySession } from 'supertokens-node/recipe/session/framework/express'; -import { VerifySessionOptions } from 'supertokens-node/recipe/session'; +import { getSession, VerifySessionOptions } from 'supertokens-node/recipe/session'; @Injectable() export class AuthGuard implements CanActivate { - constructor(private readonly verifyOptions?: VerifySessionOptions) {} + constructor(private readonly getSessionOptions?: VerifySessionOptions) {} - async canActivate(context: ExecutionContext): Promise { + public async canActivate(context: ExecutionContext): Promise { const ctx = context.switchToHttp(); - let err = undefined; + const req = ctx.getRequest(); const resp = ctx.getResponse(); - // You can create an optional version of this by passing {sessionRequired: false} to verifySession - await verifySession(this.verifyOptions)( - ctx.getRequest(), - resp, - (res: any) => { - err = res; - }, - ); - if (resp.headersSent) { - throw new STError({ - message: "RESPONSE_SENT", - type: "RESPONSE_SENT", - }); - } - - if (err) { - throw err; - } + // If the session doesn't exist and {sessionRequired: true} is passed to the AuthGuard constructor (default is true), + // getSession will throw an error, that will be handled by the exception filter, returning a 401 response. + // To avoid an error when the session doesn't exist, pass {sessionRequired: false} to the AuthGuard constructor. + // In this case, req.session will be undefined if the session doesn't exist. + const session = await getSession(req, resp, this.getSessionOptions); + req.session = session; return true; } } @@ -493,11 +479,17 @@ import { Session } from './auth/session/session.decorator'; @Controller() export class AppController { // ... - @Get('test') + // Test endpoint for session verification; not part of the Supertokens setup. + @Get('/test') @UseGuards(new AuthGuard()) - async getTest(@Session() session: SessionContainer): Promise { - // TODO: magic - return "magic"; + getSessionInfo( + @Session() session: SessionContainer, + ): Record { + return { + sessionHandle: session.getHandle(), + userId: session.getUserId(), + accessTokenPayload: session.getAccessTokenPayload(), + }; } } ``` diff --git a/v2/thirdpartypasswordless/nestjs/guide.mdx b/v2/thirdpartypasswordless/nestjs/guide.mdx index 696218839..3dbe57ea3 100644 --- a/v2/thirdpartypasswordless/nestjs/guide.mdx +++ b/v2/thirdpartypasswordless/nestjs/guide.mdx @@ -106,7 +106,7 @@ export class AuthModule implements NestModule { } ``` -In the provided code sample, we convert this to a [dynamic module](https://docs.nestjs.com/modules#dynamic-modules) so we can configure parts of the SuperTokens setup within the App module. This approach allows for centralized configuration, which can be particularly beneficial when managing settings such as using distinct connection URIs for different environments, such as testing or production. +In the provided code sample, we convert `AuthModule` to a [dynamic module](https://docs.nestjs.com/modules#dynamic-modules) so we can configure parts of the SuperTokens setup within the App module. This approach allows for centralized configuration, which can be particularly beneficial when managing settings such as using distinct connection URIs for different environments, such as testing or production. :::info The middleware is registered using the `configure` method in the `AuthModule` class. @@ -384,9 +384,6 @@ export class SupertokensExceptionFilter implements ExceptionFilter { const ctx = host.switchToHttp(); const resp = ctx.getResponse(); - if (resp.headersSent) { - return; - } this.handler( exception, @@ -402,6 +399,9 @@ export class SupertokensExceptionFilter implements ExceptionFilter { We need to add this filter as a global exception filter. You can do this in `main.ts`, right after the updated CORS settings. + + ```ts title="./src/main.ts" import { NestFactory } from '@nestjs/core'; // @ts-ignore @@ -414,7 +414,7 @@ import { SupertokensExceptionFilter } from './auth/auth.filter'; async function bootstrap() { const app = await NestFactory.create(AuthModule); app.enableCors({ - origin: ['http://localhost:3001'], // TODO: URL of the website domain + origin: ['^{form_websiteDomain}'], allowedHeaders: ['content-type', ...supertokens.getAllCORSHeaders()], credentials: true, }); @@ -428,6 +428,7 @@ async function bootstrap() { bootstrap(); ``` + ## Add a session verification guard @@ -437,40 +438,25 @@ In the newly created `auth.guard.ts` file, implement session verification: ```ts title="./src/auth/auth.guard.ts" import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; -import { Error as STError } from "supertokens-node"; - -import { verifySession } from 'supertokens-node/recipe/session/framework/express'; -import { VerifySessionOptions } from 'supertokens-node/recipe/session'; +import { getSession, VerifySessionOptions } from 'supertokens-node/recipe/session'; @Injectable() export class AuthGuard implements CanActivate { - constructor(private readonly verifyOptions?: VerifySessionOptions) {} + constructor(private readonly getSessionOptions?: VerifySessionOptions) {} - async canActivate(context: ExecutionContext): Promise { + public async canActivate(context: ExecutionContext): Promise { const ctx = context.switchToHttp(); - let err = undefined; + const req = ctx.getRequest(); const resp = ctx.getResponse(); - // You can create an optional version of this by passing {sessionRequired: false} to verifySession - await verifySession(this.verifyOptions)( - ctx.getRequest(), - resp, - (res: any) => { - err = res; - }, - ); - if (resp.headersSent) { - throw new STError({ - message: "RESPONSE_SENT", - type: "RESPONSE_SENT", - }); - } - - if (err) { - throw err; - } + // If the session doesn't exist and {sessionRequired: true} is passed to the AuthGuard constructor (default is true), + // getSession will throw an error, that will be handled by the exception filter, returning a 401 response. + // To avoid an error when the session doesn't exist, pass {sessionRequired: false} to the AuthGuard constructor. + // In this case, req.session will be undefined if the session doesn't exist. + const session = await getSession(req, resp, this.getSessionOptions); + req.session = session; return true; } } @@ -508,11 +494,17 @@ import { Session } from './auth/session/session.decorator'; @Controller() export class AppController { // ... - @Get('test') + // Test endpoint for session verification; not part of the Supertokens setup. + @Get('/test') @UseGuards(new AuthGuard()) - async getTest(@Session() session: SessionContainer): Promise { - // TODO: magic - return "magic"; + getSessionInfo( + @Session() session: SessionContainer, + ): Record { + return { + sessionHandle: session.getHandle(), + userId: session.getUserId(), + accessTokenPayload: session.getAccessTokenPayload(), + }; } } ```