Security News
Input Validation Vulnerabilities Dominate MITRE's 2024 CWE Top 25 List
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
ng-recaptcha
Advanced tools
The ng-recaptcha package is an Angular library that provides a simple way to integrate Google's reCAPTCHA into Angular applications. It supports both reCAPTCHA v2 and v3, allowing developers to add CAPTCHA verification to forms and other interactive elements to enhance security.
Basic reCAPTCHA v2 Integration
This feature allows you to integrate the basic reCAPTCHA v2 into your Angular application. The component listens for the resolved event to handle the CAPTCHA response.
import { Component } from '@angular/core';
@Component({
selector: 'app-recaptcha',
template: '<re-captcha (resolved)="resolved($event)" siteKey="your-site-key"></re-captcha>'
})
export class RecaptchaComponent {
resolved(captchaResponse: string) {
console.log(`Resolved captcha with response: ${captchaResponse}`);
}
}
reCAPTCHA v3 Integration
This feature demonstrates how to use reCAPTCHA v3, which does not require user interaction. Instead, it generates a token based on user behavior, which can be used for verification.
import { Component } from '@angular/core';
import { ReCaptchaV3Service } from 'ng-recaptcha';
@Component({
selector: 'app-recaptcha-v3',
template: '<button (click)="executeAction()">Execute reCAPTCHA v3</button>'
})
export class RecaptchaV3Component {
constructor(private recaptchaV3Service: ReCaptchaV3Service) {}
executeAction() {
this.recaptchaV3Service.execute('importantAction').subscribe((token) => {
console.log(`Token received: ${token}`);
});
}
}
Invisible reCAPTCHA
This feature shows how to implement invisible reCAPTCHA, which is triggered programmatically rather than by user interaction. This is useful for forms where you want to minimize user friction.
import { Component } from '@angular/core';
@Component({
selector: 'app-invisible-recaptcha',
template: '<re-captcha (resolved)="resolved($event)" siteKey="your-site-key" size="invisible"></re-captcha><button (click)="executeCaptcha()">Submit</button>'
})
export class InvisibleRecaptchaComponent {
resolved(captchaResponse: string) {
console.log(`Resolved captcha with response: ${captchaResponse}`);
}
executeCaptcha() {
// Trigger the invisible reCAPTCHA
}
}
ngx-captcha is another Angular library for integrating Google's reCAPTCHA. It supports both reCAPTCHA v2 and v3, similar to ng-recaptcha. However, ngx-captcha offers more customization options and additional features like language support and multiple CAPTCHA instances on a single page.
angular-google-recaptcha is a lightweight Angular package for adding Google's reCAPTCHA to your application. It is simpler and less feature-rich compared to ng-recaptcha, making it suitable for projects that require basic CAPTCHA functionality without additional complexity.
A simple, configurable, easy-to-start component for handling reCAPTCHA v2 and v3.
@angular/forms
required
in formsThe easiest way is to install through yarn or npm:
yarn add ng-recaptcha
npm i ng-recaptcha --save
The below applies to reCAPTCHA v2, for basic usage with reCAPTCHA v3 scroll down to here.
To start with, you need to import the RecaptchaModule
(more on that later):
// app.module.ts
import { RecaptchaModule } from 'ng-recaptcha';
// if you need forms support:
// import { RecaptchaModule, RecaptchaFormsModule } from 'ng-recaptcha';
import { BrowserModule } from '@angular/platform-browser';
import { MyApp } from './app.component.ts';
@NgModule({
bootstrap: [MyApp],
declarations: [MyApp],
imports: [
BrowserModule,
RecaptchaModule,
// RecaptchaFormsModule, // if you need forms support
],
})
export class MyAppModule { }
Once you have done that, the rest is simple:
// app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `<re-captcha (resolved)="resolved($event)" siteKey="YOUR_SITE_KEY"></re-captcha>`,
}) export class MyApp {
resolved(captchaResponse: string) {
console.log(`Resolved captcha with response: ${captchaResponse}`);
}
}
// boot.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { MyAppModule } from './app.module.ts';
platformBrowserDynamic().bootstrapModule(MyAppModule);
reCAPTCHA v3 introduces a different way of bot protection. To work with v3 APIs, ng-recaptcha
provides a service (as opposed to a component). To start with, you need to import the RecaptchaV3Module
and provide your reCAPTCHA v3 site key using RECAPTCHA_V3_SITE_KEY
injection token:
import { BrowserModule } from '@angular/platform-browser';
import { RECAPTCHA_V3_SITE_KEY, RecaptchaV3Module } from 'ng-recaptcha';
import { MyApp } from './app.component.ts';
@NgModule({
bootstrap: [MyApp],
declarations: [MyApp],
imports: [
BrowserModule,
RecaptchaV3Module,
],
providers: [
{ provide: RECAPTCHA_V3_SITE_KEY, useValue: '<YOUR_SITE_KEY>' },
],
})
export class MyAppModule { }
In order to execute a reCAPTCHA v3 action, import the ReCaptchaV3Service
into your desired component:
import { ReCaptchaV3Service } from 'ng-recaptcha';
@Component({
selector: 'recaptcha-demo',
template: `
<button (click)="executeImportantAction()">Important action</button>
`,
})
export class RecaptchaV3DemoComponent {
constructor(
private recaptchaV3Service: ReCaptchaV3Service,
) {
}
public executeImportantAction(): void {
this.recaptchaV3Service.execute('importantAction')
.subscribe((token) => this.handleToken(token));
}
As always with subscriptions, please don't forget to unsubscribe.
A more advanced v3 usage scenario includes listening to all actions and their respectively emitted tokens. This is covered later on this page.
You can also play with this Stackblitz demo to get a feel of how this component can be used.
@angular/forms
There are two modules available for you:
import { RecaptchaModule, RecaptchaFormsModule } from 'ng-recaptcha';
If you want your <re-captcha>
element to work correctly with [(ngModel)]
directive,
you need to import the RecaptchaFormsModule
into your application module (pretty much
like with Angular own '@angular/forms'
module).
The component supports this options:
siteKey
theme
type
size
tabIndex
badge
They are all pretty well described either in the reCAPTCHA docs, or in the invisible reCAPTCHA docs, so I won't duplicate it here.
Besides specifying these options on the component itself, you can provide a global <re-captcha>
configuration - see Configuring the component globally section below.
resolved(response: string)
. Occurs when the captcha resolution value changed.
When user resolves captcha, use response
parameter to send to the server for verification.
This parameter is equivalent to calling grecaptcha.getResponse
.
If the captcha has expired prior to submitting its value to the server, the component
will reset the captcha, and trigger the resolved
event with response === null
.
reset()
. Performs a manual captcha reset. This method might be useful if your form
validation failed, and you need the user to re-enter the captcha.execute()
. Executes the invisible recaptcha. Does nothing if component's size is not set to "invisible". See Invisible reCAPTCHA developers guide for more information.Some properties are global - including siteKey
, size
, and others. You can provide them at the module-level using the RECAPTCHA_SETTINGS
provider:
import { RECAPTCHA_SETTINGS, RecaptchaSettings } from 'ng-recaptcha';
@NgModule({
providers: [
{
provide: RECAPTCHA_SETTINGS,
useValue: { siteKey: '<YOUR_KEY>' } as RecaptchaSettings,
},
],
}) export class MyModule { }
Global properties can be overridden on a case-by-case basis - the values on the <re-captcha>
component itself take precedence over global settings.
<re-captcha>
supports various languages. By default recaptcha will guess the user's language itself
(which is beyond the scope of this lib).
But you can override this behavior and provide a specific language to use.
The language setting is global, though, and cannot be set on a per-captcha basis.
It can be provided like this:
import { RECAPTCHA_LANGUAGE } from 'ng-recaptcha';
@NgModule({
providers: [
{
provide: RECAPTCHA_LANGUAGE,
useValue: 'fr', // use French language
},
],
}) export class MyModule { }
You can find the list of supported languages in reCAPTCHA docs.
By default, the component assumes that the reCAPTCHA API loading will be handled
by the RecaptchaLoaderService
. However, you can override that by providing your
instance of this service to the Angular DI.
The below code snippet is an example of how such a provider can be implemented.
TL;DR: there should be an Observable
that eventually resolves to a
grecaptcha
-compatible object (e.g. grecaptcha
itself).
<script src="https://www.google.com/recaptcha/api.js?render=explicit&onload=onloadCallback"></script>
<script>
// bootstrap the application once the reCAPTCHA api has loaded
function onloadCallback() {
System.import('app').catch(function(err) { console.error(err); });
}
</script>
import { RecaptchaLoaderService } from 'ng-recaptcha';
@Injectable()
export class PreloadedRecaptchaAPIService {
public ready: Observable<ReCaptchaV2.ReCaptcha>;
constructor() {
let readySubject = new BehaviorSubject<ReCaptchaV2.ReCaptcha>(grecaptcha);
this.ready = readySubject.asObservable();
}
}
@NgModule({
providers: [
{
provide: RecaptchaLoaderService,
useValue: new PreloadedRecaptchaAPIService(),
},
],
}) export class MyModule { }
required
in forms (see in action)It's very easy to put <re-captcha>
in an Angular form and have it require
d - just
add the required
attribute to the <re-captcha>
element. Do not forget to import RecaptchaFormsModule
from 'ng-recaptcha'
!
@Component({
selector: 'my-form',
template: `
<form>
<re-captcha
[(ngModel)]="formModel.captcha"
name="captcha"
required
siteKey="YOUR_SITE_KEY"
></re-captcha>
</form>`,
}) export class MyForm {
formModel = new MyFormModel();
}
A similar approach can be taken for reactive forms:
@Component({
selector: 'my-reactive-form',
template: `
<form [formGroup]="reactiveForm">
<re-captcha formControlName="recaptchaReactive"></re-captcha>
<button [disabled]="reactiveForm.invalid">Submit</button>
</form>
`,
}) export class MyReactiveForm {
reactiveForm: FormGroup;
ngOnInit() {
this.reactiveForm = new FormGroup({
recaptchaReactive: new FormControl(null, Validators.required)
});
}
}
Working with invisible reCAPTCHA is almost the same as with regular one. First, you need to provide the right size:
<re-captcha size="invisible" ...></re-captcha>
You will also need to invoke the "execute()"
method manually. This can be done by either obtaining a reference to RecaptchaComponent
via @ViewChild()
, or by using inline template reference:
<re-captcha #captchaRef="reCaptcha" ...></re-captcha>
...
<button (click)="captchaRef.execute()">Submit</button>
Normally you would only submit a form when recaptcha response has been received. This can be achieved by reacting to (resolved)
event and invoking submit logic when the captcha response is truthy (this will not try to submit the form when recaptcha response has expired). A sample implementation would look like this:
@Component({
selector: 'my-form',
template: `
<form>
<re-captcha
#captchaRef="reCaptcha"
siteKey="YOUR_SITE_KEY"
size="invisible"
(resolved)="$event && submit($event)"
></re-captcha>
<button (click)="captchaRef.execute()">Submit</button>
</form>`,
}) export class MyForm {
public submit(captchaResponse: string): void {
this.http.post({
captcha: captchaResponse,
/* ... */
});
}
}
Making reCAPTCHA responsive is sometimes necessary, especially when working with mobile devices. You can use css-transforms to achieve that as in this StackOverflow answer, which is also ell-described in this blog post. You can also take a look at a live example of how this might be implemented. This boils down to
<div style="transform:scale(0.7);transform-origin:0;">
<re-captcha></re-captcha>
</div>
To configure the package to work with SystemJS, you would configure it approximately like that (assuming you've installed ng-recaptcha
using npm
):
// SystemJS config file
(function () {
System.config({
paths: {
'npm:': '/node_modules/',
},
map: {
'ng-recaptcha': 'npm:ng-recaptcha',
},
packages: {
'ng-recaptcha': { main: './index.js' },
},
});
})();
Since "google.com"
domain might be unavailable in some countries, reCAPTCHA core team has a solution for that - using "recaptcha.net"
domain. You can configure the component to use that by providing the RECAPTCHA_BASE_URL
token, for example:
import { RECAPTCHA_BASE_URL } from 'ng-recaptcha';
@NgModule({
providers: [
{
provide: RECAPTCHA_BASE_URL,
useValue: 'https://recaptcha.net/recaptcha/api.js', // use recaptcha.net script source for some of our users
},
],
}) export class MyModule { }
Per reCAPTCHA FAQ on CSP, the recommended approach for that is to supply nonce to the script tag. This is possible by providing the RECAPTCHA_NONCE
token, for example:
import { RECAPTCHA_NONCE } from 'ng-recaptcha';
@NgModule({
providers: [
{
provide: RECAPTCHA_NONCE,
useValue: '<YOUR_NONCE_VALUE>',
},
],
}) export class MyModule { }
More often than not you will need to only get a reCAPTCHA token with the action the user is currently taking, and submit it to the backend at that time. However, having a single listener for all events will be desirable.
There is an Observable
exactly for that purpose: ReCaptchaV3Service.onExecute
. It emits a value every time a token is received from reCAPTCHA. The shape of payload it operates on is defined via OnExecuteData
interface:
interface OnExecuteData {
action: string;
token: string;
}
where action
is the name of the action that has been executed, and token
is what reCAPTCHA v3 provided when executing that action.
Here's how you would potentially set this up:
import { OnExecuteData, ReCaptchaV3Service } from 'ng-recaptcha';
@Component({
selector: 'my-component',
templateUrl: './v3-demo.component.html',
})
export class MyComponent implements OnInit, OnDestroy {
private subscription: Subscription;
constructor(
private recaptchaV3Service: ReCaptchaV3Service,
) {
}
public ngOnInit() {
this.subscription = this.recaptchaV3Service.onExecute
.subscribe((data: OnExecuteData) => {
this.handleRecaptchaExecute(data.action, data.token);
});
}
public ngOnDestroy() {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
}
There are a couple things to keep in mind:
onExecute
will trigger for all actions. If you only need to bulk-process some actions, and not others - you will have to apply filtering yourself.onExecute
observable will provide you with all the events emitted after you have subscribed to it - it doesn't keep references to the previously emitted actions. So make sure you add such a subscription as early in your code as you feel is necessary.FAQs
Angular component for Google reCAPTCHA
The npm package ng-recaptcha receives a total of 116,306 weekly downloads. As such, ng-recaptcha popularity was classified as popular.
We found that ng-recaptcha demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.