keycloak-nodejs-connect: Could not obtain grant code: 400:Bad Request - node.js

Setup:
I am trying to get the demo code for keycloak-connect library to run, but failing.
Here's what I did:
Download and start keycloak 4.7 standalone, set admin user and pw
Create a basic public client
Create a user
Create a basic express app in webstorm
Relevant files:
index.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var session = require('express-session');
var Keycloak = require('keycloak-connect');
var memoryStore = new session.MemoryStore();
let keycloak = new Keycloak({ store: memoryStore });
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
app.set('trust proxy', 1); // trust first proxy
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: true },
store: memoryStore
}));
app.use( keycloak.middleware() );
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.get('/$', function(req, res) {
res.write('Secure');
res.end();
});
app.get( '/secure', keycloak.protect('realm:master'), function(req, res){
//Edit: keycloak.protect() gives the same result
res.write("Yo!");
res.end();
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
keycloak.json (copy/paste)
{
"realm": "master",
"auth-server-url": "http://localhost:8080/auth",
"ssl-required": "external",
"resource": "test",
"public-client": true,
"confidential-port": 0
}
package.json
{
"name": "keycloak-test",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"cookie-parser": "~1.4.3",
"debug": "~2.6.9",
"express": "~4.16.0",
"express-session": "^1.15.6",
"http-errors": "~1.6.2",
"keycloak-connect": "^4.7.0",
"morgan": "~1.9.0",
"pug": "2.0.0-beta11"
}
}
Problem:
On accessing http://localhost:3000/secure, I am redirected to the keycloak login form, an can log in with the user credentials for the demo user.
I am then redirected back to /secure, and the website says Access denied with 403 forbidden response code.
The keycloak console says
16:44:56,691 WARN [org.keycloak.events] (default task-8)
type=CODE_TO_TOKEN_ERROR,
realmId=master,
clientId=test,
userId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,
ipAddress=127.0.0.1,
error=invalid_code,
grant_type=authorization_code,
code_id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,
client_auth_method=client-secret
The node.js console says Could not obtain grant code: 400:Bad Request.
What am I doing wrong?

you are securing your resource /secure with a realm role called master
app.get( '/secure', keycloak.protect('realm:master')
you need to create master role and assign to demouser as shown below

The problem with this is a problem with the npm keycloak-connect package, when you install using npm install must be getting a warning which says, run npm audit.
Run npm audit --force abd rerun the app it will work. I was stuck in the same problem for a day and this thing came as a life saver for me.
run npm audit --force after an npm install.
npm install
npm audit --force

Related

nodejs express-session middleware is not working in visual studio

I'm trying to use express-session in nodejs express but I can't set or get sessions. I get "Property 'session' does not exist on type 'Request'" when I'm trying to build.
I tried to change the order of the codes but nothing works
node version : v10.15.3
visual studio : 2017
my dependencies
"dependencies": {
"axios": "^0.19.0",
"body-parser": "^1.19.0",
"cookie-parser": "^1.4.4",
"debug": "^2.2.0",
"express": "^4.14.0",
"express-session": "^1.16.2",
"pug": "^2.0.0-rc.3",
"session-file-store": "^1.3.0"
},
"devDependencies": {
"#types/debug": "0.0.30",
"#types/express": "^4.0.37",
"#types/express-serve-static-core": "^4.0.50",
"#types/mime": "^1.3.1",
"#types/serve-static": "^1.7.32",
"#types/node": "^6.0.87"
}
app.ts
var app = express();
var bodyParser = require('body-parser');
var session = require('express-session');
var FileStore = require('session-file-store')(session);
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json()); // to support JSON-encoded bodies
app.use(express.json()); // to support JSON-encoded bodies
app.use(express.urlencoded({ extended: true })); // to support URL-encoded bodies
app.use(session({
name: 'test-session-cookie-id',
secret: 'test',
resave: true,
store: new FileStore(),
saveUninitialized: true,
cookie: { secure: true }
}));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use('/signup', signup);
app.use('/verify', verify);
app.use(function printSession(req, res, next) {
console.log('req.session', req.session); //error
return next();
});
update :
module seems to be working fine itself . it created a session folder with 500+ files which is odd
update2 :
the express session is working fine but the error is bugging me. I uninstalled vs2017 and installed vs2019 and updated the typescript but the problem is still there
there was no #types/express-session in my dependencies/devDependencies . npm install --save #types/express-session did the job . there is no error now

Deployment of Nodejs Code with Google Cloud

I am trying to deploy my webapp code built on NODE JS. I deployed a simple application hello-world from
https://github.com/GoogleCloudPlatform/nodejs-docs-samples/tree/master/appengine/hello-world
and it worked.
Attached is my project structure.
In the client folder i have angular4 where the build files will be stored in public
In the server folder i have defined routes.
This setup is working find on my local. No errors.
But when i deploy it on google cloud i am getting
Error: Server Error
The server encountered a temporary error and could not complete your request.
Please try again in 30 seconds.
and error log says
Error: No default engine was specified and no extension was provided.
at View (/app/server/node_modules/express/lib/view.js:61)
at EventEmitter.render (/app/server/node_modules/express/lib/application.js:570)
at ServerResponse.render (/app/server/node_modules/express/lib/response.js:1008)
at (/app/server/app.js:42)
at Layer.handle_error (/app/server/node_modules/express/lib/router/layer.js:71)
at trim_prefix (/app/server/node_modules/express/lib/router/index.js:315)
at (/app/server/node_modules/express/lib/router/index.js:284)
at Function.process_params (/app/server/node_modules/express/lib/router/index.js:335)
at next (/app/server/node_modules/express/lib/router/index.js:275)
at Layer.handle_error (/app/server/node_modules/express/lib/router/layer.js:67)
Can anyone guide me on why this error?
My root package.json file to run npm start is
{
"name": "test-application",
"description": "A simple application for testers who run",
"version": "0.0.1",
"private": true,
"license": "Apache-2.0",
"author": "Alaksandar Jesus Gene",
"repository": {
"type": "git",
"url": ""
},
"engines": {
"node": ">=4.3.2"
},
"scripts": {
"deploy": "gcloud app deploy",
"start": "node server/app.js"
},
"dependencies": {
},
"devDependencies": {
},
"cloud-repo-tools": {
"test": {
"app": {
"msg": "Hello, world!"
}
},
"requiresKeyFile": true,
"requiresProjectId": true
}
}
And my app.yaml file is
# [START app_yaml]
runtime: nodejs
env: flex
skip_files:
- ^client$
# [END app_yaml]
Point to note, both files were copied from google sample github project and added values.
Project Folder Structure - Expanded
Project Folder Structure - Collapsed
Can anyone guide me on why this error?
Fixed it. My mistake in app.js coding
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
const http = require('http');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var api = require('./routes/api');
var app = express();
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, '../public')));
app.use('/api', api);
app.get('*', (req, res) => { //i think the issue was here. I had app.use
res.sendFile(path.join(__dirname, '/index.html'));
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
const port = process.env.PORT || '3000';
app.set('port', port);
const server = http.createServer(app);
server.listen(port, () => console.log(`Running on localhost:${port}`));
module.exports = app;

Issues deploying NodeJS w/ MongoLab on Heroku

I'm having issues deploying my app on Heroku. I keep getting a screen in my browser saying Application Error. From what i've read this is something with MongoLab.
I have set my PROCESS.ENV.MONGOLAB_URI correctly on heroku and I can't get it to work. I have also tried adding a new user to MongoLAB for this DB and even that user won't work as well.
I am Process.env.PORT because I am using Socket.io. Is it something in my app.js?
var express = require('express');
var http = require('http')
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
mongoose.connect(process.env.MONGOLAB_URI || 'mongodb://localhost/queueThat');
var db = mongoose.connection;
var routes = require('./routes/index');
var app = express();
var server = http.createServer(app);
//Stuff for Sockets
var io = require('socket.io').listen(server);
//sockets
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');
app.engine('html', require('ejs').renderFile);
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
//Connect to the Socket
io.on('connection', function(socket){
socket.on('song send', function(song){
io.emit('song send', song)
console.log('artist on')
})
socket.on('artist send', function(artist){
console.log('artist on')
io.emit('artist send', artist)
})
//Disconnect
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
var port = (process.env.PORT || 8000);
server.listen(port, function() {
console.log("Listening on " + port);
});
module.exports = app;
I have also tried adding my node and NPM versions to no avail. Any ideas? Package.json looks like this.
{
"name": "queueThat",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"body-parser": "~1.13.2",
"cookie-parser": "~1.3.5",
"debug": "~2.2.0",
"ejs": "^2.3.4",
"express": "~4.13.1",
"mongoose": "*",
"morgan": "~1.6.1",
"serve-favicon": "~2.3.0",
"socket.io": "*"
},
"engines": {
"node": "5.4.0",
"npm": "3.3.12"
}
}
Application Error doesn't mean that there is something wrong with MongoLAB, not necessarily.
To be clear you need to double check few places:
You need to have proper Procfile in the root folder of your project
Be aware of postinstall npm script.
Also you could check your logs on heroku heroku logs -n 200 (200 or more lines if needed) to be sure what's the problem you have.

Auto reload with supervisor in express.js

My package.json
{
"name": "lays-vroubek",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "supervisor ./bin/www"
},
"dependencies": {
"body-parser": "~1.13.2",
"cookie-parser": "~1.3.5",
"debug": "~2.2.0",
"express": "~4.13.1",
"jade": "~1.11.0",
"less-middleware": "^2.0.1",
"morgan": "~1.6.1",
"reload": "^0.7.0",
"serve-favicon": "~2.3.0",
"supervisor": "^0.9.1"
}
}
My app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var lessMiddleware = require('less-middleware');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(lessMiddleware(path.join(__dirname, 'public'), {
force: true,
debug: true,
once: false
}));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
I run my app with comand: "$ DEBUG=lays-vroubek:* npm start" but auto-reload does not work without any error msg (app runs)
lays-vroubek#0.0.0 start /Users/jan.michalik/Workspace/Sites/lays-vroubek
supervisor ./bin/www
Running node-supervisor with
program './bin/www'
--watch '.'
--extensions 'node,js,/bin/www'
--exec 'node'
Starting child process with 'node ./bin/www'
Watching directory '/Users/jan.michalik/Workspace/Sites/lays-vroubek' for changes.
Press rs for restarting the process.
lays-vroubek:server Listening on port 3000 +0ms
Any help?
For example, you have an express app named backend. Than you can use
DEBUG=backend:* supervisor -w server -e ejs,js,json bin/www
to autorestart express app if any of ejs, js or json files is changed inside server dir (usual, i place my express app into server dir)

Session using NodeJS and Express 4.x (req.session undefined)

First of all sorry my bad English. I'm studying and I'm doing an academic project and came across a problem. I can not recall a session variable.
package.json
"dependencies": {
"body-parser": "^1.7.0",
"ejs": "~1.0.0",
"express": "^4.8.7",
"express-session": "^1.11.3",
"ini": "^1.3.4",
"mysql": "^2.8.0",
"winston": "^1.0.1"
}
server.js
var express = require('express');
var session = require('express-session');
var app = express();
...
require('./router/main')(app, language, connection, logger);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.engine('html', require('ejs').renderFile);
app.use(express.static(__dirname + '/public'));
app.use(session({
secret: 'pecuniamsekretsession',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));
main.js
module.exports = function(app, languageItems, connection, logger) {
app.post('/', require('../router/login.js')(languageItems, connection, logger));
app.get('/', require('../router/login.js')(languageItems, connection, logger));
}
login.js
module.exports = function (language, connection, logger) {
var routerTemplateLogin = function (req, res) {
var utils = require('../utils/utils');
var util = new utils.Util;
// It does not work :-(
logger.debug(req.session);
req.on('data', function(data) {
var arrayPost = util.postDataToArray(data);
});
res.render('pages/login.ejs', {
lang: language
});
}
return routerTemplateLogin;
}
In login.js see // It does not work :-(. Full project in https://github.com/braulioti/pecuniam
Thanks
The problem is that the routes are set up before any other middleware. Move this line:
require('./router/main')(app, language, connection, logger);
after this:
app.use(session({
secret: 'pecuniamsekretsession',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));
in your server.js.

Resources