salar
04/01/2024, 11:35 PMimport { Controller, Get, Query, Session, UseGuards } from '@nestjs/common';
import { SessionContainer } from 'supertokens-node/recipe/session';
import { BasicAuthGuard } from '../auth/guard/base-auth.guard';
import { GetSubscriptionDetailsRequestDto } from './dto/get-subscription-details.dto';
import { PaymentsService } from './payments.service';
function getUserEmailFromSession(session: SessionContainer) {
const { email } = session.getAccessTokenPayload();
return email;
}
@UseGuards(BasicAuthGuard)
@Controller('payments')
export class PaymentsController {
constructor(private readonly paymentsService: PaymentsService) {}
@Get('details')
public async getSubscriptionDetails(
@Session() session: SessionContainer,
@Query() input: GetSubscriptionDetailsRequestDto,
) {
const subscriptionDetails = await this.getSubscriptionDetailsFromEmail(
getUserEmailFromSession(session),
);
return subscriptionDetails;
}
}
Here's the code for the auth guard
import type { CanActivate, ExecutionContext } from '@nestjs/common';
import { Error as STError } from 'supertokens-node';
import { verifySession } from 'supertokens-node/recipe/session/framework/express';
export class BasicAuthGuard implements CanActivate {
constructor() {}
public async canActivate(context: ExecutionContext): Promise<boolean> {
const ctx = context.switchToHttp();
let err = undefined;
const resp = ctx.getResponse();
// You can create an optional version of this by passing {sessionRequired: false} to verifySession
await verifySession({ checkDatabase: true, sessionRequired: true })(
ctx.getRequest(),
resp,
(res) => {
err = res;
},
);
if (resp.headersSent) {
throw new STError({
message: 'RESPONSE_SENT',
type: 'RESPONSE_SENT',
});
}
if (err) {
throw err;
}
return true;
}
}
This controller runs fine 95% of the time. But we're seeing a weird log on our servers that shouldn't be there.
ALERT!!!! INTERNAL SERVER ERROR!!!
STATUS: 500
METHOD: GET
PATH: /payments/details?checkoutCancelPath=%2Fbilling&checkoutSuccessPath=%2Fbilling&portalReturnPath=%2Fbilling
REQUEST-ID: 492f101b-92e4-4762-8a82-4f131c995c3f
MESSAGE: Cannot read properties of undefined (reading 'getAccessTokenPayload')
ERROR: 'Unhandled Rejection'
STACK: TypeError: Cannot read properties of undefined (reading 'getAccessTokenPayload')
at PaymentsService.getUserEmailFromSession (/app/dist/modules/payments/payments.service.js:187:35)
at PaymentsController.getSubscriptionDetails (/app/dist/modules/payments/payments.controller.js:27:37)
at /app/node_modules/@nestjs/core/router/router-execution-context.js:38:29
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async /app/node_modules/@nestjs/core/router/router-execution-context.js:46:28
at async /app/node_modules/@nestjs/core/router/router-proxy.js:9:17
And I have no clue as to what is happening on the FE that's causing this. We've been unable to identify which user is having this issue. The authentication method is cookies, the access token is sent in the 'cookie' header.
I would really appreciate if anyone can give insights into why we're getting a session
that's undefined
. In my limited knowledge, if the cookie header is not present the BasicAuthGuard should already throw a 401, and I've tested this manually and it is indeed the case.
What escapes me is how can a request pass through the auth guard successfully and end up having a session that is undefined
Thanks allot!SuperTokens is an open source authentication solution offering features like: Different types of login: Email / password, Passwordless (OTP or Magic link based).
Powered by