@nestlab/google-recaptcha 3.3.0 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +268 -0
  2. package/README.md +309 -107
  3. package/package.json +3 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,268 @@
1
+ # Changelog
2
+
3
+ ## v3.3.1
4
+ - Reworked readme docs.
5
+ - Added changelog file.
6
+
7
+ ## v3.3.0
8
+ - Reworked to use axios instead of @nestjs/axios.
9
+ - Removed peer dependencies:
10
+ - `@nestjs/axios`
11
+ - `rxjs`
12
+
13
+ ## v3.2.0
14
+
15
+ - Upgraded peer dependencies versions:
16
+ - `@nestjs/axios`: >=1.0.0 <2.0.0
17
+ - `axios`: >=1.0.0 <2.0.0
18
+
19
+ ## v3.1.9
20
+
21
+ - Declared used axios package as peerDependency.
22
+
23
+ ## v3.1.8
24
+
25
+ - Fixed async module options type in ts strict mode.
26
+ - Declared used `rxjs` package as peerDependency.
27
+
28
+ ## v3.1.7
29
+
30
+ - Smallfix with logging recaptcha results.
31
+ - Fixed resolving error codes for enterprise validator.
32
+
33
+ ## v3.1.6
34
+
35
+ - Fixed handling enterprise response without token properties info.
36
+
37
+ ## v3.1.5
38
+
39
+ - Fixed recaptcha enterprise error handling.
40
+
41
+ ## v3.1.4
42
+
43
+ - Fixed instance of response for recaptcha v2.
44
+ - Fixed error handling for recaptcha enterprise.
45
+ - Internal fixes.
46
+ - Test coverage.
47
+
48
+ ## v3.1.3
49
+
50
+ - Fixed response type for `RecaptchaVerificationResult.getEnterpriseRiskAnalytics()`.
51
+
52
+ ## v3.1.2
53
+
54
+ - Fixed http exception statuses for error codes: `site-mismatch`, `browser-error` (HTTP status - 400).
55
+ - Added error code: `incorrect-captcha-sol`.
56
+
57
+ ## v3.1.1
58
+
59
+ - Minor type fixes by eslint rules.
60
+ - Fixes in: README.md, package.json.
61
+
62
+ ## v3.1.0
63
+
64
+ - Added support reCAPTCHA Enterprise API.
65
+ - Updated module options:
66
+ - Updated `secretKey` as optional (shouldn't use for enterprise configuration).
67
+ - Added `enterprise` option
68
+
69
+ | Property | Description |
70
+ |---------------------------------|-------------|
71
+ | `enterprise.projectId` | **Required.**<br> Type: `string`<br> Google Cloud project ID |
72
+ | `enterprise.siteKey` | **Required.**<br> Type: `string`<br> [reCAPTCHA key](https://cloud.google.com/recaptcha-enterprise/docs/keys) associated with the site/app. |
73
+ | `enterprise.apiKey` | **Required.**<br> Type: `string`<br> API key associated with the current project. <br>Must have permission `reCAPTCHA Enterprise API`. <br> You can manage credentials [here](https://console.cloud.google.com/apis/credentials). |
74
+
75
+ **Updated GoogleRecaptchaValidator interface**
76
+
77
+ ```typescript
78
+ class GoogleRecaptchaValidator {
79
+ validate(options: VerifyResponseOptions): Promise<RecaptchaVerificationResult<VerifyResponseV3>>;
80
+ }
81
+ ```
82
+
83
+ **Addded recaptcha validator for enterprise**
84
+
85
+ ```typescript
86
+ @Injectable()
87
+ export class SomeService {
88
+ constructor(private readonly recaptchaEnterpriseValidator: GoogleRecaptchaEnterpriseValidator) {
89
+ }
90
+
91
+ async someAction(recaptchaToken: string): Promise<void> {
92
+ const result = await this.recaptchaEnterpriseValidator.validate({
93
+ response: recaptchaToken,
94
+ score: 0.8,
95
+ action: 'SomeAction',
96
+ });
97
+
98
+ if (!result.success) {
99
+ throw new GoogleRecaptchaException(result.errors);
100
+ }
101
+
102
+ const riskAnalytics = result.getEnterpriseRiskAnalytics();
103
+
104
+ console.log('score', riskAnalysis.score);
105
+ console.log('score', riskAnalysis.reasons);
106
+
107
+ // TODO: Your implemetation
108
+ }
109
+ }
110
+ ```
111
+
112
+
113
+ ## v3.0.3
114
+
115
+ - Updated README.md.
116
+
117
+ ## v3.0.2
118
+
119
+ - Added debug mode and logging
120
+ - Added module options
121
+ - `debug?: boolean` enables debug mode
122
+ - `logger?: Logger` instance of Logger from @nestjs/common or extended from this
123
+
124
+ ## v3.0.1
125
+
126
+ - Fixed published root dir
127
+
128
+ ## v3.0.0
129
+
130
+ - Compat with NestJS 9
131
+ - Removed deprecated options:
132
+ - `applicationType?: ApplicationType` (now detect it automatically)
133
+ - `agent?: https.Agent` (use option axiosConfig.httpsAgent)
134
+
135
+ ## v2.1.2
136
+
137
+ - Fixed decorators reexports
138
+
139
+ ## v2.1.1
140
+
141
+ - Removed source maps. Little fixes in readme file.
142
+
143
+ ## v2.1.0
144
+
145
+ - Added request type auto detection from execution context`applicationType` configuration option marked as deprecated. Will removed in next major release.
146
+
147
+ ## v2.0.8
148
+
149
+ - Fixed README.md.
150
+
151
+ ## 2.0.7
152
+
153
+ - Added axiosConfig: AxiosRequestConfig option.
154
+ - Option agent?: https.Agent marked as deprecated.
155
+ - Added GoogleRecaptchaNetworkException.
156
+
157
+ ## v2.0.6
158
+
159
+ - Added support NestJS 8.
160
+ - Dynamic loading HttpModule from `@nestjs/axios` or `@nestjs/common`.
161
+
162
+ ## v2.0.5
163
+
164
+ - Fixed dynamic module loading.
165
+
166
+ ## v2.0.4
167
+
168
+ - Added `RecaptchaResult` decorator.
169
+
170
+ ## v2.0.3
171
+
172
+ - Added `SetRecaptchaOptions` decorator.
173
+
174
+ ## v2.0.2
175
+
176
+ - Added error handling for invalid-keys.
177
+
178
+ ## v2.0.1
179
+
180
+ - Removed console.log
181
+
182
+ ## v2.0.0
183
+
184
+ - Added validation by action and score for reCAPTCHA v3.
185
+ - Updated external interfaces. Affected places:
186
+ - service GoogleRecaptchaValidator
187
+ - decorator Recaptcha
188
+ - module options (added optional default parameters)
189
+
190
+ ## v1.2.4
191
+
192
+ - Fixed readme.
193
+
194
+ ## v.1.2.3
195
+
196
+ - Updated readme. Added example to use validation in service.
197
+
198
+ ## v1.2.2
199
+
200
+ - Added support GraphQL.
201
+
202
+ ## v1.2.1
203
+
204
+ - Added LICENSE, CONTRIBUTING.md to build. Fixed readme.
205
+
206
+ ## v1.2.0
207
+
208
+ - Updated google recaptcha module options.
209
+ - Removed option useRecaptchaNet: boolean
210
+ - Added option: network: GoogleRecaptchaNetwork | string <br>If your server has trouble connecting to 'https://google.com' then you can set networks:
211
+ <br/>GoogleRecaptchaNetwork.Google = 'https://www.google.com/recaptcha/api/siteverify'
212
+ </br>GoogleRecaptchaNetwork.Recaptcha = 'https://recaptcha.net/recaptcha/api/siteverify'
213
+ or set any api url
214
+
215
+ ## v1.1.11
216
+
217
+ Removed unused dev dependencies. Updated readme.
218
+
219
+ ## v1.1.10
220
+
221
+ - Extended peer dependencies versions:
222
+ - @nestjs/core: >=6.0.0 <8.0.0
223
+ - @nestjs/common: >=6.0.0 <8.0.0
224
+
225
+ ## v1.1.9
226
+
227
+ - Fixed global option for `forRootAsync` method.
228
+
229
+ ## v1.1.8
230
+
231
+ - Module declared as global.
232
+
233
+ ## v1.1.7
234
+
235
+ - Fixed readme.md file.
236
+
237
+ ## v1.1.6
238
+
239
+ - Updated `skipIf` option to `boolean | ((request: any) => boolean | Promise<boolean>)`
240
+
241
+ ## v1.1.5
242
+
243
+ - Updated skipIf argument from `() => boolean` to `(request) => boolean | Promise<boolean>`.
244
+
245
+ ## v1.1.4
246
+
247
+ - Added option to use recaptcha.net and agent support.
248
+
249
+ ## v1.1.3
250
+
251
+ - Async module initialization.
252
+
253
+ ## v1.1.2
254
+
255
+ - Added override ability default recaptcha property.
256
+
257
+ ## v1.1.1
258
+
259
+ - Updated `GoogleRecaptchaException`.
260
+
261
+
262
+ ## v1.1.0
263
+
264
+ - Added `GoogleRecaptchaException`. Error handling via exception filter.
265
+
266
+ ## v1.0.13
267
+
268
+ - Reexported types
package/README.md CHANGED
@@ -1,22 +1,35 @@
1
- # Google recaptcha module
1
+ # @nestlab/google-recaptcha
2
+
3
+ This package provides protection for endpoints using [reCAPTCHA](https://www.google.com/recaptcha/about/) for [NestJS](https://docs.nestjs.com/) REST and GraphQL applications. By integrating with reCAPTCHA, this package helps to prevent automated abuse such as spam and bots, improving the security and reliability of your application.
4
+
2
5
  [![NPM Version](https://img.shields.io/npm/v/@nestlab/google-recaptcha.svg)](https://www.npmjs.com/package/@nestlab/google-recaptcha)
3
6
  [![Licence](https://img.shields.io/npm/l/@nestlab/google-recaptcha.svg)](https://github.com/chvarkov/google-recaptcha/blob/master/LICENSE)
4
7
  [![NPM Downloads](https://img.shields.io/npm/dm/@nestlab/google-recaptcha.svg)](https://www.npmjs.com/package/@nestlab/google-recaptcha)
5
8
  [![Circle CI build](https://img.shields.io/circleci/build/github/chvarkov/google-recaptcha/master)](https://github.com/chvarkov/google-recaptcha/tree/master)
6
9
  [![Coverage Status](https://coveralls.io/repos/github/chvarkov/google-recaptcha/badge.svg?branch=master)](https://coveralls.io/github/chvarkov/google-recaptcha?branch=master)
7
10
 
8
- The [NestJS](https://docs.nestjs.com/) module to protect your endpoints via [google recaptcha](https://www.google.com/recaptcha/about/).
9
-
10
- Supported for HTTP and GraphQL [NestJS](https://docs.nestjs.com/) applications.
11
-
12
- - [Installation](#installation)
13
- - [Configuration](#configuration)
14
- - [Usage](#usage)
15
- - [Validate in service](#validate-in-service)
16
- - [Validate in service (enterprise)](#validate-in-service-enterprise)
17
- - [Guard](#guard)
18
- - [GraphQL guard](#graphql-guard)
19
- - [Error handling](#error-handling)
11
+ ## Table of Contents
12
+
13
+ * [Installation](#installation)
14
+ * [Changes](#changes)
15
+ * [Configuration](#configuration)
16
+ * [Options](#options)
17
+ * [REST application](#rest-application)
18
+ * [reCAPTCHA v2](#rest-recaptcha-v2)
19
+ * [reCAPTCHA v3](#rest-recaptcha-v3)
20
+ * [reCAPTCHA Enterprise](#rest-recaptcha-enterprise)
21
+ * [Graphql application](#graphql-application)
22
+ * [reCAPTCHA v2](#graphql-recaptcha-v2)
23
+ * [reCAPTCHA v3](#graphql-recaptcha-v3)
24
+ * [reCAPTCHA Enterprise](#graphql-recaptcha-enterprise)
25
+ * [Usage](#usage)
26
+ * [REST application](#usage-in-rest-application)
27
+ * [Graphql application](#usage-in-graphql-application)
28
+ * [Validate in service](#validate-in-service)
29
+ * [Validate in service (Enterprise)](#validate-in-service-enterprise)
30
+ * [Error handling](#error-handling)
31
+ * [Contribution](#contribution)
32
+ * [License](#license)
20
33
 
21
34
  Usage example [here](https://github.com/chvarkov/google-recaptcha-example)
22
35
 
@@ -27,9 +40,45 @@ Usage example [here](https://github.com/chvarkov/google-recaptcha-example)
27
40
  $ npm i @nestlab/google-recaptcha
28
41
  ```
29
42
 
43
+ ## Changes
44
+
45
+ The list of changes made in the project can be found in the [CHANGELOG.md](./CHANGELOG.md) file.
46
+
30
47
  ## Configuration
31
48
 
32
- **Configuration for REST application**
49
+ ### Options
50
+
51
+ **GoogleRecaptchaModuleOptions**
52
+
53
+ | Property | Description |
54
+ |-------------------|-------------|
55
+ | `response` | **Required.**<br> Type: `(request) => string`<br> Function that returns response (recaptcha token) by request |
56
+ | `secretKey` | Optional.<br> Type: `string`<br> Google recaptcha secret key. Must be set if you don't use reCAPTCHA Enterprise |
57
+ | `debug` | Optional.<br> Type: `boolean` <br> Default: `false` <br> Enables logging requests, responses, errors and transformed results |
58
+ | `logger` | Optional.<br> Type: `Logger` <br> Default: `new Logger()` <br> Instance of custom logger that extended from Logger (@nestjs/common) |
59
+ | `skipIf` | Optional.<br> Type: `boolean` \| `(request) => boolean \| Promise<boolean>` <br> Function that returns true if you allow the request to skip the recaptcha verification. Useful for involing other check methods (e.g. custom privileged API key) or for development or testing |
60
+ | `enterprise` | Optional.<br> Type: `GoogleRecaptchaEnterpriseOptions` <br> Options for using recCAPTCHA Enterprise API. Cannot using with `secretKey` option. |
61
+ | `network` | Optional.<br> Type: `GoogleRecaptchaNetwork` \| `string`<br> Default: `GoogleRecaptchaNetwork.Google` <br> If your server has trouble connecting to https://google.com then you can set networks:<br> `GoogleRecaptchaNetwork.Google` = 'https://www.google.com/recaptcha/api/siteverify'<br>`GoogleRecaptchaNetwork.Recaptcha` = 'https://recaptcha.net/recaptcha/api/siteverify'<br> or set any api url |
62
+ | `score` | Optional.<br> Type: `number` \| `(score: number) => boolean`<br> Score validator for reCAPTCHA v3 or enterprise. <br> `number` - minimum available score. <br> `(score: number) => boolean` - function with custom validation rules. |
63
+ | `actions` | Optional.<br> Type: `string[]`<br> Available action list for reCAPTCHA v3 or enterprise. <br> You can make this check stricter by passing the action property parameter to `@Recaptcha(...)` decorator. |
64
+ | `axiosConfig` | Optional.<br> Type: `AxiosRequestConfig`<br> Allows to setup proxy, response timeout, https agent etc... |
65
+
66
+ **GoogleRecaptchaEnterpriseOptions**
67
+
68
+ | Property | Description |
69
+ |-----------------|-------------|
70
+ | `projectId` | **Required.**<br> Type: `string`<br> Google Cloud project ID |
71
+ | `siteKey` | **Required.**<br> Type: `string`<br> [reCAPTCHA key](https://cloud.google.com/recaptcha-enterprise/docs/keys) associated with the site/app. |
72
+ | `apiKey` | **Required.**<br> Type: `string`<br> API key associated with the current project. <br>Must have permission `reCAPTCHA Enterprise API`. <br> You can manage credentials [here](https://console.cloud.google.com/apis/credentials). |
73
+
74
+
75
+ The module provides two static methods for configuration: `forRoot` and `forRootAsync`.
76
+
77
+ **forRoot**
78
+
79
+ > forRoot(options: GoogleRecaptchaModuleOptions): DynamicModule
80
+
81
+ The `forRoot` method accepts a `GoogleRecaptchaModuleOptions` object that configures the module. This method should be used in the root `AppModule`. <br/>Example usage:
33
82
 
34
83
  ```typescript
35
84
  @Module({
@@ -37,8 +86,6 @@ $ npm i @nestlab/google-recaptcha
37
86
  GoogleRecaptchaModule.forRoot({
38
87
  secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY,
39
88
  response: req => req.headers.recaptcha,
40
- skipIf: process.env.NODE_ENV !== 'production',
41
- network: GoogleRecaptchaNetwork.Recaptcha,
42
89
  })
43
90
  ],
44
91
  })
@@ -46,40 +93,94 @@ export class AppModule {
46
93
  }
47
94
  ```
48
95
 
49
- **Configuration for reCAPTCHA V3**
96
+ **forRootAsync**
97
+
98
+ > forRootAsync(options: ModuleAsyncOptions): DynamicModule
99
+
100
+ The `forRootAsync` method is similar to `forRoot`, but allows for asynchronous configuration.<br/>
101
+ It accepts a `GoogleRecaptchaModuleAsyncOptions` object that returns a configuration object or a Promise that resolves to a configuration object. <br/>
102
+ Read more about [ConfigService](https://docs.nestjs.com/techniques/configuration#getting-started) and [custom getter function](https://docs.nestjs.com/techniques/configuration#custom-getter-functions).
103
+
104
+ Example usage:
105
+
106
+ ```typescript
107
+ @Module({
108
+ imports: [
109
+ GoogleRecaptchaModule.forRootAsync({
110
+ imports: [ConfigModule],
111
+ useFactory: (configService: ConfigService) => configService.googleRecaptchaOptions,
112
+ inject: [ConfigService],
113
+ })
114
+ ],
115
+ })
116
+ export class AppModule {
117
+ }
118
+ ```
119
+
120
+ ### REST application
121
+
122
+ #### REST reCAPTCHA V2
50
123
 
51
124
  ```typescript
52
125
  @Module({
53
126
  imports: [
54
127
  GoogleRecaptchaModule.forRoot({
55
128
  secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY,
56
- response: (req: IncomingMessage) => (req.headers.recaptcha || '').toString(),
129
+ response: req => req.headers.recaptcha,
130
+ skipIf: process.env.NODE_ENV !== 'production',
131
+ }),
132
+ ],
133
+ })
134
+ export class AppModule {
135
+ }
136
+ ```
137
+
138
+ **Tip: header names transforming to lower case.**
139
+
140
+ **For example:** If you send 'Recaptcha' header then use `(req) => req.headers.recaptcha`
141
+
142
+ <br/>
143
+
144
+ #### REST reCAPTCHA V3
145
+
146
+ ```typescript
147
+ @Module({
148
+ imports: [
149
+ GoogleRecaptchaModule.forRoot({
150
+ secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY,
151
+ response: req => req.headers.recaptcha,
57
152
  skipIf: process.env.NODE_ENV !== 'production',
58
153
  actions: ['SignUp', 'SignIn'],
59
154
  score: 0.8,
60
- })
155
+ }),
61
156
  ],
62
157
  })
63
158
  export class AppModule {
64
159
  }
65
160
  ```
66
161
 
67
- **Configuration for reCAPTCHA Enterprise**
162
+ **Tip: header names transforming to lower case.**
163
+
164
+ **For example:** If you send 'Recaptcha' header then use `(req) => req.headers.recaptcha`
165
+
166
+ <br/>
167
+
168
+ #### REST reCAPTCHA Enterprise
68
169
 
69
170
  ```typescript
70
171
  @Module({
71
172
  imports: [
72
173
  GoogleRecaptchaModule.forRoot({
73
- response: (req: IncomingMessage) => (req.headers.recaptcha || '').toString(),
174
+ response: (req) => req.headers.recaptcha,
74
175
  skipIf: process.env.NODE_ENV !== 'production',
75
176
  actions: ['SignUp', 'SignIn'],
76
177
  score: 0.8,
77
- enterprise: {
78
- projectId: process.env.RECAPTCHA_ENTERPRISE_PROJECT_ID,
79
- siteKey: process.env.RECAPTCHA_ENTERPRISE_SITE_KEY,
80
- apiKey: process.env.RECAPTCHA_ENTERPRISE_API_KEY,
178
+ enterprise: {
179
+ projectId: process.env.RECAPTCHA_ENTERPRISE_PROJECT_ID,
180
+ siteKey: process.env.RECAPTCHA_ENTERPRISE_SITE_KEY,
181
+ apiKey: process.env.RECAPTCHA_ENTERPRISE_API_KEY,
81
182
  },
82
- })
183
+ }),
83
184
  ],
84
185
  })
85
186
  export class AppModule {
@@ -90,99 +191,108 @@ export class AppModule {
90
191
 
91
192
  **For example:** If you send 'Recaptcha' header then use `(req) => req.headers.recaptcha`
92
193
 
93
- #### Configuration options
194
+ ### Graphql application
94
195
 
95
- | Property | Description |
96
- |-------------------|-------------|
97
- | `response` | **Required.**<br> Type: `(request) => string`<br> Function that returns response (recaptcha token) by request |
98
- | `secretKey` | Optional.<br> Type: `string`<br> Google recaptcha secret key. Must be set if you don't use reCAPTCHA Enterprise |
99
- | `debug` | Optional.<br> Type: `boolean` <br> Default: `false` <br> Enables logging requests, responses, errors and transformed results |
100
- | `logger` | Optional.<br> Type: `Logger` <br> Default: `new Logger()` <br> Instance of custom logger that extended from Logger (@nestjs/common) |
101
- | `skipIf` | Optional.<br> Type: `boolean` \| `(request) => boolean \| Promise<boolean>` <br> Function that returns true if you allow the request to skip the recaptcha verification. Useful for involing other check methods (e.g. custom privileged API key) or for development or testing |
102
- | `enterprise` | Optional.<br> Type: [`GoogleRecaptchaEnterpriseOptions`](#GoogleRecaptchaEnterpriseOptions) <br> Options for using recCAPTCHA Enterprise API. Cannot using with `secretKey` option. |
103
- | `network` | Optional.<br> Type: `GoogleRecaptchaNetwork` \| `string`<br> Default: `GoogleRecaptchaNetwork.Google` <br> If your server has trouble connecting to https://google.com then you can set networks:<br> `GoogleRecaptchaNetwork.Google` = 'https://www.google.com/recaptcha/api/siteverify'<br>`GoogleRecaptchaNetwork.Recaptcha` = 'https://recaptcha.net/recaptcha/api/siteverify'<br> or set any api url |
104
- | `score` | Optional.<br> Type: `number` \| `(score: number) => boolean`<br> Score validator for reCAPTCHA v3 or enterprise. <br> `number` - minimum available score. <br> `(score: number) => boolean` - function with custom validation rules. |
105
- | `actions` | Optional.<br> Type: `string[]`<br> Available action list for reCAPTCHA v3 or enterprise. <br> You can make this check stricter by passing the action property parameter to `@Recaptcha(...)` decorator. |
106
- | `axiosConfig` | Optional.<br> Type: `AxiosRequestConfig`<br> Allows to setup proxy, response timeout, https agent etc... |
196
+ #### Graphql reCAPTCHA V2
197
+
198
+ ```typescript
199
+ @Module({
200
+ imports: [
201
+ GoogleRecaptchaModule.forRoot({
202
+ secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY,
203
+ response: (req: IncomingMessage) => (req.headers.recaptcha || '').toString(),
204
+ skipIf: process.env.NODE_ENV !== 'production',
205
+ }),
206
+ ],
207
+ })
208
+ export class AppModule {
209
+ }
210
+ ```
107
211
 
108
- #### GoogleRecaptchaEnterpriseOptions
212
+ **Tip: header names transforming to lower case.**
109
213
 
110
- | Property | Description |
111
- |-----------------|-------------|
112
- | `projectId` | **Required.**<br> Type: `string`<br> Google Cloud project ID |
113
- | `siteKey` | **Required.**<br> Type: `string`<br> [reCAPTCHA key](https://cloud.google.com/recaptcha-enterprise/docs/keys) associated with the site/app. |
114
- | `apiKey` | **Required.**<br> Type: `string`<br> API key associated with the current project. <br>Must have permission `reCAPTCHA Enterprise API`. <br> You can manage credentials [here](https://console.cloud.google.com/apis/credentials). |
214
+ **For example:** If you send 'Recaptcha' header then use `(req: IncomingMessage) => (req.headers.recaptcha || '').toString()`
115
215
 
116
- 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.
216
+ <br/>
217
+
218
+ #### Graphql reCAPTCHA V3
117
219
 
118
220
  ```typescript
119
221
  @Module({
120
222
  imports: [
121
- GoogleRecaptchaModule.forRootAsync({
122
- imports: [ConfigModule],
123
- useFactory: (configService: ConfigService) => configService.googleRecaptchaOptions,
124
- inject: [ConfigService],
125
- })
223
+ GoogleRecaptchaModule.forRoot({
224
+ secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY,
225
+ response: (req: IncomingMessage) => (req.headers.recaptcha || '').toString(),
226
+ skipIf: process.env.NODE_ENV !== 'production',
227
+ actions: ['SignUp', 'SignIn'],
228
+ score: 0.8,
229
+ }),
126
230
  ],
127
231
  })
128
232
  export class AppModule {
129
233
  }
130
234
  ```
131
235
 
132
- ## Usage
236
+ **Tip: header names transforming to lower case.**
133
237
 
134
- ### Validate in service
238
+ **For example:** If you send 'Recaptcha' header then use `(req: IncomingMessage) => (req.headers.recaptcha || '').toString()`
135
239
 
136
- ```typescript
137
- @Injectable()
138
- export class SomeService {
139
- constructor(private readonly recaptchaValidator: GoogleRecaptchaValidator) {
140
- }
240
+ <br/>
141
241
 
142
- async someAction(recaptchaToken: string): Promise<void> {
143
- const result = await this.recaptchaValidator.validate({
144
- response: recaptchaToken,
242
+ #### Graphql reCAPTCHA Enterprise
243
+
244
+ ```typescript
245
+ @Module({
246
+ imports: [
247
+ GoogleRecaptchaModule.forRoot({
248
+ response: (req: IncomingMessage) => (req.headers.recaptcha || '').toString(),
249
+ skipIf: process.env.NODE_ENV !== 'production',
250
+ actions: ['SignUp', 'SignIn'],
145
251
  score: 0.8,
146
- action: 'SomeAction',
147
- });
148
-
149
- if (!result.success) {
150
- throw new GoogleRecaptchaException(result.errors);
151
- }
152
- // TODO: Your implemetation
153
- }
252
+ enterprise: {
253
+ projectId: process.env.RECAPTCHA_ENTERPRISE_PROJECT_ID,
254
+ siteKey: process.env.RECAPTCHA_ENTERPRISE_SITE_KEY,
255
+ apiKey: process.env.RECAPTCHA_ENTERPRISE_API_KEY,
256
+ },
257
+ }),
258
+ ],
259
+ })
260
+ export class AppModule {
154
261
  }
155
262
  ```
156
263
 
157
- ### Validate in service (Enterprise)
264
+ **Tip: header names transforming to lower case.**
158
265
 
159
- ```typescript
160
- @Injectable()
161
- export class SomeService {
162
- constructor(private readonly recaptchaEnterpriseValidator: GoogleRecaptchaEnterpriseValidator) {
163
- }
266
+ **For example:** If you send 'Recaptcha' header then use `(req) => req.headers.recaptcha`
164
267
 
165
- async someAction(recaptchaToken: string): Promise<void> {
166
- const result = await this.recaptchaEnterpriseValidator.validate({
167
- response: recaptchaToken,
268
+
269
+ **Configuration for reCAPTCHA Enterprise**
270
+
271
+ ```typescript
272
+ @Module({
273
+ imports: [
274
+ GoogleRecaptchaModule.forRoot({
275
+ response: (req) => req.headers.recaptcha,
276
+ skipIf: process.env.NODE_ENV !== 'production',
277
+ actions: ['SignUp', 'SignIn'],
168
278
  score: 0.8,
169
- action: 'SomeAction',
170
- });
171
-
172
- if (!result.success) {
173
- throw new GoogleRecaptchaException(result.errors);
174
- }
175
-
176
- const riskAnalytics = result.getEnterpriseRiskAnalytics();
177
-
178
- // TODO: Your implemetation
179
- }
279
+ enterprise: {
280
+ projectId: process.env.RECAPTCHA_ENTERPRISE_PROJECT_ID,
281
+ siteKey: process.env.RECAPTCHA_ENTERPRISE_SITE_KEY,
282
+ apiKey: process.env.RECAPTCHA_ENTERPRISE_API_KEY,
283
+ },
284
+ }),
285
+ ],
286
+ })
287
+ export class AppModule {
180
288
  }
181
289
  ```
182
290
 
183
- ### Guard
291
+ ## Usage
292
+
293
+ ### Usage in REST application
184
294
 
185
- Use `@Recaptcha` decorator to protect your endpoints.
295
+ To protect your REST endpoints, you can use the `@Recaptcha` decorator.<br/>Example:
186
296
 
187
297
  ```typescript
188
298
 
@@ -197,7 +307,7 @@ export class FeedbackController {
197
307
 
198
308
  ```
199
309
 
200
- You can override default property that contain recaptcha for specific endpoint.
310
+ You can also override the default property that contains reCAPTCHA for a specific endpoint.<br/>
201
311
 
202
312
  ```typescript
203
313
 
@@ -212,7 +322,7 @@ export class FeedbackController {
212
322
 
213
323
  ```
214
324
 
215
- Also you can override recaptcha v3 options.
325
+ Additionally, you can override reCAPTCHA v3 options.<br/>
216
326
 
217
327
  ```typescript
218
328
 
@@ -227,7 +337,7 @@ export class FeedbackController {
227
337
 
228
338
  ```
229
339
 
230
- Get verification result
340
+ To get the verification result, you can use the @RecaptchaResult() decorator.<br/>
231
341
 
232
342
  ```typescript
233
343
 
@@ -243,8 +353,7 @@ export class FeedbackController {
243
353
 
244
354
  ```
245
355
 
246
- If you want use google recaptcha guard in combination with another guards then you can use `@UseGuards` decorator.
247
-
356
+ If you want to use the Google reCAPTCHA guard in combination with other guards, you can use the `@UseGuards` decorator.<br/>
248
357
  ```typescript
249
358
 
250
359
  @Controller('feedback')
@@ -259,9 +368,11 @@ export class FeedbackController {
259
368
 
260
369
  ```
261
370
 
262
- ### GraphQL guard
371
+ You can find a usage example in the following [link](https://github.com/chvarkov/google-recaptcha-example).
263
372
 
264
- Use `@Recaptcha` decorator to protect your resolver.
373
+ ### Usage in Graphql application
374
+
375
+ To protect your resolver, use the `@Recaptcha` decorator.
265
376
 
266
377
  ```typescript
267
378
  @Recaptcha()
@@ -274,7 +385,22 @@ export class RecipesResolver {
274
385
  }
275
386
  ```
276
387
 
277
- You can override default property that contain recaptcha for specific query, mutation or subscription.
388
+ Obtain verification result:
389
+
390
+ ```typescript
391
+ @Recaptcha()
392
+ @Resolver(of => Recipe)
393
+ export class RecipesResolver {
394
+ @Query(returns => Recipe)
395
+ async recipe(@Args('id') id: string,
396
+ @RecaptchaResult() recaptchaResult: RecaptchaVerificationResult): Promise<Recipe> {
397
+ console.log(`Action: ${recaptchaResult.action} Score: ${recaptchaResult.score}`);
398
+ // TODO: Your implementation.
399
+ }
400
+ }
401
+ ```
402
+
403
+ You can override the default recaptcha property for a specific endpoint.
278
404
 
279
405
  ```typescript
280
406
  @Recaptcha()
@@ -294,21 +420,87 @@ export class RecipesResolver {
294
420
  }
295
421
  ```
296
422
 
297
- ## Error handling
423
+ ### Validate in service
424
+
425
+ ```typescript
426
+ @Injectable()
427
+ export class SomeService {
428
+ constructor(private readonly recaptchaValidator: GoogleRecaptchaValidator) {
429
+ }
430
+
431
+ async someAction(recaptchaToken: string): Promise<void> {
432
+ const result = await this.recaptchaValidator.validate({
433
+ response: recaptchaToken,
434
+ score: 0.8,
435
+ action: 'SomeAction',
436
+ });
437
+
438
+ if (!result.success) {
439
+ throw new GoogleRecaptchaException(result.errors);
440
+ }
441
+ // TODO: Your implemetation
442
+ }
443
+ }
444
+ ```
445
+
446
+ ### Validate in service (Enterprise)
447
+
448
+ ```typescript
449
+ @Injectable()
450
+ export class SomeService {
451
+ constructor(private readonly recaptchaEnterpriseValidator: GoogleRecaptchaEnterpriseValidator) {
452
+ }
453
+
454
+ async someAction(recaptchaToken: string): Promise<void> {
455
+ const result = await this.recaptchaEnterpriseValidator.validate({
456
+ response: recaptchaToken,
457
+ score: 0.8,
458
+ action: 'SomeAction',
459
+ });
460
+
461
+ if (!result.success) {
462
+ throw new GoogleRecaptchaException(result.errors);
463
+ }
464
+
465
+ const riskAnalytics = result.getEnterpriseRiskAnalytics();
466
+
467
+ // TODO: Your implemetation
468
+ }
469
+ }
470
+ ```
298
471
 
299
- Google recaptcha guard will throw GoogleRecaptchaException on error.
472
+ ### Error handling
300
473
 
301
474
  **GoogleRecaptchaException**
302
475
 
303
- `GoogleRecaptchaException` has data with google recaptcha error codes.
476
+ `GoogleRecaptchaException` extends `HttpException` extends `Error`.
477
+
478
+ The `GoogleRecaptchaException` is an exception that can be thrown by the `GoogleRecaptchaGuard` when an error occurs. It extends the `HttpException` class provided by NestJS, which means that it can be caught by an ExceptionFilter in the same way as any other HTTP exception.
479
+
480
+ One important feature of the `GoogleRecaptchaException` is that it contains an array of Error Code values in the errorCodes property. These values can be used to diagnose and handle the error.
304
481
 
305
- `GoogleRecaptchaException` ← `HttpException` ← `Error`.
306
482
 
307
- **GoogleRecaptchaNetworkException**
308
483
 
309
- `GoogleRecaptchaNetworkException` has error code `ErrorCode.NetworkError`.
484
+ | Error code | Description | Status code |
485
+ |----------------------------------|-------------|-------------|
486
+ | `ErrorCode.MissingInputSecret` | The secret parameter is missing. (Throws from reCAPTCHA api). | 500 |
487
+ | `ErrorCode.InvalidInputSecret` | The secret parameter is invalid or malformed. (Throws from reCAPTCHA api). | 500 |
488
+ | `ErrorCode.MissingInputResponse` | The response parameter is missing. (Throws from reCAPTCHA api). | 400 |
489
+ | `ErrorCode.InvalidInputResponse` | The response parameter is invalid or malformed. (Throws from reCAPTCHA api). | 400 |
490
+ | `ErrorCode.BadRequest` | The request is invalid or malformed. (Throws from reCAPTCHA api). | 500 |
491
+ | `ErrorCode.TimeoutOrDuplicate` | The response is no longer valid: either is too old or has been used previously. (Throws from reCAPTCHA api). | 400 |
492
+ | `ErrorCode.UnknownError` | Unknown error. (Throws from reCAPTCHA api). | 500 |
493
+ | `ErrorCode.ForbiddenAction` | Forbidden action. (Throws from guard when expected action not equals to received). | 400 |
494
+ | `ErrorCode.LowScore` | Low score (Throws from guard when expected score less than received). | 400 |
495
+ | `ErrorCode.InvalidKeys` | keys were copied incorrectly, the wrong keys were used for the environment (e.g. development vs production), or if the keys were revoked or deleted from the Google reCAPTCHA admin console.. (Throws from reCAPTCHA api). | 400 |
496
+ | `ErrorCode.NetworkError` | Network error (like ECONNRESET, ECONNREFUSED...). | 500 |
497
+ | `ErrorCode.SiteMismatch` | Site mismatch (Throws from reCAPTCHA Enterprise api only). | 400 |
498
+ | `ErrorCode.BrowserError` | Browser error (Throws from reCAPTCHA Enterprise api only). | 400 |
310
499
 
311
- `GoogleRecaptchaNetworkException` ← `GoogleRecaptchaException`
500
+
501
+ **GoogleRecaptchaNetworkException**
502
+
503
+ The `GoogleRecaptchaNetworkException` is an exception that extends the `GoogleRecaptchaException` class and is thrown in the case of a network error. <br/> It contains a `networkErrorCode` property, which contains the error code of the network error, retrieved from the `code` property of the `AxiosError` object.
312
504
 
313
505
  You can handle it via [ExceptionFilter](https://docs.nestjs.com/exception-filters).
314
506
 
@@ -339,4 +531,14 @@ bootstrap();
339
531
 
340
532
  ```
341
533
 
342
- Enjoy!
534
+ ## Contribution
535
+
536
+ We welcome any contributions to improve our package! If you find a bug, have a feature request, or want to suggest an improvement, feel free to submit an issue on our GitHub repository.
537
+
538
+ If you want to contribute to the codebase directly, please follow our contributing guidelines outlined in the [CONTRIBUTING.md](./CONTRIBUTING.md) file in the repository.
539
+
540
+ We value the contributions of our community and appreciate all efforts to make this package better for everyone. Thank you for your support!
541
+
542
+ ## License
543
+
544
+ This project is licensed under the MIT License - see the [LICENSE.md](./LICENSE) file for details.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestlab/google-recaptcha",
3
- "version": "3.3.0",
3
+ "version": "3.3.1",
4
4
  "description": "Google recaptcha module for NestJS.",
5
5
  "keywords": [
6
6
  "nestjs",
@@ -11,7 +11,7 @@
11
11
  "private": false,
12
12
  "main": "index.js",
13
13
  "scripts": {
14
- "build": "rimraf dist && tsc && cp package.json dist && cp README.md dist && cp LICENSE dist && cp CONTRIBUTING.md dist",
14
+ "build": "rimraf dist && tsc && cp package.json dist && cp README.md dist && cp LICENSE dist && cp CONTRIBUTING.md dist && cp CHANGELOG.md dist",
15
15
  "format": "prettier \"**/*.ts\" \"**/*.json\" --ignore-path ./.prettierignore --write",
16
16
  "lint:fix": "eslint . --fix",
17
17
  "lint:check": "eslint . --max-warnings=0",
@@ -64,7 +64,7 @@
64
64
  "prettier": "^2.7.1",
65
65
  "reflect-metadata": "^0.1.13",
66
66
  "rxjs": "^7.5.6",
67
- "supertest": "^6.2.4",
67
+ "supertest": "^6.3.3",
68
68
  "ts-jest": "^28.0.8",
69
69
  "ts-loader": "^9.3.1",
70
70
  "ts-node": "^10.9.1",