#Auth Injection in ContainerFilter - authentication

I'm using DW 0.9.1 and it would be cool, if I could inject the #Auth XYzObject into some ContainerRequest or even better in a ContainerResponseFilter (or servlet filter).
Does anyone knows if this is possible?
The usecase: Some users does have different allowd access rates (rate limiting), e.g. max. 2 request per second and max 60 per Minute. This can be verified with the injected #Auth XYzObject.
In the end I can do this also in the Ressource, where this information is available, but as I said it would be cool to do this outside of my ressources in a filter or something else. And I do not want to do this is the authenticating/ authorization process, because rate limiting is not related to this. At the moment,all the variants I tried, nothing works, so it seems not possible, but I hope someone knows the trick.

How the #Auth annotation works is that it is handled by a ValueFactoryProvider, which is used only for (resource) method parameter injection. So you can't inject it into arbitrary locations.
However, when you created XyzObject you made it implement java.security.Principal. The reason DW makes you use this type, is because after it authenticates, it sets the Principal in the SecurityContext, as seen in the AuthFilter.
If you look at the implementation for AuthValueFactoryProvider, you will see that the way it obtains the Principal is by getting it from the SecurityContext. And that's how the Principal is injected with #Auth as a method argument.
In a ContainerRequestFilter (and in may other locations), you have access to the SecurityContext. In a filter you can get it with requestContext.getSecurityContext(). So in your filter you can get the Principal from the SecurityContext and just cast it
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
Principal principal = requestContext.getSecurityContext().getUserPrincipal();
if (principal != null) {
XyzObject xyz = (XyzObject)principal;
}
}

Related

A simple exchange for using usr/pwd from another backend in Aspnetcore2.2

How do I create a simple aspnetcore(2.2)+ solution that uses a backend to only authenticate users?
I should not manage users and I can specify the API so it should have, hopefully, only 1 method IsAuthenticated(email,password).
I started out with the boiler plate
services.AddDefaultIdentity<MyIdentityUser>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddUserStore<MyUserStore>();
with the simplest possible implementation of
MyIdentityUser and
MyUserStore : IUserStore<MyIdentityUser>, IUserPasswordStore<MyIdentityUser>, IUserEmailStore<MyIdentityUser>
but it does too much as I had to do (faux) implementations of FindByNameAsync, GetPasswordHashAsync, GetUserIdAsync, GetUserNameAsync and more.
I guess it is the AddDefaultIdentity method that is to blame (well... it is me to blame really as I still see me as superior to computers) as I guess the "Default" in the method name means that I will have a backend that manages everything.
I have read MSDN:Introduction to Identity on ASP.NET Core and Configure ASP.NET Core Identity but they are either too oriented around replacing EF-and-everything or my reading-docs-skillz are not good enough. Similarly I have scoured the internet but it seems my google-fu is not strong enough.
UPDATE
Unmentioned above I especially had to implement GetPasswordHashAsync which should return the same hashing algorithm as is used when hashing the user input (viewmodel). If I can override that hashing algorithm I can either send plain text to the backend (hmm) or ask for the algorithm and implement it myself (better).
As it is now GetPasswordHashAsync has to return a hash in a special format with a leading character telling which of two algoritms was used.
Is the solution to override (how) the algorithm used for the viewmodel? If so, how?
I see articles about setting a new PasswordHasher for a UserManager but I cannot get my head around how to inject it into the flow.
I think it is not the responsibility of IUserPasswordStore to hash the password, so you don't need to put your hash algorithm there. The responsibility of IUserPasswordStore is only how to set and get the hashed password from your Identity User (MyIdentityUser).
Take a look at the implementation of GetPasswordHashAsync in the UserStoreBase, it is simply return the user.PasswordHash, that's all.
https://github.com/aspnet/AspNetCore/blob/bfec2c14be1e65f7dd361a43950d4c848ad0cd35/src/Identity/Extensions.Stores/src/UserStoreBase.cs
So if you implement IUserPasswordStore it does not mean that you have to have your own Password Hasher.
The one that responsible for hashing the password is IPasswordHasher. If you want to have your own Password Hasher you can implement it yourself.
public class MyPasswordHasher : IPasswordHasher<MyIdentityUser>
{
public string HashPassword(MyIdentityUser user, string password)
{
...
}
public PasswordVerificationResult VerifyHashedPassword(MyIdentityUser user, string hashedPassword, string providedPassword)
{
...
}
}
For the default password hasher you can find it here,
https://github.com/aspnet/AspNetCore/blob/bfec2c14be1e65f7dd361a43950d4c848ad0cd35/src/Identity/Extensions.Core/src/PasswordHasher.cs
And register it for DI in startup.cs, so that the UserManager will be using your own custom Password Hasher. Or in other word this will inject your Password Hasher into the flow.
services.AddScoped<IPasswordHasher<MyIdentityUser>, MyPasswordHasher>();
And also take a look at the UserManager class, this is where the IUserPasswordStore and IPasswordHasher interacting. Inside the UserManager you'll find the following code
passwordStore.SetPasswordHashAsync(user, PasswordHasher.HashPassword(newPassword)).WithCurrentCulture();
The function signInManager.PasswordSignInAsync does take username and password and logs you in. It takes two more fields (bools), the first is "is persistent" which you can mark as false in your case and the second is lockout. This returns SignInResult which you can then use to check if the login was successful by using result.Succeeded.
var result = signInManager.PasswordSignInAsync(username, pass, true, true);
return result.Succeeded;

Liferay custom single-sign-on with redirect and parameters

this is my first question here and it's quite tricky as i didn't find enough relevant resources on the web. So I really hope, to get some help with this:
I am doing a custom single-sign-on with Liferay 6.2 GA4. Therefore I have developed a custom login-hook, that can handle my URL that looks like:
http://localhost:8080/c/portal/login?q=10C7vCMqv%2BlYThuxjdOmbUIXj1LKz9W3s5IUg%2F8H%2FvqRPUGOuzoC7pRT4hwVp2TpLf%2FnDRaGfpvoubhvSxlhidyX1SAowlvhdeWb95xRyxyCGZmKxE%2FZejk%2BIS5PvVHYIprBmM5Ec1cM%2Fq5dd5OGpEJJislrctRP
From this i decode the q-parameter to get the login parameters and other parameters, that i need to decide on which page I get redirected and i pass the attribute to the request
request.setAttribute("myParam", recordId);
and
return credentials;
I have also a LoginPostAction, that gets called afterwards and here it is, where it gets tricky:
public final void run(final HttpServletRequest request, final HttpServletResponse response)
throws ActionException {
...
final PortletURL redirectURL = PortletURLFactoryUtil.create(
request, "portlet_WAR_myportlet",
>>>> PortalUtil.getPlidFromPortletId(???, "portlet_WAR_myportlet"),
PortletRequest.RENDER_PHASE);
redirectURL.setParameter("myParam", String.valueOf(request.getAttribute("myParam")));
response.sendRedirect(redirectURL.toString());
}
So, I have the portlet name (PortletId) but I cannot get the Plid from this, as i don't have the ThemeDisplay at this time.
First question: How can i create a PortletURL at this time, which i can use in sendRedirect()?
Second: I have also tried to setAttribute and hardcode the sendRedirect("/urlToMyPortlet"), but I cannot use this at this time anymore as it gets lost afterwards (and is null) when i try to get it on the next page.
Any suggestions?
Thanks a lot in advance,
rom12three

WCF Data Service authorization policies

I'm using the WCF Data Service and i need to implement authorization policies.
The polices are dynamic and are stored into a table that contains the target table,
the field and the allowed value.
In order to achieve this, I override the OnStartProcessingRequest method
of the DataService but I try to change the RequestUri I run into "Unauthorization" problem.
There is a way to change the RequestUri parameter in OnStartProcessingRequest method?
this code generate the exeption
protected override void OnStartProcessingRequest(ProcessRequestArgs args) {
Uri uri = new Uri(args.RequestUri + "?$filter=Id eq 3");
args.RequestUri = uri;
}
I can't use the Interceptor because the system is dynamic and entites are unknown.
Currently the adopted solution is to apply filters in client application (html5/js)
and verify the filtering parameters on server (into the OnStartProcessingRequest).
I wonder if there is a way for me to add filter parameters in OnStartProcessingRequest
or any way that can fix this problem.

Multitenant/Shared Application system, how to maintain multiple tentant-specific identifiers?

I have a multi-tenant system where each tenant shares the same instance of the codebase, but has their own databases.
I'm using RavenDB for persistence, with a standard c# facade/BLL backend wrapped with Asp.net WebAPI, and I'm finding that at every lower level operation (deep within my business logic classes) that touch the datbase, I need to pass in an identifier so that my RavenDb client session knows which database to operate against.
When the user authenticates, I resolve the appropriate database identifer, store it in the session manager. Every call against the Web API layer passes in a session ID which resolves the database ID in the backend, which is then used to pass into every single facade/BLL call.
All my dependencies are handled via an IoC container at the WebAPI level, but i can't pass in the database ID at this phase because it can be different for every user that is logged in.
this, of course is getting tedious.
can someone give me some guidance as to what I can do to alleviate this? Maybe perhaps some sort of policy injection/AOP solution?
a rough sample of my backend code looks like..
public class WidgetService()
{
private WidgetBLL _widgetBLL;
private ISessionManager _sessionManager;
public WidgetService(WidgetBLL _widgetBLL, ISessionManager sessionManager)
{
_widgetBLL = widgetBLL;
_sessionManager = sessionManager
}
public Widget getWidget(string sessionId, string widgetId)
{
string DbId = sessionManager.ResolveDbId(sessionId)
return _widgetBLL.GetWidget(string dbId, string widgetId);
}
}
public class WidgetManager()
{
public GetWidget(string dbId, string widgetId)
{
using (IDocumentSession session = documentStore.OpenSession(dbId)
{
var widget = session.load<Widget>(widgetid);
}
return widget;
}
}
the DBID is the identifier for that particular tenant that this particular user is a member of.
You need to change how you are using the session.
Instead of opening and closing the session yourself, do that in the IoC code.
Then you pass a session that is already opened for the right db.

Apache Shiro: Exception-Handling with Multiple Realms

We are using two realms (one for hashed passwords, the other one for generated plaintext keys) - this is working as expected.
With a single realm, we could throw a DisabledAccountException exception in our realm's protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken authToken) and explicitly catch such an exception in our application.
Now that we have two realms, all exceptions are Shiro-internally caught; so if one realm fails, the second one can be tried as well. However, this kind of redirect will only throw generic AuthenticationExceptions to our application.
Is there any workaround with multiple realms so that we can have more specific exceptions (to know if an account is locked, the credentials are simply wrong,...)?
You need to specify your own AuthenticationStrategy in your ModularRealmAuthenticator.
The ModularRealmAuthenticator uses AtLeastOneSuccessfulStrategy by default and AtLeastOneSuccessfulStrategy ignores the exceptions and keeps trying to login the users using all the realms available.
We had a similar scenario on the tynamo project and to workaround this issue I've implemented my own AuthenticationStrategy, called FirstExceptionStrategy, that works with multiple realms and throws the first exception it gets. This approach works fine as long as there is only one Realm per Token type.
The implementations is rather simple:
/**
* {#link org.apache.shiro.authc.pam.AuthenticationStrategy} implementation that throws the first exception it gets
* and ignores all subsequent realms. If there is no exceptions it works as the {#link FirstSuccessfulStrategy}
*
* WARN: This approach works fine as long as there is ONLY ONE Realm per Token type.
*
*/
public class FirstExceptionStrategy extends FirstSuccessfulStrategy {
#Override
public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException {
if ((t != null) && (t instanceof AuthenticationException)) throw (AuthenticationException) t;
return super.afterAttempt(realm, token, singleRealmInfo, aggregateInfo, t);
}
}
I repeat, this only works if there is ONLY ONE Realm per Token type.
For more info about my particular scenario see here: http://jira.codehaus.org/browse/TYNAMO-154