Wolkenkit: ACLs for authorization and user roles - authorization

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 :-(

Related

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

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?

How do I enforce 2FA in .Net Core Identity?

Question: How can I enforce existing users to set up 2FA in .Net Core 3.1 Identity?
I have seen a couple of answers here already, but I have issues with them as follows:
Redirect user to set up 2FA page on login if they do not have it set up. Problem with this is that the user can simply jump to a different url to avoid this, therefore it is not actually enforced.
Have some on executing filter that checks if the user has 2FA enbaled or not and if not redirect them to MFA set up page. The issue I have with this is that on every single navigation the server must go to the database to check whether the user has this field enabled, thus creating a significant performance hit on each request. I know one trip to the database may not sound like much but I have worked with applications where this was the norm and other things used this method, causing a pile up of pre action db queries. I want to avoid this kind of behavior unless absolutely necessary.
My current idea is to on login:
Check the users credentials but NOT log them in
userManager.CheckPasswordAsync(....)
If the credentials pass, check if the user has 2FA enabled or not. If they do, continue through login flow, if not:
Generate a user token:
userManager.GenerateUserTokenAsync(.......)
and store this along with the username in a server side cache. Then pass a key to the cached items with a redirect to the 2FA setup page, which will not have the [authorize] attribute set, allowing users not logged in to access it.
Before doing anything on the 2FA set up page, retrieve the cached items with the provied key andverify the token and username:
userManager.VerifyUserTokenAsync(......)
If this doesn't pass, return Unauthorized otherwise continue and get the current user from the supplied UserName in the url that was passed via a cache key. Also dump the cached items and key so that should the url be snatched by a dodgy browser extension it can't be used again.
Continue to pass a new cache key to new user tokens and usernames to each 2FA page to authenticate the user as they navigate.
Is this an appropriate use of user tokens? And is this approach secure enough? I'm concerned that having the user not logged in presents security issues, but I think it is necessary in order to avoid the previously mention problem of going to the database on every request to check 2FA, as with this method trying to navigate away will just redirect to login.
I implemented this via a Filter Method
I have a BasePageModel which all my pages inherit
public override async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
{
if (!User.Identity.IsAuthenticated)
{
await next.Invoke();
return;
}
var user = await UserManager.GetUserAsync(User);
var allowedPages = new List<string>
{
"Areas_Identity_Pages_Account_ConfirmEmail",
"Areas_Identity_Pages_Account_ConfirmEmailChange",
"Areas_Identity_Pages_Account_Logout",
"Areas_Identity_Pages_Account_Manage_EnableAuthenticator",
"Areas_Identity_Pages_Account_ResetPassword",
"Pages_AllowedPageX",
"Pages_AllowedPageY",
"Pages_Privacy"
};
var page = context.ActionDescriptor.PageTypeInfo.Name;
if (!user.TwoFactorEnabled && allowedPages.All(p => p != page))
{
context.Result = RedirectToPage("/Account/Manage/EnableAuthenticator", new { area = "Identity" });
}
else
{
await next.Invoke();
}
}
I then changed both the Disable2fa and ResetAuthenticator pages to redirect to the main 2fa page
public IActionResult OnGet() => RedirectToPage("./TwoFactorAuthentication");
And removed the reset/disable links from that page
I chose to implement a more modern and OAuth friendly solution (which is inline with .Net Core Identity).
Firstly, I created a custom claims principal factory that extends UserClaimsPrincipalFactory.
This allows us to add claims to the user when the runtime user object is built (I'm sorry I don't know the official name for this, but its the same thing as the User property you see on controllers).
In here I added a claim 'amr' (which is the standard name for authentication method as described in RFC 8176). That will either be set to pwd or mfa depending on whether they simply used a password or are set up with mfa.
Next, I added a custom authorize attribute that checks for this claim. If the claim is set to pwd, the authorization handler fails. This attribute is then set on all controllers that aren't to do with MFA, that way the user can still get in to set up MFA, but nothing else.
The only downside with this technique is the dev needs to remember to add that attribute to every non MFA controller, but aside from that, it works quite well as the claims are stored in the users' cookie (which isn't modifiable), so the performance hit is very small.
Hope this helps someone else, and this is what I read as a base for my solution:
https://damienbod.com/2019/12/16/force-asp-net-core-openid-connect-client-to-require-mfa/
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/mfa?view=aspnetcore-5.0#force-aspnet-core-openid-connect-client-to-require-mfa

React/Rebase/Firebase warning: Permission Denied - How do I add user authentication?

Please excuse the simplicity of my question but I can't get Rebase/Firebase to work due to permission errors (Rebase is very similar to Firebase https://github.com/tylermcginnis/re-base)
I am building a simple website as part of a React.js tutorial and I simply want to persist some state on my page. To do this, all I want is the Firebase database, without user authentication, however when I set up the database, I get permission errors so user authentication must be mandatory.
This is what I have at the top of my main.js:
var Rebase = require('re-base');
var base = Rebase.createClass('https://fishmonger-f3761.firebaseio.com/');
and then in my main app component, I added this:
componentDidMount : function() {
base.syncState(this.props.params.storeId + '/fishes', {
context : this,
state : 'fishes'
});
I get the following warning in my console:
FIREBASE WARNING: set at /(*my custom store name*)/fishes/fish1/name failed: permission_denied
How do I add in anonymous browser-session based user authentication to disregard this error?
Firebase DB default rules require authentication.
From the Get Started with Database Rules page:
By default, your database rules require Firebase Authentication and
grant full read and write permissions only to authenticated users. The
default rules ensure your database isn't accessible by just anyone
before you get a chance to configure it.
That means that, for instance, you can give access to anyone. You just need to change the default rules of your database to look like this (again from the same documentation page):
// These rules give anyone, even people who are not users of your app,
// read and write access to your database
{
"rules": {
".read": true,
".write": true
}
}
Read the other samples on the page I linked to find one that suit your needs.
EDIT
To access the rules go to your console (make sure you're logged in Google) and select "Database" in the sidebar menu, then click on the "rules" tab. The url should be something like https://console.firebase.google.com/project/<your-project>/database/rules

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.

What is the most secured way to check if a user is already logged in?

I have read many questions like my question title, none of them give me a solution.
I am implement a website (using struts2 framework) and I dont know what is the most secure way to check if user is already logged or not. My site has the payment feature, so I should really be careful about this.
All the solution I have read are similar like this:
// Is there a "user" object stored in the user's HttpSession?
Object user = session.getAttribute (USER_HANDLE);
if (user == null) {
// The user has not logged in yet.
}
else {
// the user has logged in
}
I was wondering is there any chance some bad guys can create a fake session object like the user object and then can logged in the system without a valid password?
I also want to know is it practice way, at every required logged in page, not just check the user object is not null, but also check the username and password in the database?
Maybe you should use a security framework like spring security or Apache Shiro.
Security issues are always based on your requirements, in simple which kind of security you want ,because there are various layers of security regarding web. But as you have mentioned, This you can achieve using Struts2-Interceptors, because It provides you terminology to perform some essential operation before and after your action is called.For example refer this link.