Express REST API with JWT and Routes - api

I am trying to create an Express API with JWT authentication.
However, I was wondering how to best allow users to only access their own resources.
For example if there is a user with id 1 and each user has a list of books in the database:
The id is already part of the JWT Token but commonly there would be a request to something like /users/1/books to get all of the books belonging to user 1.
Would my routes typically still look like this and I would just check the id in the token is the same the request is made for, or is there any other/simpler way?
Thank you for your help!

You can define, some access rights permissions base on the user role or id.
Example: roles : {root, admin, staff}
Then, in your routes you can have some checking whether this user have the permission to access the functions or you can do in the controller level to check the access rights.
You need to define model relations between User, UserModel. In your case as I understand you need to have the relations between UserModel and BooksModels.
UserModel hasMany BooksModel
When you call findOne() to retrieve specific user's data, you can just define include: 'aliasModelName', to retrieve the users related book data.
With this way, you can only have 1endpoint users/:id to retrieve users data and book data. It depends on what you really want, you can also have an endpoint users/:id/books to get all books that belongs to this user.
Your model definition will then become
BooksModel belongsTo UserModel
If you use hasMany you can get all the results that you need in just one query.
Hope this helps!

When user sends the login credentials, you check database if the email exists, if yes then you check if the password matches. If user successfully signins you create the token.
const token = jwt.sign({ _id: user._id, email: user.email }, "this-is-secret", {
expiresIn: "1h",
});
this token is sent to the browser, whenever user make requests, it manually attachs this token to the req, and sends the request to your server. You check if the token is valid, by using the secret key (in this case "this-is-secret").
const decodedToken = jwt.verify(token, "this-is-secret")
req.userId = decodedToken.userId;
now "userId" is attached to the req object. Now when you fetch the data from database, the items that you are fetching, you write a query that (implementation depends on which database you are using)
book.userId=req.userId

Related

Use the same route with different types of users

I'm developing an Expressjs application and I want to know how I could access the same route using different types of users.
In my application, I'm using sessions to authenticate the user, so when the user is logged in, I store the user id in a session on the server. When the user sends a request to the server I use that id to access the user data, my question is the following, how an admin user can use these same routes to access the user data?. In the case of an admin, I can't use the id stored in the session, because the admin id and the user id are different. One solution would be to send the user id in the params of the request, but then I have another problem, how can I know when to use the id of the params or the id of the session.
For example I have the route GET /user, this route return the logged in user, using the session id:
route.get('/user', (req, res) => {
const user = User.findOne(req.session.userId);
res.json(user)
})
But what happend if I'am a admin and I want get a user by his id, I need to duplicate the route, but instead of use the session id I use the id send in the params:
route.get('/user/:id', (req, res) => {
const user = User.findOne(req.params.userId);
res.json(user)
})
Now, imagine that these routes are much bigger and have dozens of lines. I wouldn't like to repeat the same logic several times.
I don't want that a normal user can access to his data using its id (as a param in the URL), because that user just must access his own data and if I put the id in the URL then a logged in user could access the data of other users.
What I want to achieve is that the normal user just can access their own data, but that the admin users can access the data of all users, without having to create different routes for each type of user.
I want to know as this scenario is managed on other applications.
My solution would be to save the user's role in session then use a middleware to check his privilege.
middlewares/Auth.js
exports.hasPrivilege = (req, res, next) => {
if (req.session.isAdmin) {
return next();
}
res.status(403).json({
msg: 'Forbidden'
});
};
If the user is allowed to access this route the function will send the data
route.get('/user/:id', Auth.hasPrivilege, (req, res) => {
const user = User.findOne(req.params.userId);
res.json(user);
});

Disqus - How to pass current logged in user?

I am using Disqus API to fetch details of the logged in user. I am not sure how to pass the current logged in user.
I have both api_key(public) and remote_auth and I am using Jquery ajax to send api request over http.
If I do something like this,
https://disqus.com/api/3.0/users/details.json?api_key=[apikey]
It says "You must either provide a user or authenticate the user." Now I have the loggedin users remote_auth.
FYI: This is how I am creating the remote_auth. Example User Id: 3096795, email = "a#a.com", Name="Test". Now when this user logs in to the website, it logs in to Disqus as well. I can see this user in http://disqus.com/api/sso/users/ with id = 3096795.
I have couple of questions:
1) Can I use jquery ajax to send a authenticated user and get user details? Or this can be done only via Server side? (Java/Php)
2) If I pass ?remote_auth=[remote_auth] as a query string, will it work?
3) if yes, remote_auth value has spaces in between HMAC->SHA1(secret_key, message + ' ' + timestamp) so how can I pass it as query string parameter?
4) If no, then how to pass a user to the listActivity.json endpoint? If I am passing the userid, then it returns me some other user and not the user I created.
The below request returns a different user.
https://disqus.com/api/3.0/users/details.json?api_key=[apikey]&user=3096795
How can I ensure the userid I am passing is unique and not already taken by a different disqus account?
Am I missing something?
Your remote_auth is a form of authentication, just like access_token, so you'll want to pass that in your request as remote_auth=<YOUR_PAYLOAD>.
If you pass "user=" that ID would have to be the Disqus user ID, which isn't the same as your remote_auth ID. Your remote_auth is a form of authentication, just like the access_token. However, keep in mind that we don't return as many details for SSO users as authenticated Disqus users. This is because the details are managed by you, the SSO site owner.
To answer your other questions:
You can use the client-side API to get these details, but we recommend the server-side API + caching the results to avoid bumping into API limits.
URL-encode the payload and this will work
Easier using https://github.com/anthavio/disquo
DisqusApplicationKeys keys = new DisqusApplicationKeys("...api_key...", "...secret_key...", "...access_token...");
DisqusApi disqus = new DisqusApi(keys);
//SSO is available only to premium accounts
SsoAuthData ssoauth = new SsoAuthData("custom-12345-id", "Firstname", "Surname");
//SSO User identity is used to create post
disqus.posts().create(ssoauth, keys.getApiSecret(), threadId, "Hello world " + new Date(), null);

Login as user without password (For an Admin Use-Case.)

To check if the view of a user is working or to make change out of the users view point (in development) it can be quite useful to incarnate a certain user.
How would I do this with Meteor? Best would be a solution which is independent of the Account Authentication.
To impersonate a user in production, you can call setUserId on the server, and Meteor.connection.setUserId on the client. For more details, see my blog post.
If you're using Meteor.userId() and Meteor.user() to identify your person in your javascript you could use something like this to override it at the very top of your client js
Meteor.userId = function (impersonate_id) {
return (impersonate_id) ? impersonate_id : Meteor.default_connection.userId();
}
Meteor.user = function (impersonate_id) {
var userId = Meteor.userId(impersonate_id);
if (!userId)
return null;
return Meteor.users.findOne(userId);
}
And now when you use Meteor.userId or Meteor.user modify your code so everywhere you use Meteor.user & Meteor.userId accepts an argument. So when you want to impersonate a user just pass it argument of the _id of the user you want to log in as
Meteor.user("1"); //Loads the data for user with _id 1
Meteor.user(); //Loads the actual logged in user
Also this will only work if you're actually the admin and your publish function allows you to see all your user's data

Laravel, get currently logged-in users

I want to display a list of currently logged-in users in an app. I want to use Laravel Auth method. I'm looking at the API and I cannot find anything like it.
I would probably need to loop through the sessions store and then match it to a user ID. Am I right?
UPDATE: Forgot to mention, I'm storing sessions in the DB.
"Currently logged in" is something you can't do with plain old sessions. Let me explain why:
A session is a bunch of data stored at server side which is assigned to an user through a cookie. That cookie remains on user browser and so it keeps the session active. Sessions can stay "alive" months without the user even logging in.
But, it's possible to store sessions on database.
As you can see, Laravel keeps a field called last_activity and, through that field, you should be able to retrieve all sessions that had activity within the last 15 minutes (or something else, you call it).
When your retrieve those records, the data field is a serialized representation of session data. You can unserialize($session_record->data) and retrieve the user id.
Depending on your Auth driver, session's user id may have different names:
For eloquent driver, it should be eloquent_login.
For fluent driver fluent_login.
For your Custom\AuthClass, it should be called custom_authclass_login.
Assume that all http requests from logged in users are passing auth middleware, we can override terminate function like following:
public function terminate($request, $response)
{
Auth::user()->save();
}
Then a query like User::where('updated_at', '>', Carbon::now()->subMinutes(12))->get(); will bring all logged in user, where 12 is the lifetime of session.
Of course, for real time, we should use ajax calls every 5 seconds or websockets via pusher or other.
First create a table where the logged in user's id will be inserted
Schema::create('active_users', function(Blueprint $table)
{
$table->increments('id')->unsigned();
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')
->onUpdate('cascade')->onDelete('cascade');
$table->timestamps();
});
Then in yourcontroller insert data while logging in
if (Auth::attempt($credentials)) {
DB::table('active_users')->insert(array('user_id' => Auth::id()));
}
and delete the data while logging out
DB::table('active_users')->where('user_id', '=', Auth::id())->delete();
Print the online users list in your view
<ul><strong>Online Users</strong>
<?php $online_users = DB::table('active_users')->where('user_id','!=',Auth::id())->get(); ?>
#foreach($online_users as $online_user)
<li>{{User::find($online_user->user_id)->first_name}}</li>
#endforeach
</ul>

How to get useID/Email of logged in user in Google Contacts API after OauTh Token

I developed a program which works well and I can import data from gmail but. I want to keep track how is the user given permission to manage contacts. But after a hard search I did not get any Idea about the loged in user. My code is as follows.
============================================
var parameters = new OAuth2Parameters
{
ClientId = ConfigurationManager.AppSettings["ClientID"].ToString(),
ClientSecret = ConfigurationManager.AppSettings["ClientSecret"].ToString(),
RedirectUri = ConfigurationManager.AppSettings["RedirectURL"].ToString(),
Scope ="https://www.googleapis.com/auth/userinfo.profile"
};
parameters.AccessCode = Request.QueryString["Code"].ToString();
OAuthUtil.GetAccessToken(parameters);
Session["Token"] = parameters.AccessToken;
==================================
But I dont how to get email of logged in user. Please let me that
Thanks in advance
Request an additionall scope of https://www.googleapis.com/auth/userinfo.email and then you can access the user info as well. There is also a userinfo.profile witch contains other info on the user like name, profile picture, language and so on.
Your code looks like C# but I only have a Python example of using multiple scopes and sharing tokens.
Code: https://code.google.com/p/google-api-oauth-demo/
Article: http://www.hackviking.com/2013/10/python-get-user-info-after-oauth/