How do you allow other users to access your Streamlabs API app? - node.js

The documentation isn't perfectly clear on this, I am able to hardcode in my token and get it to work as such
const socketToken = 'mytokenrandomlongstringofchars';
//Connect to socket
const streamlabs = io(`https://sockets.streamlabs.com?token=${socketToken}`, {
transports: ['websocket']
});
Then listen in for events as such
streamlabs.on("event", (eventData) => {
if (eventData.for === "streamlabs" && eventData.type == "donation") {
var donobj = eventData.message;
var dononame = donobj[0].from;
var donomessage = donobj[0].message;
document.getElementById("alert-message").innerHTML = dononame;
document.getElementById("alert-user-message").innerHTML = donomessage;
console.log(donobj);
}
});
The API uses oAuth 2 to allow users to connect and this is where I'm stuck and the snippets in the documentation aren't exactly helping, I'm supposed to send the user to an authorization link that looks something like this
streamlabs.com/api/v1.0/authorize?client_id=CLIENT-ID-HERE&redirect_uri=REDIRECT-URI&response_type=code&scope=SOME+SCOPES+HERE
as per this stack overflow answser, then once they accept the authorization they are redirected by to the redirect uri that I specified when registering the app alongside a code, that looks something like this
my.site/callback?code=randomstringofcharacters.
I'm supposed to send a POST request to https://streamlabs.com/api/v1.0/token with that code to get an access token, then use that access token to send a GET request to https://streamlabs.com/api/v1.0/socket/token so that I can finally get the web socket token that I could use to listen for events, where I have no clue where to procede is how to get the code from the redirected URL, if I'm understanding the process correctly then I should be able to manage the other steps, but how to I get the code in the first place?

I don't know if this is what you are asking for, but you can add authorized users on the streamlabs website, under the app settings. Let me know if I need to clarify.

Related

Can I access twitter auth data via firebase cloud functions Admin SDK? If so, how?

I'm currently using firebase for the backend of a project I'm working on. In this project, the client authenticates using the firebase-twitter sign in method. For the purpose of security, I'm trying to minimise the amount of communication between the client and backend when it comes to auth data. In jest of this, I'm wondering if there is a way to access the auth data i.e. the user's twitter key/secret (as well as things like the user's twitter handle) from the server-side after the user authenticates ? I figured there might be a way as the authentication happens through twitter + firebase, but I'm struggling to find the exact solution I need in the documentation (been stuck on this for a week now) so was hoping someone else already knows if this is possible and how :) cheers
Maybe not the best way, but you can try: on client side use RealTime database and add a new entry every time the user log in. They call this 'realtime triggers'.
You don't mention what front are you using, but on ionic is something like:
firebase.auth().onAuthStateChanged(function(user) {
if (user)
this.db.addLogin(user.uid)
});
On database class function:
addLogin(uid){
let path = "/logins/"
let ref = this.db.list(path)
let body = {uid: uid}
return ref.push(body)
}
On the server side, listen the path using child_added
var ref = db.ref("logins");
ref.on("child_added", function(snapshot, prevChildKey) {
var newPost = snapshot.val();
console.log("Uid: " + newPost.uid);
console.log("Previous Post ID: " + prevChildKey);
});
More information about triggers

How to preserve Socket.io sockets app-wide

I am trying to add socket.io functionality to my App.
I have never used socket.io before, so I have no idea how to progress from here.
I've used the MERN Stack until now, and the next step would be to implement socket.io for chat functionality. The problem is, I don't know when to connect, and how to preserve my sockets. The user can sign in, so I thought I could just connect after signing the user in, but then the socket is created in a component, and I can't access it from anywhere else.
The problem is, I use JWT tokens for authentication, so I have a function, that "signs the user in" when going to a new page, if the token hasn't expired yet.
if(localStorage.jwtToken){
const token = localStorage.jwtToken;
setAuthToken(token);
const user = jwt_decode(token);
store.dispatch(action_setCurrentUser(user));
store.dispatch(setGroupsOfUser({ id: user.id }));
const currentTime = Date.now() / 1000;
if(user.exp < currentTime){
store.dispatch(logoutUser());
window.location.href = './login';
}
}
I thought I could just connect in here, but then my ChatView component can't access it to send messages and stuff. I need a socket to send notifications, even if the user isn't in a chat room, and the ChatView component needs it to send messages.
Tried to connect after the login dispatch, and store the online users on the server, with their socketIDs.
If I try to search for a solution, every hit I get is about authentication using socket.io, but the authentication is already done for me so I'm not sure how to proceed.
As suggested, I decided to create the socket in my App.js and store it in my state.
I can use this stored state then in my subcomponents, and assign it on the server to a user after sign in.
You might want to look in redux. Since your having all the auth stuff and all . It might get messy handling app wide authentication .

How to catch Facebook messaging_optins with Azure Bot Channels Registration + Botbuilder SDK?

I've got a chatbot up and running, built using Node.JS Microsoft Bot Framework, and deployed to an Azure server as a Web App, with a Bot Channels Registration resource as the frontend endpoint.
This Bot Channels Registration is connected to Facebook Messenger (via a FB App) - meaning, the webhook for the Facebook App points to https://facebook.botframework.com/api/v1/bots/<BOT_CHANNELS_REGISTRATION_RESOURCE_NAME>.
This all works well for normal chat functionality.
However, I'd now like to add an opt-in checkbox to a separate web page I have. This checkbox works by pinging FB, which then sends a very specific payload to the already configured bot webhook.
{
"recipient":{
"id":"<PAGE_ID>"
},
"timestamp":<UNIX_TIMESTAMP>,
"optin":{
"ref":"<PASS_THROUGH_PARAM>",
"user_ref":"<UNIQUE_REF_PARAM>"
}
}
My question is this:
How does the Bot Channels Registration receive and handle the above payload? Will it just automatically forward it to the Messaging Endpoint I have configured in the Bot Channels Registration settings? Or will it get stuck, and never reach my actual bot Web App?
Finally, if it does reach my normal messages endpoint, how can I handle the specific payload with my botbuilder.ChatConnector() listener? Given that my web app code looks like (in essence)
var restify = require('restify');
var builder = require('botbuilder');
var dialogues = require('./dialogues');
var chatbot = function (config) {
var bot = {};
chatbot.listen = function () {
var stateStorage = new builder.MemoryBotStorage();
var connector = new builder.ChatConnector({
appId: process.env.APP_ID,
appPassword: process.env.APP_PASSWORD
});
bot = new builder.UniversalBot(connector, function (session) {
session.beginDialog(dialogues.base(bot).name);
}).set('storage', stateStorage);
return connector.listen();
};
return chatbot;
}
var server = restify.createServer();
// Listen for messages from users
server.post('/api/messages', chatbot.listen());
server.listen(process.env.port, function () {
console.log('%s listening to %s', server.name, server.url);
});
Thanks!
EDIT: I've figured out how to handle the above payload within my messaging endpoint - by adding a server.pre() handler to my server, e.g.
server.pre(function (req, res, next) {
if (req.body && req.body.optin_payload_specific_field){
// handle opt-in payload
} else {
return next();
}
});
However, via extra logging lines, it seems the opt-in payload isn't even making it to this endpoint. It seems to be stopped within the Bot Channels Registration. Currently looking for a way to resolve that major roadblock.
So, per #JJ_Wailes investigation, it seems like this is not a supported feature (in fact, it's a current feature request). See his comments on the original post for more details.
However, I did find a half-workaround to capture the user_ref identifier generated by the checkbox_plugin, for those interested:
1) From your external site, follow the steps from the documentation here for sending the initial user_ref to FB. FB will then make a callout to your bot, but per the above, that gets blocked by the Bot Channels Registration piece, so it's ignored.
2) From that same external site, use the user_ref to send a message to the user (just using the normal requests library). A successful send means that the user_ref was properly registered in FB by that step #1 call - a failure means you'll need to repeat step #1 (or use some other error handling flow).
3) After that, the next time the user responds to your bot in FB (as long as you don't send any other messages to them), the message your bot will receive will contain this as part of the payload:
{ ...
channelData:
{ ...
prior_message:
{ source: 'checkbox_plugin',
identifier: <user_ref> }
}
}
So I've currently added a check within my bot.use(), where if that section is present in the incoming message payload (session.message.sourceEvent.prior_message) and the source is "checkbox_plugin", I store the corresponding user_ref in the session.userData, and can work from there.
I would love to see this feature added into the supported Azure bot stack, but in the meantime hopefully this helps anyone else encountering this (admittedly niche) hurdle.

Generated Access Token invalid for Demo Video Application

I am using the sample Video application pulled from GitHub. I am using a node.js server to supply the sample application with the access token. When I use the Twilio Console to generate a video access token and put it in my Node.js server as a literal and return it I am able to run the example application and connect to a room. If I use the sample token generation code in my Node.js server I get 'Invalid Access Token' back in an exception in the onDisconnected method in the Room.Listener.
The following code is what is running in the server to create the access token, I also found a different sample which I tried as well. I have gone back and verified that my data values for the account SID and the API keys are correct. I have a similar method running returning the VoiceGrant access token and that is working, but something about this VideoGrant one is off, I just do not see it.
// ***********************************************************************************
// ***********************************************************************************
// Video Access Token
// ***********************************************************************************
// ***********************************************************************************
var videoCallAccessToken = function(request, response) {
console.log('/twilio/video/accessToken');
var accessToken = makeVideoAccessToken();
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end(accessToken);
console.log(accessToken);
};
app.get('/twilio/video/accessToken', videoCallAccessToken);
var makeVideoAccessToken = function() {
const AccessToken = twilio.AccessToken;
const VideoGrant = AccessToken.VideoGrant;
const grant = new VideoGrant({configurationProfileSid: accountData.videoConfigurationProfileSid});
const accessToken = new AccessToken(accountData.sid, accountData.videoApiSid, accountData.videoApiSecret);
accessToken.identity = 'ABC123';
accessToken.addGrant(grant);
return accessToken.toJwt();
};
FYI...I plan to alter the identity generation, but have not got there yet.
Thanks,
Adding this from my comment as an answer to close this question out, the issue was that the example code was flawed...
Ok, thought I had waited long enough prior to actually sending this, but apparently not. The issue is the example does not work in that the value passed into the VideoGrant constructor needed to have the attribute name quoted, so {configurationProfileSid: accountData.videoConfigurationProfileSid}); needed to be {'configurationProfileSid': accountData.videoConfigurationProfileSid}); Glad I finally found that, wasted a ton of time on it, but at least it is working properly now.

Sending data to a independent remote server

I want to send a json object to another server, independent of my website.
The API I am using requires a user (user x in this case) to log into their service to be authorized so user x can manipulate user x's list. However, other users can't write to x's list. So, users need to request an item to be added to x's list, then a server who is logged into x's account can add it to x's list. Refer to the image below.
http://imgur.com/a/wT53t
I am using node/express.js for the servers on the user's side. However, I don't know what I should use for a server who's only job is to receive requests and write to x's list. Can you provide some guidance as to how I can achieve something like this?
Thanks!
There are two options here:
You have to refresh the list in the realtime for connected users.
To achieve this you should use either: WebSockets(e.g. socket.io) or LongPolling.
In second option you dont have to refresh the list in the realtime. You simply use express. Accept data and refresh the list server-side.
Auth with web sockets:
Once understanding the nature of web sockets, you're free to build any logic around them, including authentication/authorization. The great library doing lots of auth things is passport.js.
Very quick and abstract example of server-side:
socket.on('auth', function(data) {
const vendor = data.vendor,
token = data.id
switch(vendor) {
/*
Here you grab through some social API user social id
and save it to database
*/
}
/* set socket as logged in */
socket.logged = true
/* or even save user object */
socket.user = { vendor, token }
})
Next time you need authorized user, you check:
socket.on('mustBeAuthorized', function() {
if(socket.logged || socket.user) {
/* Continue your logic*/
}
})

Resources