Why can I not access 'passport' fields in session store JSON? - json

I've got a node application that uses express, socket.io 1.0 and passport. When a user auths through passport-twitter I store their information in a session store using the below code;
var passportSocketIo = require("passport.socketio");
var MemoryStore = express.session.MemoryStore
,sessionStore = new MemoryStore();
io.set('authorization', passportSocketIo.authorize({
cookieParser: express.cookieParser,
key: 'express.sid',
secret: 'secret',
store: sessionStore
}));
I then use the following for my socket.io connection handler;
io.on("connection", function(client){
console.log(sessionStore.sessions[client.request.sessionID]);
});
This returns all the session data for the client with that ID in this format;
{
"cookie": {
"originalMaxAge": null,
"expires": null,
"httpOnly": true,
"path": "/"
},
"passport": {
"user": {
"id": "XXXXXXXXXX",
[...],
[...]
}
}
}
The issue is that if I tried to access "passport" from the structure, the result is always undefined. I tried the following (both with and without the . before "passport");
sessionStore.sessions[client.request.sessionID].[passport]
sessionStore.sessions[client.request.sessionID].["passport"]
sessionStore.sessions[client.request.sessionID].passport
sessionStore.sessions[client.request.sessionID]."passport"
Unfortunately these return as undefined. I'm really just trying to get the passport.user.id field value out of that structure so I can perform some DB lookup (e.g. user group, user privacy settings, etc) and so I can ensure I emit the correct DB data back to the client.
Any ideas?

After looking into it further, it appears that passing it through JSON.parse() was the correct method to use;
var jsobj = JSON.parse(sessionStore.sessions[client.request.sessionID]);
console.log(jsobj.passport.user.id);
or for a single line solution;
console.log(JSON.parse(sessionStore.sessions[client.request.sessionID]).passport.user.id);

Related

How to link JWT to my users info database

I have created a web app and use Auth0 for authentication. Each user has his own page with personal data.
How can I connect an user logged via Auth0 to my Mysql database in order to retrieve and update his specific data?
The tokens returned from Auth0 contain encoded data. When you decode it you can see for example something like this.
{
"iss": "http://YOUR_DOMAIN/",
"sub": "auth0|123456",
"aud": "YOUR_CLIENT_ID",
"exp": 1311281970,
"iat": 1311280970,
"name": "Jane Doe",
"given_name": "Jane",
"family_name": "Doe",
"gender": "female",
"birthdate": "0000-10-31",
"email": "janedoe#example.com",
"picture": "http://example.com/janedoe/me.jpg"
}
This is the payload of an ID token which I copied from this page. You can connect the Auth0 user and the user data in your database by using a common unique ID. Here you could use sub for example. You can also use the access token. It contains the same sub but some of the other data is missing.
Create an authToken state in your user reducer & upon sign in set this authToken state equal to received auth0 token. Then for each subsequent request for data retrieval pass this authToken value to validate your request.
reducer.js
const INITIAL_STATE = {
...
authToken = '';
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
...
...
case 'SET_AUTH_TOKEN':
return ({
...state,
authToken: action.payload
})
}
};
To persist this authToken for a session you can use redux-persist library which uses localStorage & sessionStorage to preserve redux state upon reload.

How to add array values in Claims of IdToken in Cognito using claimsToAddOrOverride

I am using Pre Token Generation to update the claims of IdToken.
I am successfully able to update claim using single key:value pair.
Below is the sample example of that.
event["response"] = {"claimsOverrideDetails":{"claimsToAddOrOverride":{"scope": "test.debug"}}}
But when i am trying to add array of string inside that, it giving me internal server error (Response from AWS Cognito)
Ex:
event["response"] = {"claimsOverrideDetails":{"claimsToAddOrOverride":{"scope": ["test1","test2]}}}
It is working fine using 'Test' option of lambda function.
If i am using groupsToOverride then it is overriding the cognito:groups claim.
Any help?
I think this must be a bug with Cognito and unfortunately will require a workaround until it's resolved.
It's not ideal I know, but I've worked around this issue by using a delimited string which I then parse to an array when I receive the token.
Lambda:
exports.handler = (event, context, callback) => {
event.response = {
"claimsOverrideDetails": {
"claimsToAddOrOverride": {
"scope": "test1|test2"
}
}
};
// Return to Amazon Cognito
callback(null, event);
};
Client:
const token = jwt.decode(id_token);
const scopes = token.scope.split('|');
The name scope have special meaning in a JWT, libraries expect this to be a list in string form separated by space. So the scopes test1 and test2 would become "test1 test2".
I would recommend using space as separator and not any other format. If you prefer another format just give your field a different name - like group.
{
"iss": "https://authorization-server.example.com/",
"sub": " 5ba552d67",
"aud": "https://rs.example.com/",
"exp": 1544645174,
"client_id": "s6BhdRkqt3_",
"scope": "openid profile reademail"
}

What's the best way to map objects into ember model from REST Web API?

The topic of this post is: my solution is too slow for a large query return.
I have a Web Api serving REST results like below from a call to localhost:9090/api/invetories?id=1:
[
{
"inventory_id": "1",
"film_id": "1",
"store_id": "1",
"last_update": "2/15/2006 5:09:17 AM"
},
{
"inventory_id": "2",
"film_id": "1",
"store_id": "1",
"last_update": "2/15/2006 5:09:17 AM"
}
]
Since my WebAPI did not provide a root key for my JSON response, I made a RESTSerializer like following.
export default DS.RESTSerializer.extend({
extract:function(store,primaryType,payload,id,requestType){
var typeName = primaryType.typeKey;
var data = {};
data[typeName] = payload; // creating root
payload = data;
return this._super(store,primaryType,payload,id,requestType)
}
});
When this gets run, I get the following error message: Assetion failed: You must include an 'id' for inventory in an object passed to 'push'
As you can see, these objects do not have the attribute id, so I found that the default behaviour of Ember RESTSerializer forces me to write my own.
Okay, so here's where I'm not sure my solution is right. inventory_id from my return is unique, therefore I choose to use that as an id, okay I'm thinking to my self, I'll just add it manually. The function looks like this now:
export default DS.RESTSerializer.extend({
extract:function(store,primaryType,payload,id,requestType){
var typeName = primaryType.typeKey;
for(var i=0;i<payload.length;i++){
payload[i].id = payload[i].inventoryId;
}
var data = {};
data[typeName] = payload; // creating root
payload = data;
return this._super(store,primaryType,payload,id,requestType)
}
});
By just manually duplicating an attribute, I feel like I'm cheating my way over this error message. In addition, I sometimes return a large payload array (over 150k rows). Looping O(n) just doesn't seem a right price to pay for just a simple mapping.
Is there some other way to set either my WebAPI or serializer up so I avoid the for loop in assigning the id that ember so desperately wants.
I think this should fix your problem:
export default DS.RESTSerializer.extend({
primaryKey: 'inventory_id'
});
With this parameter Ember Data will map inventory_id to it's id parameter.

Can I store a node process variable in JSON?

I am currently in the process of migrating an Express app to Heroku.
To keep sensitive information out of source, Heroku uses config vars which are assigned by to process variables of the same name.
Currently, I am loading my keys using .json, such as:
{
"key": "thisismykey",
"secret": "thisismysecret"
}
However, if I try to load the variables in via Heroku's format:
{
"key": process.env.KEY
"secret": process.env.SECRET
}
Obviously, I get an error here. I would assume that it is possible to load these values into JSON, but I'm not sure. How could I do this?
To generate JSON with these values, you would first create a JavaScript object and then use JSON.stringify to turn it into JSON:
var obj = { "key": process.env.KEY
"secret": process.env.SECRET };
var json = JSON.stringify(obj);
// => '{"key":"ABCDEFGH...","secret":"MNOPQRST..."}'

Sending complex JSON with fetch, save, and delete on a model or collection

We have an internal API that was specifically built to be used with a new piece of software I'm building that runs on Backbone. The API has a single URL and takes JSON as input to determine what it needs to return. It essentially allows me to build custom queries with JSON that return exactly what I'm looking for.
Thing is this JSON can get pretty verbose and is often 3–4 levels deep, but sometimes may just be a few lines and just 1 level deep.
First question first: How do I send a string of JSON along with the ID when I do a fetch()? Do I have to set these parameters as the model or collection's defaults?
Here is an example of a really simple string to get a specific user's info
{
"which" : "object",
"object" : {
"type" : "customer",
"place" : "store",
"customerID" : "14"
}
}
As others have suggested it will likely be challenging to work with SOAP, but it shouldn't be impossible. Backbone models and collections communicate with the server through the sync operation; you should be able to customize that. I think something along these lines might get the ball rolling (for models):
Backbone.SoapyModel = Backbone.Model.extend({
sync: function(method, model, options) {
// force POST for all SOAP calls
method = 'create';
options = _.extend(options, {
// Setting the data property will send the model's state
// to the server. Add whatever complexity is needed here:
data: JSON.stringify({
"which" : "object",
"object" : model.toJSON()
}),
// Set the request's content type
contentType: 'application/json'
});
// Defer the rest to Backbone
return Backbone.sync.apply(this, [method, model, options]);
}
});
var SoapyModelImpl = Backbone.SoapyModel.extend({
url: '/test'
});
var soapTest = new SoapyModelImpl({
id: 42,
name: 'bob',
address: '12345 W Street Dr',
phone: '867 5304'
});
soapTest.fetch();