How would you approach an "authorization" microservice for resources that this service doesn't directly manage - authorization

We have a monolith application and looking to decouple the authentication / authorization service.
At this stage, authorization is the simplest to start with.
The problem comes with authorizing certain type of access to resources. e.g. a user can edit only his own posts.
Given that the microservice will hold only roles/auth items and assignments to an user id, does it make sense to create the following endpoint?
POST v1/<userEmail>/authorize/<authItemName>
with data, e.g.
v1/user#company.com/authorize/Posts.UpdateOwn`
{
post: {
content: 'My first post'
...
creator: {
email: user#company.com
}
}
}
Where we would send the object's data and the user's data. That way I can have a rule that would return true if object.creatorId === userData.id however if you think about it, it seems pretty dumb... if the monolith already has the info, why not just check for
the general permission Post.Edit and also checking that the user is the creator.
Is there a better approach for this?

Related

Authentication with JWT using GraphQL

After some search on the web I found that the best way of JWT authentication when using GraphQL is by inserting the JWT token into the GraphQL context. By doing so, resolvers can have access to it and check if the user is logged in, has permissions, etc.
I was wondering if I will need to place the authentication logic/function into every resolver that authentication is required. Is there a way which I could set by default (eg. middlewares) the authentication to every query except for login/logout/register/forgotpasword ones?
This question pops up every so often but not enough has been discussed. I think the answer lies not in the technology but in which way best suits your needs.
It is important to be mindful when adopting GraphQL that;
You don't have to give up on REST
You can have more than one GraphQL endpoints
Here are some suggestions based on my experience with implementing GraphQL
Authentication
For login/logout/forgot password and the whole shebang, consider going old-school. Form Post + Server-side rendering, REST API served us well for decades. Many third-party authentication services are based on this (Facebook Login, Google, OAuth2... etc). I tend to avoid using GraphQL for this purpose.
Authorisation
The logic to check if the requester is authorised to access the GraphQL can be generalised to 2 levels
GraphQL services
Essentially you check to see if the requester is authorised to use GraphQL service. Typically it's easier to check if the requester is authenticated, else deny access to the service altogether. This is typically done via a web server middleware.
There will be times where you'll need to expose some GraphQL queries to anonymous users, and I tend to lean towards having another 'unrestricted' GraphQL endpoint. This endpoint tends to have little to no mutations, exposes a limited subset of information and restricted nested queries.
Basically, you look at the data and decide which information/operation is public and which is not. IMO this is much easier to manage and secure than have a single GraphQL endpoint and implementing authorisation checkpoints in every query path/resolver.
Fine grain authorisation
At this stage basically, all requesters are authenticated users. We may need to question:
Is the requester the same user whose info is currently viewed?
Is the requester a friend of the user whose info is currently viewed?
Is the requester a member of the company whose info is currently viewed?
This is where putting the checking logic in resolvers (or models) really makes sense. I personally think resolvers are a great place to do this. Coupled with DataLoader the implementation can still be fast and effective.
Hope this helps!
No need to do checking in resolvers. You can add a middleware in your server side.
const graphQLServer = express();
graphQLServer.use('/graphql', function(req, res, next) {
var token = req.headers.token;
if (token != null && token != 'undefined') {
//Do token verification here
next();
} else {
// if there is no token
// return an error
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
})
Just try this

Wolkenkit: ACLs for authorization and user roles

I am trying to understand on how to extend the wolkenkit auth layer.
Say i want users with different roles: normal, moderator and admin.
normal users can see and modify their own content, but aren't allowed to modify content from other users.
moderator users are allowed to modify all entries, but don't have permission to delete anything than their own content.
admin users can modify and delete everything.
There are also unauthenticated guest users who can read everything but modify nothing.
Reading the docs for Write model: Configuring authorization i can model the guest/normal use case by writing something along the lines of:
const initialState = {
isAuthorized: {
commands: {
issue: { forAuthenticated: false, forPublic: false }
},
events: {
issued: { forAuthenticated: true, forPublic: true }
}
}
};
For my requirements i would need additional roles defined in this object. Something like { forModerator: true, forAdmin: true }.
There is also Granting access from a command to change permissions at runtime, but i am not sure if that would work. Even if it does, that feels quite hacky.
Is this somehow possible?
Disclaimer: I am one of the developers of wolkenkit.
To cut a long story short: No, right now unfortunately this is not possible, but this feature is on our roadmap. At least today, I can't tell you when this will be available.
Your best option would be to do it on your own. One way to do this might be to use your identity provider to include a moderator claim in the JWTs of the moderators, and then handle this in the command handler appropriately.
In the command handler you have access to the token by
command.user.token
so you can get the claims as needed. I'm very sorry, that there is no better answer right now :-(

How to restrict access some part of module in ZendFramework 2 (i.e. only administrator can do some actions)

so!
I have a question: how to allow access some part of module only for adminisitrator, for example.
For example, I have module album. It has controllers index, delete, add, edit, full. I want full and index controller be available for all roles, but edit, delete and add action only for administrators.
What module I have to use to do that? I found Zend\Authentification.
Table is: username, password, role.
How to authentificate user?:
// do the authentication
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($authAdapter);
if ($result->isValid()) {
// success: store database row to auth's storage
// system. (Not the password though!)
$data = $authAdapter->getResultRowObject(null, 'password');
$auth->getStorage()->write($data);
$this->_redirect('/');
} else {
// failure: clear database row from session
$this->view->message = 'Login failed.';
}
After that I will get access to user data, for example, by:
Zend_Auth::getInstance()->getIdentity()->username;
So, in action, in which I want to restrict access I just need to use:
if(Zend_Auth::getInstance()->getIdentity()->role == admin) {
redirect("auth/login");
}
Right?
The questions:
Is my suggestion about how to check user role in each contoller correct?
Do I understand correctly how to work with Zend\Authentification and restrict access to some actions? So in future I will just use same for each action, right?
Additional question: Does Aclmodule uses for managing permissions? So Acl is needed to help Zend_Auth with permissions, right?
To be able to do this you have to build or implement an ACL (Access Control List). You can also use a third party solution in combination with the earlier mentioned Zend_Auth (or any other authentication module). You can read more on Zend ACL here: Zend ACL introduction
You could for example also take a look at BjyAuthorize. This ACL module provides a complete authorization solution for your application but depends on ZfcUser for user authentication and registration. It might be a good way to get started.
If you are done building or implementing BjyAuthorize you can easily tie your access permission checking to your routes (but there are many other ways). You can see how this works here on the BjyAuthorize GitHub page
These modules will teach you a lot about how authentication and authorization can be build into your Zend Framework 2 application.

Authorization dependent REST API

as part of a server REST API design I'm considering I'd like to be able to return data that is conditional on the level of authorization of the client. What would be the recommended way of doing accomplishing that and still calling it one API? More specifically, consider the following example for a book access API:
HTTP GET /library/books/{book-name}
Any authenticated client should be able to get (JSON) data for the book, like:
{
"book":
{"book-name":"abc", "author":"someone"}
}
But a specific sub-set of authenticated clients should also be able to get:
{
"book":
{"book-name":"abc", "author":"someone"},
"private-info" :
{"book-status":"on-loan", "price":"$20"}
}
For a given book, any suitably authorized client can also access the "private info" via a direct HTTP GET /library/books/{book-name}/private-info.
Now, assuming a suitable client authentication scheme is in place, I cannot help but think that the HTTP GET /library/books/{book-name} above is actually looking like two API's, distinguished by authorization state on the server regarding authentication. This seems not very RESTful.
Perhaps it would be better to keep the base GET book API the same for all without ever having any "private-info", while offerring authorized clients only access to the private-info URI and returning 403 to all others?
How does this type of conditional data access typically get handled with REST APIs?
There is nothing inherently wrong with your approach - it makes good sense to hide information as you suggest based on the user's authorization. REST says nothing about this - the representation of a resource may depend on user authorization, moon phase or what ever else you can think of.
You can although improve caching if you extract the private information to a separate resource. In this case you would have some rather static content for /library/books/{book-name} which can be cached on the client side. Then you would have /library/books/{book-name}/private-info which would be more volatile and user-dependent - and thus not easily cachable.
Building on this you can include a link to the private information in the original resource:
{
Title: "A book",
Author: "...",
PrivateInfoLink: "http://your-api.com/library/books/{book-name}/private-info"
}
The benefit of this is two-fold:
1) The server can leave out the link if the client does not have access to the private information and thus saving the client from a unnecessary round trip to (not) get the private info.
2) The server is free to change the private-info URL if it needs so later on (it could for instance be different URLs based on the user authorization).
If you want to read more about the benefits of hypermedia then try this: http://soabits.blogspot.dk/2013/12/selling-benefits-of-hypermedia.html
I recently answered a similar question. You can find my answer here.
The bottom line is: You should try to separate business logic from authorization logic always. This means you want to externalize your authorization. There are several ways of doing that.
In your particular case, imagine the list of sensitive fields that only a subset of clients can view changes over time, that would potentially require a rewrite of your API. If you decouple authorization logic from your business logic (API) then you can easily update authorization logic without having to rewrite any code. This is called externalized authorization management (see this great Gartner paper on the topic).
As part of my day-to-day job, I help clients secure APIs and web services using XACML. The best practice is always to keep concerns separate.

Is it RESTful to send user role in http response?

I'm trying to find a way to modify a web page based on the a user's authorization. For example, the owner of a resource should see edit and delete buttons while a regular user should not see those.
The following is a method I am thinking about, but am unsure if there is a more common/better way.
For example, assume there is a resource
project: {
name: string,
owner_id: id,
moderators: [ids],
other_stuff: string
}
Would it be RESTful and good practice to extend this object with an attribute that describes what role the current logged in user is? For example, assuming this user is one of the moderators, it'd send
project: {
name: string,
owner_id: id,
moderators: [ids],
other_stuff: string,
user_role: "moderator"
}
Then the client-side framework would use project.user_role to display role-based controls such as delete and edit.