OpenID authentication through Steam - node.js

I've spent the better part of the day trying to figure out how OpenID works. My goal is to set up a simple site where, upon clicking a login button, users are taken to a Steam login-page, where they are prompted for username and password. After successfully logging in, the user is redirected to a page on my domain, where I collect the query string parameters. They look like this:
{
"openid.ns": "http://specs.openid.net/auth/2.0",
"openid.mode": "id_res",
"openid.op_endpoint": "https://steamcommunity.com/openid/login",
"openid.claimed_id": "https://steamcommunity.com/openid/id/7656119[0000000000]",
"openid.identity": "https://steamcommunity.com/openid/id/7656119[0000000000]",
"openid.return_to": "http://127.0.0.1:8000/resolve",
"openid.response_nonce": "2018-12-01T14:49:46Z30hhn2/[someTEXTendingIN=]",
"openid.assoc_handle": "1234567890",
"openid.signed": "signed,op_endpoint,claimed_id,identity,return_to,response_nonce,assoc_handle",
"openid.sig": "[someTEXTandNUMBERSendingIN=]"
}
What I am unable to solve though, is the actual authentication issue. I'm not sure what to do with this data. I want to have my own database where I store more information about the user, such as friends, messages, currency etc. For this, it is very important that I can verify that someone didn't just take this request body, change their ID for another and in that way access their account.
I'm pretty sure these are the relevant pieces of documentation, but it still isn't clear to me. How am I supposed to authenticate the user with this data?
I've omitted some values in this post that I fear could be bad to share. These placeholders have been outlined with brackets []. Also, that assoc_handle is really 1234567890, which kind of puts me off, since according to the OpenID documentation, it is used for determining the signature.
To be clear: this page where credentials are collected is not run by me, but is the official OpenID sign-in page for Steam. Steam is a gaming platform. https://steamcommunity.com/dev/ for reference.

For Steam authentication in nodejs you can use Passport.
Passport is an authentication library that works best with Express-based web application.
There is a steam-strategy that can handle your steam authentication.
Check passport here
And this is the Repository for Steam strategy. There is an example folder that you can see how to setup your Steam authentication.

Related

How can I protect a express route without authentication?

I'm trying to implement a GET method with Express in my nodeJs application.
I'd like to do something like this in order to display user data :
router.get("/user/:idUser", (req, res) => {
The user doesn't need to be authenticated in order to execute this code. However I don't want that anybody can execute this request with a user id of someone else. Because he could see data he's not supposed to see.
How could I proceed ? I thought about using some encryption process to have something like :
/user/PdfgdfJFDGTfrfgdsf
Your question isn't really making sense. You don't want authentication, but you only want a user to be able to view their own data so nobody else can view it.
The ONLY way to solve that is by using some form of authentication. The user has to prove to the server that they are allowed to view that data before the user renders the page for them.
Yes, you could obscure the URL (make it some mostly unguessable string of characters), but it's not clear what problem that is solving. The user themselves won't be able to remember it or type it so it would probably have to be a link in a web page and if it's a link in an unauthenticated web page, then anyone can get to it - thus defeating the purpose.
There are cases where temporary links (often done for privileged downloads) such as what you mention /user/PdfgdfJFDGTfrfgdsf are sent via an authenticated channel (either an authenticated webpage or sent to an email address known to belong to an authenticated user) and these links contain some unique and hard to guess code. The user can then click on that link (in authenticated webpage or in email) and access that resource without further authentication. In that case, the knowledge of the code in the URL is serving as a form of proof of authentication. Because URLs may be logged in service providers or corporate infrastructure and thus not remain entirely private, this technique has its limitations and is typically only used for short term (download this resource in the next 10 minutes) type of uses, not a long term substitute for authentication and not used for things that demand real security. You don't explain enough of your use case to know whether this is practical for your situation or not.
The user doesn't need to be authenticated in order to execute this code. However I don't want that anybody can execute this request with a user id of someone else. Because he could see data he's not supposed to see.
That's an inconsistent statement. You say "user doesn't need to be authenticated in order to execute this code" and then you say "I don't want that anybody can execute this request with a user id of someone else.". You can't have both. The user is either required to prove authorization or they aren't. Pick one. It can't be both.
you can use jwt for this and a auth middleware for this
upon decoding jwt token, you can implement logic to check if the decodedToken.user_id (given that you add user_id when encode token payload) is equal to the :idUser in route (or any kind of logic you want) there.

Is there any difference in behaviour between auth/credentials and auth/basic?

We have two separate websites which essentially share the same UserAuth data store. We want to provide the user with a link from one to the other without requiring them to login again.
At the moment we currently make a call to the target website's API: /auth/credentials which sets up the session and allows us to then redirect the user, bypassing the need go through the login screen. Great.
As far as I can tell /auth/basic should do exactly the same thing. However, the response from the API call is the same but when redirected the user ends up at the login page.
Have I missed something?
Version: 4.5.8
They are not the same, the BasicAuthProvider enables HTTP’s Basic Access Authentication and is a per Request Auth Provider.

Node.js Two-Factor Authentication

I am working on a personal program using node.js that uses authentication for Steam app specifically. The login reads the username and password from an external .txt file and it works using array positioning, split by a ‘:’ (colon). Now this is where I need help. With some accounts Steam uses a two factor code that is randomly generated by time on a mobile app or by email. At this time, I have my program so it checks to see if the account has the authentication code enabled and if it does I have it prompt to manually put in the appropriate two factor code. I know that there is a way to incorporate my program to pull this authentication code and put it in without having the user to do so manually but I don’t know where to start.
Problem: I want the program to pull a randomly generated code and automatically set it in without having to do anything manual.
Code is as follows:
else if (eresult === Steam.EResult.AccountLoginDeniedNeedTwoFactor)
{
login.two_factor_code = readline.question(`[${param[0]}] Mobile auth code: `);
client.disconnect();
client.connect();
}
else if (eresult === Steam.EResult.AccountLogonDenied)
{
login.auth_code = readline.question(`[${param[0]}] Steam Guard code: `);
client.disconnect();
client.connect();
}
Thank you.
Two factor authentication (2FA) is a principle where you're authorized to a resource by two separate factors. 1. something you know (login/pass) 2. something you have (a phone with a 2FA app installed, like Google Authenticator, Authy, also I think there's an app for this made by Steam).
If I understood you correctly - you want to store passwords and 2FA details in your app. Probably there's a technical way to do it, but I would not use such an app. This is a big security no-no. Better to ask users of your app to provide login/password each time, and if Steam API asks for second factor - ask the users for it.
As I seen most APIs - you could probably get a special token so the user don't have to login and provide the code each time without storing the password etc. Dig in the docs - you'll find it. (Unless you don't use any official Steam API, but it looks form the code that you probably do)

Authorisation strategy for a first-party express based node API

I'm tackling the design of my first API and am struggling somewhat with authorisation concepts - I was hoping some kind people could give me some advice!
What I'm building:
An API that will eventually be accessed by third party apps and a mobile app.
A web-based 'client' (first-party single page app) that will use the API. (Should this first-party app be 'a part' of the API, or a completely separate node app?)
Technology I plan to use:
Node
Express
Passport
Mongodb with Mongoose
I'm not wed to express or passport, they just seem like the best options and are well documented - bit I wouldn't want a potential solution to be dismissed because of alternative dependencies. Same with Mongoose, I actually prefer the look of Monk (or even just Mongojs), but every tut seems to use mongoose, so seems like the safest option for a node beginner.
Authenticating a user is simple enough (I've gone through the fantastic Beer Locker tutorial), what I'm struggling with is ongoing authorisation. Naturally I don't want the user to have to input a username and password with every request they make - should this information be stored locally and sent with every request? (if so, how? I can't find any info on handling an API with a session) or should I be working with tokens of some sort? The small amount of reading I did on 'Digest' authorisation (including the Beer Locker tutorial follow-up) made it seem like it had security issues, at least with the Passport implementation (this I don't fully understand, but seems to relate to hashing passwords, which passport doesn't do as standard, and only MD5 is supported even if it's added?).
I have built a working API that I can authorise with 'Basic' (directly, through Postman), so I have the foundations in place - authorisation works, I just need the tools to take that to the next step and add sessions into the mix!
I've been trying to get my head around this for a couple of days now, but I fear I'm too stuck in a more traditional local web-app workflow - the whole API thing is throwing me somewhat.
Any help is hugely appreciated, even if it's just pointing me at an appropriate tutorial - the above set of requirements must be quite common!
I have come accross this problem too...
I can only recommend doing this for the beginning:
http://scotch.io/tutorials/javascript/easy-node-authentication-setup-and-local
tell me if it helped :)
As I understand you have done the authentication and the only thing you have to do now is store somewhere that the current user is authenticated, his name, roles etc to use later with other requests. In the Passport you will do it in the function callback (instead of the "If this function gets called..." comment).
Now you have to decide, you have two options:
Store the user information (name, roles etc.) on your server (in a session) and give the user some long code which will identify his session for the next requests
to store the information on your server you may use for example the express-session middleware
it would be probably best to save the session identifier in a cookie, but read some security issues before
Give the user something that would prove to you he/she is authenticated and which name, roles etc. he/she has
you can generate a token, that contains the user information (name, roles etc.) that the user will send with every request. to know this token is legit, you will have to sign it. more on this is on jwt.io and you can use express-jwt middleware.
you dont have to care about storage of session with this one
the token can be placed to a cookie too, but same security issues apply. it is still considered better that localstorage (more here)

Facebook Javascript SDK security

I'm in the process of using the facebook javascript sdk to provide user login functionality for a website.
What I'd like to do is simply take the logged in user's unique facebook id and then put/fetch data to/from a mysql database using the id to determine what data is available to said user.
However I don't really feel like this is very secure. Whilst I'm not storing anything sensitive like credit-card details etc, I'd obviously prefer it to be as secure as practically possible.
My fear is that with javascript being what is it, someone could fake the facebook id and just pull whatever they wanted.
I'm aware that the php sdk would provide a solid solution to this problem, but i like the javascript one mainly because it's easy to use and I have the basis of it set up (I admit it, I'm lazy).
So, my questions are:
Would this set up be as insecure as I feel it might be?
Is there anything I can do to improve the security of such a system, other than switching to the php sdk?
Thanks!
Facebook Ids are pretty hard to make up (at most a user will only know their own). Depending on what you store in the database (which will not be anything that the user cannot get on their own, unless you ask for extended permissions)
If you are worried about a user trying to get information from the database, add an access token or signed request to each row and us that and facebook id to get data. That will greatly increase security.
EDIT
There are few occasions where you get a signed request from a user:
* A signed_request is passed to Apps on Facebook.com when they are loaded into the Facebook environment
* A signed_request is passed to any app that has registered an Deauthorized Callback in the Developer App whenever a given user removes the app using the App Dashboard
* A signed_request is passed to apps that use the Registration Plugin whenever a user successfully registers with their app
Signed requests will contain a user id only if the use has accepted permissions though, and are not passed again if the user enters the application, and accepts permissions (meaning that the signed request would not contain the ID). Because of this saving an access token may be a better idea. Here is more on the signed request
Also the signed request is in the url (param = "signed_request"). I always parse it through c# but I am sure you can at least get one through javascript
It's pretty easy to spoof the origin using curl. I'd imagine Facebook has another mecanism in place to make this possible. If you inspect their code, it appears that they generate an iframe and pass requests through. If I had to guess, they have setup the requests to only be made from the Facebook domain, and ensure that the iframe can only be embedded in a page that has a white listed domain.

Resources