Once I have a principal logged in, how can I obtain all roles for a user?
I'm creating a Java EE 6 application, and I'm writing a JAX-RS service to return all the roles for the current user, which will be consumed by a front-end to properly render the screen.
I know that there are multiple interfaces that can return whether the user is a member of a certain role, but what I want is a interface that would allow me to get all roles for that particular user.
Given that all the role names are known at compile time, you can do something like the following :
public final class SecurityRoles {
static final String USER_ROLE = "user";
static final String ADMIN_ROLE = "admin";
static final String SUPPORT_ROLE = "support";
}
and
#DeclareRoles({
USER_ROLE,
ADMIN_ROLE,
SUPPORT_ROLE
})
#Path("/rest")
public class SomeRS {
#Context
SecurityContext securityContext;
#GET
#PermitAll
#Produces(MediaType.APPLICATION_JSON)
public List<String> lookupUserRoles() {
return Arrays.stream(SomeRS.class.getAnnotation(DeclareRoles.class).value())
.filter(roleName -> securityContext.isUserInRole(roleName))
.collect(Collectors.toList());
}
}
which tests to see if the user is in each of the known roles before adding the role name to a list that is returned.
Note that if you do not use #DeclareRoles then the roles used by the application must be declared in either the web.xml or application.xml files (and you will need to declare the names in a String[] array somewhere).
Related
Is it possible to use API instead of following sql query for user authentication in openfire properties:
jdbcAuthProvider.passwordSQL: SELECT username FROM
chat_authentication WHERE username=?
Basically, the chat_authentication table in our mysql database is not functioning properly and hence some users' entries are not there in the table. So I want to hit the API(which has very low failure rate) directly. How can I do that in this case?
You have to create your own class to substitute DefaultAuthProvider.class of Openfire.
Can looks like:
import org.jivesoftware.openfire.auth.AuthProvider
public class MyAuthProvider implements AuthProvider
and implements correctly all the methods.
As alternative you can extends OF's DefaultAuthProvider and override all the methods
public void authenticate(String username, String password) throws UnauthorizedException
public void authenticate(String username, String token, String digest) throws UnauthorizedException
getPassword(String)
public boolean checkPassword(String username, String testPassword) throws UserNotFoundException
public void setPassword(String username, String password).
Finally, make a jar of your class, deploy it in openfireDirectory/lib and change the value of property
provider.auth.className
with your MyAuthProvider fullname.
You can do it
by Admin Console Panel -> Server -> System Property
or by database updating OfProperty table.
After that, you'll must shut down and start Openfire.
I have an entities like this:
Restaurant
String name
User manager
User
String name
Date lastLogin
When I do GET /restaurants I want to inline the manager, but only with name, not with lastLogin.
When I do GET /users I want to see the full user: name + lastLogin
So I created a Restaurant-Projection and applied it as excerpt to the RestaurantRepo. But this embeds the full user into the restaurant.
When I create an excerpt project for user too, which omits the lastLogin field then it works for restaurants as expected but not for users because here the lastLogin is missing.
How can I solve this problem?
Thank you
You can do something like this (example from the spring data rest documentation)
#Projection(name = "virtual", types = { Person.class })
public interface VirtualProjection {
#Value("#{target.firstName} #{target.lastName}")
String getFullName();
}
So in your case this would result into this projection:
#Projection(name = "restaurantWithManagerName", types = { Restaurant.class })
public interface RestaurantWithManagerNameProjection {
String getName();
#Value("#{target.manager.name}")
String getManagerName();
}
If you want to keep the orginal structure with a nested User object you could achieve this by creating a custom reduced interface for the user and use it in your projection:
public interface UserLight {
String getName();
}
#Projection(name = "restaurantWithReducedManager", types = Restaurant.class)
public interface RestaurantWithManagerNameProjection {
String getName();
UserLight getManager();
}
I use ASP.NET SimpleMembership..
My scenario;
The user login and then I change IsConfirmed column to false on webpages_Membership table..
And the user try to change page, the login page seems to the user..
Your most sensible options are to use any of the authentication related steps in Global.asax.cs, or to derive from AuthorizeAttribute. Given that non-confirmed users are going to have to get to somewhere (for example in order to confirm their account) then you probably don't want the former. With either approach their next request will get denied.
Therefore, I would just extend your [Authorize] attribute to do something like the following, and just use that in the appropriate Controllers and Actions instead of [Authorize] (I'm assuming C# as you didn't specify language in your tags):
public class AuthorizeIfConfirmedAttribute : AuthorizeAttribute {
protected override bool AuthorizeCore(HttpContextBase httpContext) {
if (!base.AuthorizeCore(httpContext)) return false;
System.Security.Principal.IIdentity user = httpContext.User.Identity;
return WebMatrix.WebData.WebSecurity.IsConfirmed(user.Name);
}
}
[AuthorizeIfConfirmed]
public class MyController { ... }
(If you want to use a custom property on your UserProfile class instead of IsConfirmed then you can simply adjust this code accordingly).
The advantage of this approach is that it keeps all your authorization logic in the usual place, and you can also combine it with role enforcement, e.g.:
[AuthorizeIfConfirmed(Roles = "admin")]
public class MyController { ... }
Note that if you use WebApi or SignalR you may have to include these checks in however you are performing request authorization for the apis as well.
I user Application_AuthenticateRequest in Global.asax.. Because my application needs authenticate on all pages..
protected void Application_AuthenticateRequest()
{
if (WebSecurity.IsAuthenticated)
{
bool isConfirmed = (..your codes here..)
if (isConfirmed == false)
{
WebSecurity.Logout();
}
}
}
Our old software architecture used role based validation. We now want to use claims based authorization. As a matter of fact, I think we always used something modelling claims, even if we used role base technology.
The lowest level are Privileges. A privilege may be "invoke the user service adding a user" or short "UserService.Add". Privileges can be assigned to groups. Users can be members of groups. In the end, through group membership, a user can have a list of privileges.
The old system used a combination of UserNamePasswordValidator, IAuthorizationPolicy and CodeAccessSecurityAttribute to have attributes that were written above the service method and on call of the service method, the validity would be checked. If the user didn't have the required privilege, access would be denied. Worked great.
[CompanyRoleRequired(SecurityAction.Demand, Role = "Common.Connect")]
[CompanyRoleRequired(SecurityAction.Demand, Role = "SomeServiceName.Save")]
public void Save(IEnumerable<Data> data)
{
// code
}
Now I'd like to use claims based authorization. Keeping the model above, I would create either a claim for each former privilege, or maybe a claim for each service with valid values of it's operations. For example, instead of "UserService.Add" I could add a claim "UserService" and people with the former privilege would get the claim with the value "Add". I would like to offer the service developers the same ease of access checking, so I'd like the required claims to be annotated above the service method. Microsoft already provides a ClaimsPrincipalPermissionAttribute for this.
Instead of implementing IAuthorizationPolicy, I implemented ClaimsAuthorizationManager.
Question 1) The authorization manager gets called twice. Once with the soap url and once with my attribute. I've googled a lot and it seems to be by design. I don't have a problem differentiating between the calls and checking only my calls, but maybe I didn't see something. Is there an option or an easy way to not get called on soap calls with the urls and only getting called for the attributes?
Question 2) The access check offers the ability to check if the pricipal has a claim. Obviously, a claim has a type/name and a value. I would have expected the attribute to offer such an interface. However, the attribute wants to know about the resource and operation. The access check function I need to overwrite also needs to check resources and operations. Why is that? Do I need to map resource/operation to claims in my AuthorizationManager? And if I don't see any need for it, would it be ok to just put the expected type and value of the claim in the attribute as resource and operation and map them 1:1 in the authorization manager? Or do I miss out on some important security feature if I do this?
Q1) That's unfortunately the case - and since both the "automatic" calls and the attribute/.CheckAccess use the same claim types you cannot easily distinguish between the two. I wrote about that here: http://leastprivilege.com/2011/04/30/what-i-dont-like-about-wifs-claims-based-authorization/
Q2) You are missing the concept here. The idea is to NOT check for specific claims - but to rather annotate the code with "what you are doing". The person that writes the business code typically does not know exactly who is allowed to call it (or which claims are exactly needed). You only tell the authZ poliy that you are about to add a customer (as an example). The authorization manager's job is to figure out if the principal is authorized to do that (by whatever means). Separation of concerns. See here: http://leastprivilege.com/2011/04/30/what-i-like-about-wifs-claims-based-authorization/
Not sure if this is going to be helpful to you but ClaimsAuthorizationManager has method that can be overridden (LoadCustomConfiguration) that you can use to load your policy from XML file. That policy might be designed in a way to allow mapping between resources and actions and roles. I've built in-code access control list instead that looks like this:
public interface IAccessControlList
{
List<CustomAccessRule> Rules { get; }
}
public class CustomAccessRule
{
public string Operation { get; set; }
public List<string> Roles { get; set; }
public CustomAccessRule(string operation, params string[] roles)
{
Operation = operation;
Roles = roles.ToList();
}
}
My claims authorization manager looks like this:
public class CustomClaimsAuthorizationManager : ClaimsAuthorizationManager
{
private IAccessControlList _accessControlList;
public CustomClaimsAuthorizationManager(IAccessControlList accessControlList)
{
_accessControlList = accessControlList;
}
public override bool CheckAccess(AuthorizationContext context)
{
string operation = context.Action.First().Value.Split('/').Last();
CustomAccessRule rule = _accessControlList.Rules.FirstOrDefault(x => x.Operation == operation);
if (rule == null) return true;
if (context.Principal.Identities.First().IsInRoles(rule.Roles)) return true;
throw new MessageSecurityException(string.Format("Username {0} does not have access to operation {1}.", context.Principal.Identities.First().Name, operation));
}
}
And here is an example of one access control list implementation for one service:
public class SampleServiceACL : IAccessControlList
{
public List<CustomAccessRule> Rules { get; private set; }
public SampleServiceACL()
{
Rules = new List<CustomAccessRule>();
Rules.Add(new CustomAccessRule("OpenAccount", "Manager", "Owner"));
Rules.Add(new CustomAccessRule("CloseAccount", "Manager", "Owner"));
Rules.Add(new CustomAccessRule("SendEmail", "User", "Manager", "Owner"));
}
}
And I'm applying this at service host base level by using:
protected override void OnOpening()
{
base.OnOpening();
IdentityConfiguration identityConfiguration = new IdentityConfiguration();
identityConfiguration.SecurityTokenHandlers.Clear();
identityConfiguration.ClaimsAuthorizationManager = new CustomClaimsAuthorizationManager(new SampleServiceACL());
this.Credentials.IdentityConfiguration = identityConfiguration;
...
}
As a result, I'm not using attributes at all, all authorization logic is centralized in claims authorization manager over ACL.
Now if you don't like this approach, and you're still in pursuit of attribute that will check for specific claims, you can then derive from CodeAccessSecurityAttribute and actually implement that logic. What is given by MS out of the box is good, but it does not mean you should stick to it by any means. Also logic for checking the claims can be implemented as an extension to identity, i.e.:
public static class IdentityExtensions
{
public static bool IsInRoles(this ClaimsIdentity id, List<string> roles)
{
foreach (string role in roles)
if (id.HasClaim(ClaimTypes.Role, role)) return true;
return false;
}
}
So you might build extensions, custom attribute, and then use extensions in the attribute to perform your validation logic.
Again, this is just something that I've already done. Might not be what you're looking for but it's one type of custom solution.
I'm building an authentication module for my application and I don't quite understand the relation between CWebUser and CUserIdentity.
To set the user id to Yii::app()->user->id I have to do that in my UserIdentity class and create a method:
public function getId() {
return $this->_id;
}
But to set isAdmin to Yii::app()->user->isAdmin I have to create a method in my WebUser class:
function getIsAdmin() {
$user = $this->loadUser(Yii::app()->user->id);
return intval($user->user_level_id) == AccountModule::USER_LEVEL_ADMIN;
}
Why can't I just create the methods the UserIdentity class? What is the division of labour here?
The UserIdentity (UI) class is like an ID card, where as the WebUser class is the actual person plus everything you know about them.
The UI class gives you authentication via database, webservices, textfile, whatever. It lets you know what the key attributes are and allows you to manipulate them. The user however can give you more information about what they're allowed to do, there names, granular permissions and such.
OK, end metaphor
The UI class holds the key information, so when asking for the users ID it will refer to the User Identity class to get the Identifier for the user.
Anything that isn't related to identifying or authenticating a user is in the WebUser class
Clear it up at all?
Your example
You gave the getId function as an example, but that can be created on WebUser to override the default, which is to pull from the state.
So not sure what you mean here.
I like how the accepted answer used real life examples to make it easier to understand. However, I also like how Chris explained it here with example.
User information is stored in an instance of the CWebUser class and
this is created on application initialisation (ie: when the User first
connects with the website), irrespective of whether the user is logged
in or not. By default, the user is set to “ Guest”. Authentication is
managed by a class called CUserIdentity and this class checks that the
user is known and a valid user. How this validation occurs will depend
on your application, perhaps against a database, or login with
facebook, or against an ldap server etc...
And what is the benefit of using all those classes? I can do everything just by User model. If I set scenario "login", password will be checked during validation. If validation is OK, I can set to session my own variable like this:
$model = new User("login");
$model->attributes = $_POST["User"];
if ($model->validate())
{
Yii::app()->session["currentUser"] = $model;
}
else
{
// .. show error
unset(Yii::app()->session["currentUser"]);
}
In User model I have then static methods to check this variable
public static function isGuest()
{
return isset(Yii::app()->session["currentUser"]);
}
public static function getCurrent()
{
return Yii::app()->session["currentUser"];
}
And I can call it very shortly:
User::isGuest();
$model = User::getCurrent();
// instead of writing this:
Yii::app()->user->isGuest;
So why should I use so complicated hierarchy of classes that is suggested by Yii? I never understood it.