JSON web token - applying different user roles to different routes - json

What is the standard practice for using JWTs in authentication mechanisms which require roles?
Should roles be contained somewhere within the predefined public claim names?
['iss', 'sub', 'aud', 'exp', 'nbf', 'iat', 'jti]
... Or should an application specific private claim name be used?
Or should the application refrain from putting roles in JWTs and keep all role based logic within the application only?
More detail:
When using JSON web tokens as a user authentication mechanism, and you apply the authentication on a set of routes, when a token is valid, authentication is valid for all routes in the set. If the token is not valid, it is invalid for all routes in the set.
This is great if all users have the same level of access. However, if users have different roles, say "user" and "admin", and only the "admin"s have access to certain routes, this falls down.

Related

Is using authentication as context RESTful?

I am wondering if implicitly using the currently authenticated user as context for API interactions is RESTful or not. For example, assuming all my API calls are authenticated using standard HTTP security:
Should a query to retrieve a list of orders for the user be explicit?
NO: http://example.com/orders
YES: http://example.com/orders?userid=1234
When placing a POST to create a new order, should the JSON contain the user?
NO: { orderref: 'EXAM/1', items: { ... } }
YES: { userid: 1234, orderref: 'EXAM/1', items: { ... } }
Either way I'll be securing so that the API will only allow actions for the current user, but should I make the API caller state the userid for each action?
I would say you should only pass the user ID as a query if you have access to many user's orders and need to filter them by user.
If a user has access to only their own orders they should not have to pass a user ID - the base queryset should limit it based on their own authentication details. Arguably that may not be RESTful, but don't worry about that - most API's may not be 100% RESTful and you should do what makes sense for your application rather than worrying about whether it's RESTful - it's a guide, not a cast-iron requirement.
In any case depending on what type of authentication you use (BASIC or TOKEN), you have to send the user info in your API call (Headers) which makes the request to the API.
So when you say if it is valid to use the authenticated user from the Context, of course it is
sample code here
The api call
headers.Authorization = 'Bearer ' + localStorage.getItem("tokenkey");
Obtain user from the request
RequestContext.Principal.Identity.Name
Is it RESTful? I would argue that: yes it is. There is no REST spec, so there's nothing really that says that it isn't. HTTP does allow this, and HTTP Caches should actually by default consider responses to GET requests with an Authorization header as private.
Should you use this design? I don't know! I think there's benefits to having per-user endpoints, because in the future it might allow User A to inspect the orders of User B.
In our API we actually have an example of an API similar to yours, but we do both.
We have a /users/1234 endpoint.
We also have a /current-user endpoint.
Initially the /current-user endpoint just redirected to the uri of the actual current user, but eventually we decided we're actually just going to return the full object without redirecting (due to browsers not behaving nicely with redirects).
The current-user endpoint does have a self link still that points to the real user resource.
So to sum it up. I think you are in the clear here, but I argue that there are strong design benefits to creating resources that have a consistent representation regardless of who's looking at it. It makes things a bit simpler and nicer.
And also don't forget that there's no reason why you can't, if you are actually following REST. All a client should care about is that there's a link somewhere to a list of orders and it shouldn't care what it's url is.
+1 for Matthew Daly's answer. Especially when the authenticated user has only access to his own orders (I assume that).
In case that your authenticated user can access more order lists than only his own, I would go like that:
/orders: the authenticated user's orders.
/orders/123: the specific user's orders.
If 123 equals the authenticated user's id - so what? It would be most likely no problem case for your client.
By designing a REST service you think of the comfort that the developers could have, when they use your API. I would say, this one is a comfortable solution.
Should a query to retrieve a list of orders for the user be explicit?
NO: http://example.com/orders
YES: http://example.com/orders?userid=1234
When placing a POST to create a new order, should the JSON contain the
user?
NO: { orderref: 'EXAM/1', items: { ... } }
YES: { userid: 1234, orderref: 'EXAM/1', items: { ... } }
If user queries only its own orders, user id shouldn't be passed explicitly in the query - you should pass user token in HTTP header and your code should extract user id by provided token and determine whether authorized user has rights to see or modify particular data.
In case you want to let one user get or modify another user data then you would make additional endpoint - something like users/{userId}/orders or users/{userId}/orders/{orderId}. You would still pass user token via HTTP header and your implementation should check if user has admin rights for this action.

How to manage public and private resource in a RESTful API

I have a resource that has a public and a private response, and only some users in determinant situations can access the private response.
What would be the best implementation?
Two urls, one for the public and another for the private: resource/{id} and resource/{id}/private.
Same url, different response for each user: resource/{id}.
Same url with and a parameter that different the public and private: resource/{id}?private=true.
Other?
Your terminology is a little mixed up. You have one resource, and multiple representations. The resource should have one canonical location (URL). It's perfectly fine for different users to get different representations based on their auth level.
If you want a user to be able to request a specific representation of the resource, you have a couple of options. If you're using custom MIME types, the Accept header would be the best choice. A query parameter is your best bet if you're not using custom MIME types, but make sure it's something generic and consistent throughout the application. Don't just use ?private=true, but instead use something like ?representation=public. That allows you to add representations later and use the same parameter, and share the same query parameter with other resources that need to specify a representation. You should avoid using a separate URL.
IMO one resource should have only one URL. You can make use of auth-token in HTTP to check if the server should respond with a private response or a public response. Also if some user is requesting for some unauthorized resource, you can send a 4xx status.
Thus resource/{id} seems like a good choice.

CAS LDAP and database query

I have a user authenticated against LDAP using CAS. I now have the UID. Is it possible to use CAS to also query an oracle database using the UID to get other user attributes stored from oracle?
I've tried to use SingleRowJdbcPersonAttributeDao class in my bean but I can't get any attributes to release from it ... I'm not even sure if the query is being executed.
Yes. authentication in CAS is different from attribute retrieval. You can authenticate via one source, and get attributes from another. Authentication is handled via authN handlers, and attribute retrieval is handled via attribute repositories.
Once you have retrieved attributes, you need to configure your service definition to release those attributes. You need to define an attribute policy that authorizes the release of all or select attributes.
See http://jasig.github.io/cas/4.1.x/integration/Attribute-Release.html

Hiding JSON field that Client sees

I am implementing a web app where users enter their personal information to store them onto a database, in this case MongoDB. This acts much like an address book. These services are implemented using a REST API (I am using Spring framework), where clients can call GET requests to view other people's personal information, POST to add their own information, and PUT to update. The Administrator of the DB can use DELETE To remove users.
I have implemented all the CRUD operations for the services on the server side. But I have one question:
When a client calls GET for a particular user to see his information, the request is returned as a JSON string, where the password field is visible. I do not want the client to see the password, obviously.
Now, I tried adding #JsonIgnoreProperties({"password"}) at the top of my model class on the server side. Although this works and the client cannot see the password, The password is also not even stored on the MongoDB database with this implementation. Because when I call db.users.find().pretty(), to list all the documents in the collection, I do not see the "password" field for any of the users.
I need some way for the password to be stored on the DB, but unable to be viewed by the client.
Here is one of the GET methods which finds a user by his username:
/* Get user by username */
#RequestMapping(method=RequestMethod.GET, value="/getByUsername")
public #ResponseBody User getUserByUsername(#RequestParam("username") String username) {
return repo.findByUsername(username);
}
The Model class is just a class with a bunch of String variables, and getters and setters.
Thanks
You can use the retrievedFields method available in Morphia.
getDs().createQuery(className)
.field("username").equal(username)
.retrievedFields(false, "password")
.get();

REST API & Ember (data) - Many-to-Many relation with attributes

I have two resources in my system users and organizations.
Each has a name and a relation with the other (many to many).
In my REST API I have:
/organizations - returns all organizations in the system (public)
/users - return all users in the system (public)
After this I needed to add properties to the relation (e.g. role in the organization). For this I created the concept of worker, a person in an organization.
What I have tried:
A new model, a "full resource"; it doesn't comply with a good rest design.
A nested resource inside organizations; better in json, but in Ember using EmbeddedRecordsMixin I lose the ability to manipulate the model - e.g. usage of adapter or serializer to change the resource.
How to design the REST api?
How to define Ember models and how to manipulate them?
Suggest making a 3rd resource that contains the role properties and relations to user and organization
You can use links, an example response for an organization:
{
id: 1,
links: {
users: "/organizations/1/users"
}
}