pdupavillon / express-recaptcha Goto Github PK
View Code? Open in Web Editor NEWImplementation of google recaptcha v2 & V3 solutions for express.js
License: MIT License
Implementation of google recaptcha v2 & V3 solutions for express.js
License: MIT License
Line 65 in f18f544
My content security policy was flagging a request over http instead of https. Seems to be the above line causing the issue. I manually replaced it with the below (prepending 'https:') and seems to be ok now.
return '<script src="https://'+this._api.host+this._api.script+query_string+'" async defer></script>'+
Hey, I want to implement the example files with the Ejs.
As we all know that the lots of the nodeJs users use Ejs as their templating engine.
Kindly allow me to do that so that the Ejs users can refer it for their implementation in projects.
<html>
<head>
<title> Express-Recaptcha example</title>
</head>
<body>
<h1>
Express-Recaptcha example
</h1>
<% if(captcha) {%>
<form action="<%=path%>" method="POST">
<%- captcha%>
<button type='submit'>Verify captcha</button>
<br>
</form>
<% if (path === '/v3') {%>
<a href="/">Express Recaptcha V2</a>
<%}else{%>
<% if (path === '/dark') {%>
<a href="/">Light Theme</a>
<br>
<a href="/v3">Express Recaptcha V3</a>
<% }else{%>
<a href="/dark"> Dark Theme</a>
<br>
<a href="/v3">Express Recaptcha V3</a>
<%}%>
<% } } else {%>
<% if (error){%>
<div style="color:red">Error : <%=error%></div>
<% }else{ %>
<div style="color:green">Data : <%=data%></div>
<a href="<%= path%>">Retry</a>
<% }%>
<%}%>
<script>
function cb(token) {
console.log('token', token);
var input = document.createElement('input');
input.setAttribute('type', 'text');
input.setAttribute('name', 'g-recaptcha-response');
input.setAttribute('value', token);
document.getElementsByTagName('form')[0].appendChild(input);
}
</script>
</body>
</html>
I will be waiting for your respective reply.
Is there support for adding a g-recaptcha-response to the request header?
v*.ts
if(req.headers && req.headers['g-recaptcha-response']) response = req.headers['g-recaptcha-response'];
First of all, thank you a lot for this package!
Now, I was trying to use it and at first, didn't get it to run
https://stackoverflow.com/a/12008719
This is the solution that worked for me. There's differences between express 2, 3 and 4, especially regarding how POST params are parsed. Well, works now. :)
I get following in my log:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:470:11)
at ServerResponse.header (/mycode/node_modules/express/lib/response.js:771:10)
at ServerResponse.send (/mycode/node_modules/express/lib/response.js:170:12)
at done (/mycode/node_modules/express/lib/response.js:1008:10)
at Object.exports.renderFile (/mycode/node_modules/pug/lib/index.js:421:12)
at View.exports.__express [as engine] (/mycode/node_modules/pug/lib/index.js:464:11)
at View.render (/mycode/node_modules/express/lib/view.js:135:8)
at tryRender (/mycode/node_modules/express/lib/application.js:640:10)
at Function.render (/mycode/node_modules/express/lib/application.js:592:3)
at ServerResponse.render (/mycode/node_modules/express/lib/response.js:1012:7)
at app.get (/mycode/routes/index.js:9:7)
at Layer.handle [as handle_request] (/mycode/node_modules/express/lib/router/layer.js:95:5)
at next (/mycode/node_modules/express/lib/router/route.js:137:13)
at render (/mycode/node_modules/express-recaptcha/dist/v3.js:32:21)
at Layer.handle [as handle_request] (/mycode/node_modules/express/lib/router/layer.js:95:5)
at next (/mycode/node_modules/express/lib/router/route.js:137:13)
And the code at:
at app.get (/mycode/routes/index.js:9:7)
is as follow:
/* GET home page. */
app.get('/', recaptcha.middleware.render, (req, res, next) => {
res.render('index', {
title: 'My Title',
lastPath: '/',
captcha: res.recaptcha
})
})
Do you have an implementation showcasing an invisible captcha?
I used your project recently and created typings:
declare module 'express-recaptcha' {
import { Handler, Request } from 'express';
namespace e {
type CaptchaError = 'missing-input-secret' | 'invalid-input-secret' | 'missing-input-response' | 'invalid-input-response';
interface InitOptions {
/**
* The callback function that gets called when all the dependencies have loaded.
*/
onload?(): void;
/**
* Value could be explicit OR onload, Whether to render the widget explicitly.
*/
render?: 'explicit' | 'onload';
/**
* Forces the widget to render in a specific language (Auto-detects if unspecified).
*/
hl?: string
/**
* Value could be dark OR light.
* The color theme of the widget (default light).
*/
theme?: 'dark' | 'light';
/**
* Value could be audio OR image,
* The type of CAPTCHA to serve.
*/
type?: 'audio' | 'image';
/**
* Your callback function that's executed when the user submits a successful CAPTCHA response.
*/
callback?: () => void;
/**
* Your callback function that's executed when the recaptcha response expires
* and the user needs to solve a new CAPTCHA.
*/
expired_callback?: () => void
/**
* The size of the widget.
*/
size?: number | 'invisible';
/**
* The tabindex of the widget and challenge.
* If other elements in your page use tabindex, it should be set to make user navigation easier.
*/
tabindex?: number;
/**
* Adding support of remoteip verification (based on x-forwarded-for header or remoteAddress.Value could be true OR false (default false).
* more info on : https://developers.google.com/recaptcha/docs/verify
*/
checkremoteip?: boolean;
}
}
// Technically a class but this wouldn't work right...
const e: {
public readonly middleware: {
verify: Handler;
render: Handler;
}
public init(siteKey: string, privateKey: string): void;
public render(): string;
public verify(req: Request, cb: (error: CaptchaError, data?: { hostname: string}) => void): void;
};
export = e;
declare global {
namespace Express {
export interface Request {
/**
* Will be string when the `render` middleware is used.
* Will be `{ error: ...}` when the `verify` middleware is used.
*/
recaptcha?: string | {
error: 'missing-input-secret' | 'invalid-input-secret' | 'missing-input-response' | 'invalid-input-response';
}
}
}
}
}
You might want to change your exports tho, exporting an instance of a class as module.exports
is very hard to model in TS.
Ideally you'd export exports.Recaptcha = Recaptcha
.
I'd also suggest changing req.recaptcha
to be { template: string; error: string }
.
Or you just move the entire thing to TS, all of these changes are breaking anyways.
I use this great lib with multiple language, but this need always create new instance by constructor. I think good idea on render accept some parameters - as options. This mean only one instance need, but by requests other and other language served.
When attempting to render the recaptcha, I would get an vague error only saying that "callback is required", but as far as I can tell I am doing just that. I copied the code in the example and did not change much else. What am I missing?
Here is the full error in question:
Error: callback is required
at RecaptchaV3.renderWith (/home/sawyer/Documents/code/WebstormProjects/nyx website/node_modules/express-recaptcha/dist/v3.js:65:19)
at RecaptchaV3.render (/home/sawyer/Documents/code/WebstormProjects/nyx website/node_modules/express-recaptcha/dist/v3.js:54:21)
at render (/home/sawyer/Documents/code/WebstormProjects/nyx website/node_modules/express-recaptcha/dist/v3.js:32:43)
at Layer.handle [as handle_request] (/home/sawyer/Documents/code/WebstormProjects/nyx website/node_modules/express/lib/router/layer.js:95:5)
at next (/home/sawyer/Documents/code/WebstormProjects/nyx website/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/home/sawyer/Documents/code/WebstormProjects/nyx website/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/home/sawyer/Documents/code/WebstormProjects/nyx website/node_modules/express/lib/router/layer.js:95:5)
at /home/sawyer/Documents/code/WebstormProjects/nyx website/node_modules/express/lib/router/index.js:281:22
at Function.process_params (/home/sawyer/Documents/code/WebstormProjects/nyx website/node_modules/express/lib/router/index.js:335:12)
at next (/home/sawyer/Documents/code/WebstormProjects/nyx website/node_modules/express/lib/router/index.js:275:10)
Hey @pdupavillon, I have a question about the verify process.
I am using this lib to perform validation on the server, and I see that the captcha is failing sometimes with the error: invalid-input-response
I am using the invisible captcha.
I don't understand how can I reproduce this error.
When I try to fail the challenge on purpose for over than 5 minutes, I don't see any error, just keep on getting a fresh new challenge.
So do you have any idea what can trigger that error?
Another question - When the challenge popup is visible, when you click outside of it the popup is closing. Is there any event for that? Something like onClose or something?
Thanks..
insert after line 39:
if (this.options.size) captcha_attr += ' data-size="'+this.options.size+'"';
For funkcionality is needed body-parser npm package. Because there are handled post requests.
I dont know why that information missing in readme. And on the other hand why is there present settings for public directory that is unrelated with such captcha feature.
It would be helpfull especialy for node noobies add such information. But I understand that everyone love keeping their modules without any additional dependency. And who knows maybe body-parser is de facto standard in node world. But anyway posted so maybe someone find help here.
Not sure but i have two apps running on two separate servers, using express-recaptcha - it all worked well for past two month, and for some reason yesterday both apps on separate server crashed with this error.
Error: getaddrinfo ENOTFOUND www.google.com www.google.com:443
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:67:26)
Emitted 'error' event at:
at TLSSocket.socketErrorListener (_http_client.js:395:9)
at TLSSocket.emit (events.js:180:13)
at emitErrorNT (internal/streams/destroy.js:64:8)
at process._tickCallback (internal/process/next_tick.js:178:19)
And today it all went back to normal, I have changed nothing in my code! I wonder if there is a chance that google servers were down / had issues accepting requests and your code doesn't handle this kind of failure, and if not the case, how can I handle this kind of response so the app doesn't crash?
Just as a note! I have used your example to make it work, hence its been working fine for the past two months.
many thanks in advance for your hard work in bringing express-recaptcha to us.
Hi,
I start to implement your example but I am facing the following issue:
express-recaptcha\dist\v3.js:45
next();
^
TypeError: next is not a function
NodeJS: v10.20.1
NPM: 6.14.8
OS: Windows 10
Thanks in advance
I've tried multiple attempts at implementing this package and every time I do I get the same error message.
I imported the package and configured with my two keys from google which caused the error, didn't try implementing it on any routes or views.
I also downloaded the sample code and tried to run that only to receive the same error.
Hi,
This error caused the application to crash.
Dealing with "try catch" I believe it will solve.. :) thanks!
start-app.sh: at IncomingMessage. (/opt/app-root/src/node_modules/express-recaptcha/lib/express-recaptcha.js:86:25)
start-app.sh: at JSON.parse ()
start-app.sh: SyntaxError: Unexpected token < in JSON at position 0
start-app.sh: ^
start-app.sh:
start-app.sh: undefined:1
Getting this error:
node_modules/express-recaptcha/typings/express.d.ts:1:33 - error TS2307: Cannot find module '../src/interfaces'. 1 import {RecaptchaResponse} from '../src/interfaces';
I manually adjust it for now from:
import {RecaptchaResponse} from '../src/interfaces';
to
import {RecaptchaResponse} from '../dist/interfaces';
but every time my node_modules change, it reverts back to its original value.
Is this something on my side? If not, could you guys please update this?
I recently update express-recaptcha to last version and update my code but my problem is in frontend just a frame shows that the page is recaptcha protected, and the recaptcha is not showing in div tag?
what is the solution?
I didn't receive any error
showRegsitrationForm(req , res) { res.render('register' , { messages : req.flash('errors') , recaptcha : this.recaptcha.render() }); }
`recaptchaConfig(){
this.recaptcha = new Recaptcha(
'!!!',
'!!!' ,
{callback:'cb'},{'hl' : 'en'}
);
}
`
This may not be an issue with express-recaptcha itself, but this is driving me crazy, I've made some research on stackoverflow and Google but I couldn't find any solutions on how to do this. What I'm trying to do is:
userController.js
app.get('/user/login', recaptcha.middleware.render,this.login);
login: function (req, res) {
if (req.user) {
res.redirect('/admin');
} else {
res.render('user/login', {title: 'Login', catpcha: res.recaptcha});
}
}
registerController.js
app.get('/register', recaptcha.middleware.render, this.register)
register: function(req, res) {
res.render('index', {title: 'Home', captcha: res.recaptcha})
}
But recaptcha is only rendered on the first route, not the second.
This is a reduced version of my package.json:
"express": "^4.13.4",
"express-recaptcha": "^4.0.2"
I've included the packages I thought were needed.
NOTE: I've excluded Recaptcha constructor on purpose
I have 'g-recaptcha-response': [ '', '03AOLTBLTmXVEzta....]
temporarily solved the problem by replacing
var query_string = 'secret=' + this._secret_key + '&response=' + response;
on
var query_string = 'secret=' + this._secret_key + '&response=' + response[1];
I see that v3 is already implemented. Any plans on submitting it to npm?
var recaptcha = new Recaptcha('SITE_KEY', 'SECRET_KEY', options);
I can't seem to pass any options ie {"theme" : "dark"} or theme="dark"?
Google lets you provide the end user's ip address as an optional security measure. Could this feature be added?
Perhaps with an option to use x-forwarded-for headers?
https://developers.google.com/recaptcha/docs/verify
Error thrown from middleware invalid-input-response
when form submitting with multipart/form-data
I think currently this library only support google recaptcha v2,
There are plans to support recaptcha v3 in the future?
if not, could I make a fork and integrate the changes miself by a pullrequest?
Thank you
Hi,
I don't know where is my mistake but I cannot execute verify from server side.
It seems that there is no way to set an HTTP Proxy
Must I use any module like tunnel?
Regards
Vito
Since hCaptcha is increasingly popular, it would be great to support this as well as reCaptcha - the two services can be interchanged easily: https://docs.hcaptcha.com/switch/
I don't believe this would be a huge change, mainly just offering a different set of endpoint URLs.
If there's appetite for this package to expand to support hCaptcha, then I can have a look into the work needed and create a PR.
Hi,
I am using your package and what I can see is that it injects the recaptcha code on the web page (which works wonderful), example:
...., {action: 'homepage'})
.then(recaptchaReady);
Except when an error might occur due to, for example, a timeout (slow connection). In this case, the Promise code above does not handle the exception and the browser gives an error like:
Uncaught (in promise) Timeout
Promise.then (async)
How would I handle exceptions in the Promise (auto-generated by your package)?
For example:
...., {action: 'homepage'})
.then(recaptchaReady)
.catch((err) => {
// Handle any error that occurred in any of the previous
// promises in the chain.
});
Recaptcha is not showing
It shows when I change the script src in index.js
from
<script src='//www.google.com/recaptcha/api.js'></script>
to
<script src='https://www.google.com/recaptcha/api.js'></script>
Am I missing something ?
Hi,
Our implementation seems to be functional without the app.use(bodyParser.json());
line (that we missed by error). Is it a real requirement for most implementations and we have an easy-lucky use case ?
Regards
var Recaptcha = require('express-recaptcha').Recaptcha;
var recaptcha = new Recaptcha('xxx', 'xxx');
This code works in 4.1.1, but throws an error on 4.2.0.
Version 4.2.0 requires adding the V2
.
var Recaptcha = require('express-recaptcha').RecaptchaV2;
This is a breaking change, so you should change the version number to 5.0.0 for this release. You should also release an update to 4.2.1 with this change reversed, to help people who depend on your package working as it usually did.
Please see the npm documentation page about semantic versioning for more information.
The documentation states
app.post('/', function(req, res){
recaptcha.verify(req, function(error, data){
if (!req.recaptcha.error) {
// success code
} else {
// error code
}
});
});
I believe it should be
app.post('/', function(req, res){
recaptcha.verify(req, function(error, data){
if (!rerror) {
// success code
} else {
// error code
}
});
});
Hi, first of all thank you for the wonderful library. I have a get login url, a post login url and the pug file that does the login. I followed instructions as mentioned. If I change my type to a normal recaptcha it works perfectly but an invisible one does not
Pug file
The router
const Recaptcha = require("express-recaptcha").RecaptchaV2;
const recaptcha = new Recaptcha(process.env.RECAPTCHA_SITE_KEY_V2, process.env.RECAPTCHA_SECRET_KEY_V2, { size: "invisible" });
router.get("/", homeController.index);
router.get("/login", recaptcha.middleware.render, userController.getLogin);
router.post("/login", recaptcha.middleware.verify, userController.postLogin);
A little debugging has led me to the point where
g-recaptcha-response is empty string
{ error: 'invalid-input-response', data: null }
Any suggestions are appreciated
Is there a way to use this module when there are multiple recaptcha on a single page? Right now, I am unable to figure out how to do it. But I am aware of a way to do it without using express-recaptcha. Thanks in advance.
The documentation is not very clear on the modification we have to setup in the view : the captcha
element and the callback function.
Might be useful to update the documentation with the PUG from example folder and the EJS from issue #31
Hi,
All is working fine, except when the Recaptcha session expires. Let's say you have a login page with recaptcha validation. Now, open the page and leave the form open for some time (so recaptcha session expires) - Not sure but I think more than 2 minutes. Then login. This gives a recaptcha validation error. How can one handle this type of behaviour? I am using v3
I'm using this library in an application, and recently had a hell of a time debugging because you guys changed the way the library works in a breaking fashion and incremented the minor version instead of the major version.
The commit that pulls #1 should have changed the version to 2.0.0 to prevent this.
Whether or not you fix this in the existing package is irrelevant, but in the future please make sure your npm packages follow semver.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.