Reputation: 166
I am developing a small application which uses single sign on service for the login procedure but when I run the app.js script, I get the following error:
var ssoConfig = services.SingleSignOn[0];
^
TypeError: Cannot read property '0' of undefined
and I am really don't know what is wrong because the JSON which is created automatically by IBM Bluemix and which maintains the env variables seems correct. The entire JSON file is:
{
"VCAP_SERVICES": {
"SingleSignOn": [
{
"credentials": {
"authorizationEndpointUrl": "...",
"clientId": "...",
"issuerIdentifier": "...",
"secret": "...",
"serverSupportedScope": [
"openid"
],
"tokenEndpointUrl": "https://sso-ahttzn6qt8-co15.iam.ibmcloud.com/idaas/oidc/endpoint/default/token"
},
"label": "SingleSignOn",
"name": "sso",
"plan": "standard",
"tags": [
"security",
"ibm_created",
"ibm_dedicated_public"
]
}
],
"cloudantNoSQLDB": [
{
"credentials": {
"host": "...",
"password": "...",
"port": ...,
"url": "...",
"username": "..."
},
"label": "cloudantNoSQLDB",
"name": "Cloudant NoSQL DB-vj",
"plan": "Shared",
"tags": [
"data_management",
"ibm_created",
"ibm_dedicated_public"
]
}
],
"iotf-service": [
{
"credentials": {
"apiKey": "...",
"apiToken": "...",
"base_uri": "...",
"iotCredentialsIdentifier": "...",
"mqtt_host": "...",
"mqtt_s_port": ...,
"mqtt_u_port": ...,
"org": "..."
},
"label": "iotf-service",
"name": "Internet of Things Foundation-gp",
"plan": "iotf-service-free",
"tags": [
"internet_of_things",
"Internet of Things",
"ibm_created",
"ibm_dedicated_public"
]
}
]
}
}
{
"VCAP_APPLICATION": {
"application_id": "486b73db-6a73-4536-8de2-0d8f517761b0",
"application_name": "buyonthefly-group4",
"application_uris": [
"buyonthefly-group4.mybluemix.net"
],
"application_version": "05eaa8ee-81d8-42bd-a340-a618bbcdf342",
"limits": {
"disk": 1024,
"fds": 16384,
"mem": 256
},
"name": "buyonthefly-group4",
"space_id": "a719f5fe-7835-490a-b646-928e601a5341",
"space_name": "Exercises",
"uris": [
"buyonthefly-group4.mybluemix.net"
],
"users": null,
"version": "05eaa8ee-81d8-42bd-a340-a618bbcdf342"
}
}
So services contains SingleSignOn, cloudandtNoSQLDB and iotf-service.
This is the app.js script:
var express = require('express');
var passport = require('passport');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var cfenv = require('cfenv');
var OpenIDConnectStrategy = require('passport-idaas-openidconnect').IDaaSOIDCStrategy;
var app = express();
app.use(cookieParser());
app.use(session({ secret: 'keyboard cat', resave: false, saveUninitialized: true }));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
var services = JSON.parse(process.env.VCAP_SERVICES || "{}");
var ssoConfig = services.SingleSignOn[0];
var client_id = ssoConfig.credentials.clientId;
var client_secret = ssoConfig.credentials.secret;
var authorization_url = ssoConfig.credentials.authorizationEndpointUrl;
var token_url = ssoConfig.credentials.tokenEndpointUrl;
var issuer_id = ssoConfig.credentials.issuerIdentifier;
var callback_url = 'http://buyonthefly-group4.mybluemix.net/auth/SSOLogin';
var OpenIDConnectStrategy = require('passport-idaas-openidconnect').IDaaSOIDCStrategy;
var Strategy = new OpenIDConnectStrategy({
authorizationURL : authorization_url,
tokenURL : token_url,
clientID : client_id,
scope: 'openid',
response_type: 'code',
clientSecret : client_secret,
callbackURL : callback_url,
skipUserProfile: true,
issuer: issuer_id
}, function(accessToken, refreshToken, profile, done) {
process.nextTick(function() {
profile.accessToken = accessToken;
profile.refreshToken = refreshToken;
done(null, profile);
});
});
passport.use(Strategy);
app.get('/login', passport.authenticate('openidconnect', {}));
function ensureAuthenticated(req, res, next) {
if(!req.isAuthenticated()) {
req.session.originalUrl = req.originalUrl;
res.redirect('/login');
} else {
return next();
}
}
app.get('/auth/sso/callback', function(req, res, next) {
var redirect_url = req.session.originalUrl;
passport.authenticate('openidconnect', {
successRedirect: '/hello',
failureRedirect: '/failure',
})(req,res,next);
});
app.get('/hello', ensureAuthenticated, function(request, response) {
request.send('Hello, '+ request.user['id'] + '!\n' + '<a href="/logout">Log Out</a>');
});
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
app.get('/failure', function(req, res) {
res.send('Login failed');
});
app.get('/', function (req, res) {
res.send('<h1>Bluemix Service: Single Sign On</h1>' + '<p>Sign In with a Social Identity Source (SIS): Cloud directory, Facebook, Google+ or LinkedIn.</p>' + '<a href="/auth/sso/callback">Sign In with a SIS</a>');
});
var appport = process.env.VCAP_APP_PORT || 8888;
var host = (process.env.VCAP_APP_HOST || 'localhost');
var server = app.listen(appport, function () {
var host = server.address().address
var port = server.address().port
console.log('Example app listening at http://%s:%s', host, port);
});
Anyone could help me to find out where I am doing wrong and how to fix it?
Thank you in advance.
Upvotes: 0
Views: 520
Reputation: 3233
This error occurs when you try to run the application on an environment which doesn't contain the VCAP_SERVICES environment variable (e.g. your machine). Since you are not running in Bluemix the following instruction:
var services = JSON.parse(process.env.VCAP_SERVICES || "{}");
Will result in the services variable being an empty object. For this reason services.SingleSignOn is undefined and you get the Cannot read property '0' of undefined
error.
Be sure that you are running your application on Bluemix.
Upvotes: 1