Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@nestlab/google-recaptcha

Package Overview
Dependencies
Maintainers
1
Versions
72
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@nestlab/google-recaptcha - npm Package Compare versions

Comparing version 1.2.4 to 2.0.0

interfaces/verify-response-decorator-options.d.ts

4

decorators/recaptcha.d.ts

@@ -1,2 +0,2 @@

import { RecaptchaResponseProvider } from '../types';
export declare function Recaptcha(response?: RecaptchaResponseProvider): MethodDecorator & ClassDecorator;
import { VerifyResponseDecoratorOptions } from '../interfaces/verify-response-decorator-options';
export declare function Recaptcha(options?: VerifyResponseDecoratorOptions): MethodDecorator & ClassDecorator;

@@ -7,6 +7,6 @@ "use strict";

const provider_declarations_1 = require("../provider.declarations");
function Recaptcha(response) {
return common_1.applyDecorators(common_1.SetMetadata(provider_declarations_1.RECAPTCHA_RESPONSE_PROVIDER, response), common_1.UseGuards(google_recaptcha_guard_1.GoogleRecaptchaGuard));
function Recaptcha(options) {
return common_1.applyDecorators(common_1.SetMetadata(provider_declarations_1.RECAPTCHA_VALIDATION_OPTIONS, options), common_1.UseGuards(google_recaptcha_guard_1.GoogleRecaptchaGuard));
}
exports.Recaptcha = Recaptcha;
//# sourceMappingURL=recaptcha.js.map

@@ -8,3 +8,5 @@ export declare enum ErrorCode {

TimeoutOrDuplicate = "timeout-or-duplicate",
UnknownError = "unknown-error"
UnknownError = "unknown-error",
ForbiddenAction = "forbidden-action",
LowScore = "low-score"
}

@@ -13,3 +13,5 @@ "use strict";

ErrorCode["UnknownError"] = "unknown-error";
ErrorCode["ForbiddenAction"] = "forbidden-action";
ErrorCode["LowScore"] = "low-score";
})(ErrorCode = exports.ErrorCode || (exports.ErrorCode = {}));
//# sourceMappingURL=error-code.js.map

@@ -22,2 +22,6 @@ "use strict";

return 'Invalid module configuration. Please check public-secret keys.';
case error_code_1.ErrorCode.LowScore:
return 'Low recaptcha score.';
case error_code_1.ErrorCode.ForbiddenAction:
return 'Forbidden recaptcha action.';
case error_code_1.ErrorCode.UnknownError:

@@ -32,3 +36,5 @@ case error_code_1.ErrorCode.BadRequest:

errorCode === error_code_1.ErrorCode.MissingInputResponse ||
errorCode === error_code_1.ErrorCode.TimeoutOrDuplicate
errorCode === error_code_1.ErrorCode.TimeoutOrDuplicate ||
errorCode === error_code_1.ErrorCode.ForbiddenAction ||
errorCode === error_code_1.ErrorCode.LowScore
? common_1.HttpStatus.BAD_REQUEST

@@ -35,0 +41,0 @@ : common_1.HttpStatus.INTERNAL_SERVER_ERROR;

@@ -38,7 +38,8 @@ "use strict";

}
const provider = this.reflector.get(provider_declarations_1.RECAPTCHA_RESPONSE_PROVIDER, context.getHandler());
const response = provider
? await provider(request)
const options = this.reflector.get(provider_declarations_1.RECAPTCHA_VALIDATION_OPTIONS, context.getHandler());
const response = (options === null || options === void 0 ? void 0 : options.response) ? await (options === null || options === void 0 ? void 0 : options.response(request))
: await this.options.response(request);
const result = await this.validator.validate(response);
const score = (options === null || options === void 0 ? void 0 : options.score) || this.options.score;
const action = options === null || options === void 0 ? void 0 : options.action;
const result = await this.validator.validate({ response, score, action });
if (result.success) {

@@ -45,0 +46,0 @@ return true;

@@ -1,2 +0,2 @@

import { RecaptchaResponseProvider } from '../types';
import { RecaptchaResponseProvider, ScoreValidator } from '../types';
import { ApplicationType } from '../enums/application-type';

@@ -7,2 +7,3 @@ export interface GoogleRecaptchaGuardOptions {

skipIf?: boolean | ((request: any) => boolean | Promise<boolean>);
score?: ScoreValidator;
}
import { ErrorCode } from '../enums/error-code';
export interface GoogleRecaptchaValidationResult {
success: boolean;
score?: number;
errors: ErrorCode[];
}
/// <reference types="node" />
import * as https from 'https';
import { GoogleRecaptchaNetwork } from '../enums/google-recaptcha-network';
import { ScoreValidator } from '../types';
export interface GoogleRecaptchaValidatorOptions {
secretKey: string;
actions?: string[];
score?: ScoreValidator;
network?: GoogleRecaptchaNetwork | string;
agent?: https.Agent;
}
{
"name": "@nestlab/google-recaptcha",
"version": "1.2.4",
"version": "2.0.0",
"description": "Google recaptcha module for NestJS.",

@@ -22,3 +22,3 @@ "keywords": [

"build": "rimraf dist && tsc && cp package.json dist && cp README.md dist && cp LICENSE dist && cp CONTRIBUTING.md dist",
"test": "jest",
"test": "jest --silent=false",
"test:cov": "jest --coverage"

@@ -25,0 +25,0 @@ },

export declare const RECAPTCHA_OPTIONS: unique symbol;
export declare const RECAPTCHA_RESPONSE_PROVIDER: unique symbol;
export declare const RECAPTCHA_VALIDATION_OPTIONS: unique symbol;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RECAPTCHA_RESPONSE_PROVIDER = exports.RECAPTCHA_OPTIONS = void 0;
exports.RECAPTCHA_VALIDATION_OPTIONS = exports.RECAPTCHA_OPTIONS = void 0;
exports.RECAPTCHA_OPTIONS = Symbol('RECAPTCHA_OPTIONS');
exports.RECAPTCHA_RESPONSE_PROVIDER = Symbol('RECAPTCHA_RESPONSE_PROVIDER');
exports.RECAPTCHA_VALIDATION_OPTIONS = Symbol('RECAPTCHA_VALIDATION_OPTIONS');
//# sourceMappingURL=provider.declarations.js.map

@@ -47,2 +47,21 @@ # Google recaptcha module

**Configuration for reCAPTCHA V3**
```typescript
@Module({
imports: [
GoogleRecaptchaModule.forRoot({
secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY,
response: (req: IncomingMessage) => (req.headers.recaptcha || '').toString(),
skipIf: process.env.NODE_ENV !== 'production',
agent: null,
actions: ['SignUp', 'SignIn'],
score: 0.8,
})
],
})
export class AppModule {
}
```
**Configuration for GraphQL application**

@@ -82,2 +101,4 @@

| `agent` | Optional.<br> Type: `https.Agent`<br> If you need to use an agent |
| `score` | Optional.<br> Type: `number` \| `(score: number) => boolean`<br> Score validator for reCAPTCHA v3. <br> `number` - minimum available score. <br> `(score: number) => boolean` - function with custom validation rules. |
| `actions` | Optional.<br> Type: `string[]`<br> Available action list for reCAPTCHA v3. <br> You can make this check stricter by passing the action property parameter to `@Recaptcha(...)` decorator. |

@@ -111,3 +132,7 @@ If you want import configs from your [ConfigService](https://docs.nestjs.com/techniques/configuration#getting-started) via [custom getter function](https://docs.nestjs.com/techniques/configuration#custom-getter-functions) that will return `GoogleRecaptchaModuleOptions` object.

async someAction(recaptchaToken: string): Promise<void> {
const result = await this.recaptchaValidator.validate(recaptchaToken);
const result = await this.recaptchaValidator.validate({
response: recaptchaToken,
score: 0.8,
action: 'SomeAction',
});

@@ -145,3 +170,3 @@ if (!result.success) {

export class FeedbackController {
@Recaptcha(req => req.body.recaptha)
@Recaptcha({response: req => req.body.recaptha})
@Post('send')

@@ -155,2 +180,17 @@ async send(): Promise<any> {

Also you can override recaptcha v3 options.
```typescript
@Controller('feedback')
export class FeedbackController {
@Recaptcha({response: req => req.body.recaptha, action: 'Send', score: 0.8})
@Post('send')
async send(): Promise<any> {
// TODO: Your implementation.
}
}
```
If you want use google recaptcha guard in combination with another guards then you can use `@UseGuards` decorator.

@@ -198,3 +238,3 @@

// Overridden default header. This query using X-Recaptcha header
@Recaptcha((req: IncomingMessage) => (req.headers['x-recaptcha'] || '').toString())
@Recaptcha({response: (req: IncomingMessage) => (req.headers['x-recaptcha'] || '').toString()})
@Query(returns => [Recipe])

@@ -201,0 +241,0 @@ recipes(@Args() recipesArgs: RecipesArgs): Promise<Recipe[]> {

import { HttpService } from '@nestjs/common';
import { GoogleRecaptchaValidatorOptions } from '../interfaces/google-recaptcha-validator-options';
import { GoogleRecaptchaValidationResult } from '../interfaces/google-recaptcha-validation-result';
import { VerifyResponseOptions } from '../interfaces/verify-response-decorator-options';
export declare class GoogleRecaptchaValidator {

@@ -10,3 +11,7 @@ private readonly http;

constructor(http: HttpService, options: GoogleRecaptchaValidatorOptions);
validate(response: string): Promise<GoogleRecaptchaValidationResult>;
validate(options: VerifyResponseOptions): Promise<GoogleRecaptchaValidationResult>;
private verifyResponse;
private isValidAction;
private isValidScore;
private isUseV3;
}

@@ -19,4 +19,4 @@ "use strict";

const qs = require("querystring");
const google_recaptcha_network_1 = require("../enums/google-recaptcha-network");
const error_code_1 = require("../enums/error-code");
const google_recaptcha_network_1 = require("../enums/google-recaptcha-network");
let GoogleRecaptchaValidator = class GoogleRecaptchaValidator {

@@ -29,3 +29,19 @@ constructor(http, options) {

}
validate(response) {
async validate(options) {
const result = await this.verifyResponse(options.response);
if (!this.isUseV3(result)) {
return result;
}
console.log(result);
if (!this.isValidAction(result.action, options)) {
result.success = false;
result.errors.push(error_code_1.ErrorCode.ForbiddenAction);
}
if (!this.isValidScore(result.score, options.score)) {
result.success = false;
result.errors.push(error_code_1.ErrorCode.LowScore);
}
return result;
}
verifyResponse(response) {
const data = qs.stringify({ secret: this.options.secretKey, response });

@@ -39,6 +55,7 @@ const url = this.options.network || this.defaultNetwork;

.then(res => res.data)
.then(result => ({
success: result.success,
errors: result['error-codes'] || [],
}))
.then(result => (Object.assign(Object.assign({}, result), { errors: result['error-codes'] || [] })))
.then(result => {
delete result['error-codes'];
return result;
})
.catch(() => ({

@@ -49,2 +66,24 @@ success: false,

}
isValidAction(action, options) {
if (options.action) {
return options.action === action;
}
return this.options.actions
? this.options.actions.includes(action)
: true;
}
isValidScore(score, validator) {
const finalValidator = validator || this.options.score;
if (finalValidator) {
if (typeof finalValidator === 'function') {
return finalValidator(score);
}
return score >= finalValidator;
}
return true;
}
isUseV3(v) {
return ('score' in v && typeof v['score'] === 'number') &&
('action' in v && typeof v['action'] === 'string');
}
};

@@ -51,0 +90,0 @@ GoogleRecaptchaValidator = __decorate([

export declare type RecaptchaResponseProvider = (req: any) => string | Promise<string>;
export declare type ScoreValidator = number | ((score: number) => boolean);

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc