Should login and get profile be two different api endpoints? - node.js

I am designing api for mobile application.
I am not sure should I have one endpoint login which will return tokens & user profile
Or have two endpoints and after login call getProfile endpoint.
I saw that people mostly use second option but I don't see benefit of that approach?

Thinking in terms of the single-responsibility principle (which basically says "API methods should do one thing really well"), I'd suggest separating these into two separate things:
POST /login would set up a session and return the session ID to be used in subsequent requests.
GET /profile would return profile information provided a valid session ID is provided.
There are obvious benefits along the "happy path" for combining these, mainly the fact that after a login operation completes, you automatically provide the user with the data they most obviously would want next (who the user is). Why waste an extra API call to find it out, right?
If that's all your API will ever need to support, then there's no reason to separate these. But there are a couple cases I can think of for why you might want them separate:
What if an existing and already logged-in user wants to fetch the latest profile information? This means you must support GET /profile anyway (or have them POST /login again which is wasteful).
What if profile information is already cached and the POST /login API call is only happening to re-authenticate the user inside the app to complete an action? You'd be wasting bandwidth by sending data that's not needed.
Additionally, testing is usually a bit easier when you have each API method doing the one thing they imply they do (POST /login logs the user in, GET /profile fetches the current logged-in user's profile).

Related

Passing sensitive data through to the ui

I'm working on an implementation of the Facebook api and I'm to the point that i can fetch a users pages and would now like to display these to the user so they can select where to send the post. These page objects have an access token on them to verify requests with Facebook and intuition tells me you wouldn't want to send these through to the ui then back again. I could just make 2 calls when sending and receiving, filter the results to remove the access tokens, then when receiving a request make another call to the api and filter the page results by id.
I'm curious though if theres a way to get around making 2 api requests and reduce overall requests to the api and keep the usage down.
You could just store the page tokens in the session, when you get the list of pages - then you don’t need to make a second API request after the user made their choice.
(Session data is tied to a specific client, and never leaves the server. Only thge session ID is passed between client and server.)

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.

Protocol, paradigm or software for authenticating web requests across one's own domains

tl;dr
I am considering a webservice design model which consist of several services/subdomains, each of which may be implemented in different platforms and hosted in different servers.
The main issue is authentication. If a request for jane's resources came in, can a split system authenticate that request as her's?
All services access the same DB layer, of course. So I have in mind a single point of truth each service can use to authenticate each request.
For example, jane accesses www.site.com, which renders stuff in her browser. The browser may send a client-side request to different domains of site.com, with requests like:
from internalapi.site.com fetch /user/users_secret_messages.json
from imagestore.site.com fetch /images/list_of_images
The authentication issue is: another user (or an outsider) can craft a request that can fool a subdomain into giving them information they should not access.
So I have in mind a single point of truth: a central resource accessible by each service that can be used to authenticate each request.
In this pseudocode, AuthService.verify_authentication() refers the central resource
//server side code:
def get_user_profile():
auth_token=request.cookie['auth_token']
user=AuthService.verify_authentication(auth_token)
if user=Null:
response.write("you are unauthorized/ not logged in")
else:
response.write(json.dumps(fetch_profile(user)))
Question: What existing protocols, software or even good design practices exist to enable flawless authentication across multiple subdomains?
I seen how OAuth takes the headache out of managing 3rd-party access and wonder if something exists for such authentication. I also got the idea from Kerberos and TACACS.
This idea was the result of teamthink, as a way to simplify architecture (rather than handle heavy loads).
I built a system that did this a little while ago. We were building shop.megacorp.com, and had to share a login with www.megacorp.com, profile.megacorp.com, customerservice.megacorp.com, and so on.
The way it worked was in two parts.
Firstly, all signon was handled through a set of pages on accounts.megacorp.com. The signup link from our pages went there, with a return URL as a parameter (so https://accounts.megacorp.com/login?return=http://shop.megacorp.com/cart). The login process there would redirect back to the return URL after completion. The login page also set an authentication cookie, scoped to the whole of the megacorp.com domain.
Secondly, authentication was handled on the various sites by grabbing the cookie from the request, then forwarding it via an internal web service to accounts.megacorp.com. We could have done this is a straightforward SOAP or REST query, with the cookie as a parameter, but actually, what we did was send a HTTP request, with the cookie added to the headers (sort of as if the user had sent the request directly). That URL would then come back as a 200 if the cookie was valid, serving up some information about the user, or a 401 or something if it wasn't. We could then deal with the user accordingly.
Needless to say, we didn't want to make a request to accounts.megacorp.com for every user request, so after a successful authentication, we would mark the user's session as authenticated. We'd store the cookie value and a timestamp, and if subsequent requests had the same cookie value, and were within some timeout of the timestamp, we'd treat them as authenticated without passing them on.
Note that because we pass the cookie as a cookie in the authentication request, the code to validate it on accounts.megacorp.com is exactly the same as handling a direct request from a user, so it was trivial to implement correctly. So, in response to your desire for "existing protocols [or] software", i'd say that the protocol is HTTP, and the software is whatever you can use to validate cookies (a standard part of any web container's user handling). The authentication service is as simple as a web page which prints the user's name and details, and which is marked as requiring a logged-in user.
As for "good design practices", well, it worked, and it decoupled the login and authentication processes from our site pretty effectively. It did introduce a runtime dependency on a service on accounts.megacorp.com, which turned out to be somewhat unreliable. That's hard to avoid.
And actually, now i think back, the request to accounts.megacorp.com was actually a SOAP request, and we got a SOAP response back with the user details, but the authentication was handled with a cookie, as i described. It would have been simpler and better to make it a REST request, where our system just did a GET on a standard URL, and got some XML or JSON describing the user in return.
Having said all that, if you share a database between the applications, you could just have a table, in which you record (username, cookie, timestamp) tuples, and do lookups directly in that, rather than making a request to a service.
The only other approach i can think of is to use public-key cryptography. The application handling login could use a private key to make a signature, and use that as the cookie. The other applications could have the corresponding public key, and use that to verify it. The keys could be per-user or there could just be one. That would not involve any communication between applications, or a shared database, following the initial key distribution.

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