wso2 IS 520 user accountDisabled claim verify as 'admin' - java

Is there a way to verify a multi-tenant environment USER account is enabled or disabled using WS ?
getUserClaimValue
IS the only one I could see !, unfortunately it asks for User credentials !
Cant we do it at admin level ?
Its not even storing into ldap-attributes. How can I get this verified as super-admin.
Claim URI :
http://wso2.org/claims/identity/accountDisabled
Worked out to get the claim as 'ref'.
How to get the value from this 'ref' direct using LDAP with JAVA ?

Any claims which has the pattern http://wso2.org/claims/identity/XXXXX is considered as a special claim. Hence they are ignored by getUserClaimValue (and by setUserClaimValue when setting value).
You'll need to use either getUserClaimValues or getUserClaimValuesForClaims for the above purpose (And setUserClaimValues to set).
Update
Due to the tenant separation model it is not allowed to get claim details by other tenant admins (Even for super tenant admin). In case you really need that, one possible option would be to write a custom admin service extending the org.wso2.carbon.um.ws.service.UserStoreManagerService class (which reflects RemoteUserStoreManagerService) where it will start a tenant flow for the user's tenant, and call super class method to get the claim value.

Related

Spring Boot - make sure data belongs to current logged in user

I have a Spring Boot REST API that I'm building. Im slightly stuck on the correct way to design my API in a way that protects each individual users' data. For example, consider the following database relations:
User -> (Has Many) Projects -> (Has Many) Tasks. (A User has-many Projects, and a Project has-many tasks).
For example, if I design my endpoints in the following way:
GET /api/v1/projects/{projectId}
POST /api/v1/projects/{projectId}/tasks
Just as a simple example for the above, how can I make sure, when creating new tasks for a certain project, that the project belongs to the logged in user?
Currently, I am using JWT tokens via Spring Security as my authentication strategy, and included in the payload of the token I have my Users' id. So with every request I can retrieve the user, but surely that's incredibly inefficient to be making so many requests to the database and check if the user actually has a given project.
Some solution I was thinking about is to simply have endpoints designed like this:
/api/v1/users/{userId}/projects/{projectId}/tasks
And then I can use the user id in the JWT payload and compare it to the user id in the request parameter. But then that would mean with every new relation in my database, the length of the url is going to be massive :) Also I guess it would mean all the business logic would be inside the User service for the whole application, right? Which seems a little odd to me... but maybe I'm wrong.
Im not sure if thats an issue or not, but just trying to design the API to be as elegant as possible.
Thanks again!
Checking if the user has permissions to a project on every request is the correct solution. Consider cases when many other applications / users are calling your API. You want to make sure that your API is as secure as possible and cannot be manipulated from the frontend.
To make it more efficient you should have a way/query to check associations in your database like a simple query that returns true/false which should be quicker than retrieving all the data and comparing in Java code.
And when possible combine multiple database queries into one, like for one of your examples:
GET /api/v1/projects/{projectId}
in this case, don't run a query to get a user's information and a query for the requested project. Instead you could do a single query with a join between the user's table and the project table which should only return a project if the user is associated with it. The best way really depends on how your database is structured.
Adding a user id into the API URL is just redundant information. Just because the user id in the token matches the user id in the URL doesn't mean the user has any kind of permissions to any project.
Another solution to be avoided is to include the user's project ids in the JWT token which you can then compare without making a database request. This is bad for several reasons:
The token should only have required information for the user to access the API, it shouldn't have business logic
Depending on how much business logic you store in the token the token can become large in size. See this post for a discussion on size limits: What is the maximum size of JWT token?
If there is a way for the someone other than the user (like admin) to add/remove a user's association to a project then that change will not be reflected in the token until the token's data is refreshed
EDIT:
On the spring side I have used the #PreAuthorize annotation before to handle these types of method checks. Below is pseudo code as an example.
#RestController
public class MyController {
#PostMapping
#PreAuthorize("#mySecurityService.isAllowed(principal, #in)")
public SomeResponseType api1(SomeRequestType requestData) {
/* this is not reached unless mySecurityService.isAllowed
returns true, instead a user gets a 401/403 HTTP response
code (i don't remember the exact one) */
}
}
#Service
public class MySecurityService {
/*
Object principal - this is spring's UserDetails object that is
returned from the AuthenticationProvider. So basically a Java
representation of the JWT token which should have the
user's username.
SomeRequestType requestData - this is the request data that was
sent to the API. I'm sure there is a way to get the project ID
from the URL here as well.
*/
public boolean isAllowed(Object principal, SomeRequestType requestData) {
/*
take the user's username from the principal, take the
project ID from the request data and query the database
to check authorization, return true if authorized
make this check efficient
*/
return false;
}
}
The annotation and the security service can then be applied to multiple methods. You can have many different security services depending on what your are checking.
There are other ways available too https://www.baeldung.com/spring-security-method-security and this has to be enabled in spring's configuration (also explained in the link).
Hi so if I understood it correctly you want to automatically assign the task that is going to be created with "POST /api/v1/projects/{projectId}/tasks" to the current logged in user.
You could try to add a Parameter 'Principal principal' to your rest controller. The Principal is the user that is sending the request.
After you have your Prinicipal, you could write a simple convert method(for example: convertPrincipalToUser(Principal principal) which returns you the user. Finally you can add your user to the corresponding task)
Here is some more information about it:
https://www.baeldung.com/get-user-in-spring-security

Search Filter needed to find a user with networkID in Active Directory

Updated 5/28/2019
I'm using ActiveDirectoryLdapAuthenticationProvider from org.springframework.security.ldap.authentication.ad and searchForUser method is able to find the user by email.
I'm using the default searchFilter: (&(objectClass=user)(userPrincipalName={0})).
But it doesn't work if networkID is provided as username. So:
employee#PublicCompanyEmail.com works fine
employee_AD_username#internaldomain.com doesn't work
Appreciate any ideas on it!
Har har, you tripped into the eUPN vs. iUPN issues. Your company works with UPN suffixes which creates a virtual domain with a virtual enterprise UPN for each user stored in the userPrincipalName field. As soon as the implicit UPN (Kerberos principal) is overridden with the enterprise one, you are out of luck.
You may want consider something better than nagging your users with username and password over and over again...at least on Tomcat you can have this if you can live with <security:jee> in Spring Security.
A little bit of terminology first
Security Account Manager (SAM) Name
The networkID you use to login to the network.
User Principal Name (UPN)
It may be Implicit UPN (iUPN) or Explicit UPN (eUPN).
An example for iUPN would be: networkID#internalDomain.com
An example for eUPN would be: employee_name#companyName.com
eUPN may be defined by network administrator.
In my case, the UPN we're using in our AD is actually an eUPN.
Search Filter Syntax
This is query language for AD.
We used it to define the filter while searching for objects in AD.
{0}-occurrence means full username with domain in it. If the domain is defined in LDAP configuration then Spring Security checks if it's present in the entered username to login. If not, then it'll be added.
{1}-occurrence means whatever entered as username. So, Spring won't do any modification on the provided username.
If you want to be able to login without providing domain name, you need to define the domain in LDAP configuration
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(
"domain",...);
Then if it's the domain used in email address, this filter:
(&(objectClass=user)(userPrincipalName={0}))
will find the user with and without the domain name.
Then if the configured domain is internal-domain, this filter:
(&(objectClass=user)(sAMAccountName={1}))
will find the user if the username provided is networkID with no doamin.
If you don't define the domain for LDAP configuration and leave it null while instantiating the object, then you should be able to search for both UPN and sam -account with {1} occurrence but you have to provide the domain for both networkID and email-username while on login.

EJB authentication

Here is what I'm trying to do: I have an authentication EJB that can grant user a "ticket" (pair of key and token) by validating username and password. Clients should pass the ticket every call to remote EJB and such ticket should be able to be fetched by EJB (method, or interceptor) and EJB/ or interceptor should validate the ticket and determine whether the call is valid or not.
I don't want to add ticket as parameter to each function that requires authentication, and I believe there should be a way to implement this. I've looked through several articles about JAAS custom login module, but still can't find a non-vendor specific way to do this. (And I am trying to avoid vendor specific implementation)
If JAAS can't do the job, is there anything like "header" in EJB?
Couldn't you just use roles to perform this authorization? Instead of granting a ticket to a user, assign him a role.
Then, it's just a matter of using the inbuilt functionality of checking whether a user is in a role or not.
Although I agree with #EdH, i.e. use #RunAs, you can accomplish what you want by adding to the EJB context your token.
Red Hat does something similar here by using the interface EJBClientInterceptor.
By looking the code of ReceiverInterceptor (which implements the EJBClientInterceptor) you can see how to modify the EJB context (on the client-side) and add your token:
context.setReceiverInvocationContext(new
EJBReceiverInvocationContext(context, receiverContext));
context.sendRequest();

Adding role based access for URLs

I am working on a legacy (struts 1.1 running in jdk 1.4 , tomcat 6)application and need advice for implementing user role based security.
A user u1 has a read/view permission while user u2 has write permission on certain action. E.g
Url for user u1 :
http://www.somedomain.com:8080/app?key=12
(It shows the content related with key 12 from DB).
Url for user u2 :
http://www.somedomain.com:8080/app?key=12&note=some note test
(It basically insert note value in DB for key 12)
Suppose if user u1 who has view rights, come to know the url used by u2, he can insert any malicious value for particular key, which he is not suppose to do.
Even though role based access to struts action class is in place , here the action class used by both users are same and only difference is url parameter.
Now I have to fix this issue, which is spread across thousands of action classes.So adding checking conditions in each and every action class will not be feasible.
I am thinking of writing a filter class which will read user role and allowed request parameter(with possible values like action='save' action='view') from a configuration file.
Are there any alternative solution approach?
your best choice is to modify the action class and implement some check inside called method (you can mixup container role-based permissions)
public void perform(HttpServletRequest request)
{
String note = request.getParameter("note");
if(!request.isUserInRole("writer") && note != null) throw new SecurityException("not allowed");
...
}
Without knowing much about your application, but I would try to apply java declarative security for my role based solution as much as possible.
If it is easy for you to use the java ee declarative security then go for it.
It is simple, flexible and using standards which will give you the safety you request and the ability to port your solution to different java web server providers.
Maybe a url rewriter (apache in front of the web application can help to reorganize); can split the destinations, and for that in your java web server set the url patterns which will expect different user roles for the read/view and update/write grantings permissions.
This will need some few changes to achieve, but you would definitely not need to change your 4k codebase and you will by this reach a clean solution.
Search for e.g. setting up role based security or java declarative security
some reading with demo...
http://www.thecoderscorner.com/team-blog/hosting-servers/17-setting-up-role-based-security-in-tomcat#.Us0eShoeK-Y

JAAS additional LoginModules

I'd like to know how to combine these two authentication steps :
check the user/password in an LDAP
add principals (roles) found in a DB to the subject.
The LDAP user repository have no idea about application-specific roles and I don't want to manage the passwords in the application DB. So I need both.
JAAS configuration file allows to have additional LoginModules :
<name used by application to refer to this entry> {
<LoginModule> <flag> <LoginModule options>;
<optional additional LoginModules, flags and options>;
};
but I can't find example that explains how I works.
Is it the good method ?
Thanks
=========================================
Here is my answer :
Indeed we can have additional LoginModules. The JAAS configuration file is :
Sample {
com.sun.security.auth.module.LdapLoginModule Requisite
userProvider="ldap://acme.org:389/OU=Users,OU=_ACME,DC=acmegis,DC=acme,DC=org"
authIdentity="{USERNAME}"
userFilter="(userPrincipalName={USERNAME})"
storePass=true
sample.module.SampleLoginModule required debug=true;
};
Here we have two LoginModules :
The Sun's LdapLoginModule that checks user/password,
and mine sample.module.SampleLoginModule that query my db and fills the principals.
The important parameter is storePass=true that asks the LdapLoginModule to store the username and password in the module's shared state. (see http://docs.oracle.com/javase/6/docs/jre/api/security/jaas/spec/com/sun/security/auth/module/LdapLoginModule.html).
So the next LoginModules can get the username passed to the initialize method in the sharedState Map argument. They should have nothing to do in login() and the query in DB to fill the Principales is done in commit() (like Shimi Bandiel said).
I don't use it yet but there is a DatabaseServerLoginModule developed by JBoss (see http://community.jboss.org/wiki/DatabaseServerLoginModule) that supports authentication and role mapping. Used with password-stacking=useFirstPass we should have the answer to my need without write any line-code (but a beautiful JAAS configuration file).
B.R.
You should implement a LoginModule which in the login method you access the LDAP and check username/password and in the commit method you access the DB and fill the principals.
There is no need here to use multiple LoginModule
It is great!
But implement the LoginModule give you more power to customize the way you interact with LDAP server.
I also struggle the same problem as you.
But remember when implement the LoginModule, you should add the role in login() function , not in commit(), otherwise your subjet will not get the principal.

Categories

Resources