Dynamically populate authorize attribute - asp.net-mvc-4

I'm using windows authentication with no roles setup, I simply have some admin names stored in a table that I want to check against in combination with the authorize attribute. I don't have much experience using this, but the only examples I see are hard coded values like below so I'm not sure if this functionality is available or if I'd need to add it.
[Authorize(Users = #"domain\user1, domain\user2")]
Any suggestions will be appreciated.

I ended up adding this myself, very easy to do.
public class AuthorizeUser : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
string[] admins =
//get user names
if (admins.Contains(httpContext.User.Identity.Name))
return true;
return false;
}
}
Then to use just
[AuthorizeUser]

Related

InputFormatter for Single Request

Is there a way to include an InputFormatter which only runs for a single endpoint?
We have 1 solitary endpoint which has a need for a custom InputFormatter.
So we don't really want to add an input formatter globally, for the benefit of a single endpoint. I don't really want to write a hacky middleware which would run for every request either. Some kind of ActionFilter would have been perfect.
I've seen existing SO answers on this very topic, but they all have answers which require an outdated API e.g. the InputFormatters collection is no longer available on the context in Action Filters.
Cheers
Here is an example which helps you to control the input formatter for an action method.
public class CSPContentTypeFormatterAttribute : ResultFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
var options = context
.HttpContext
.RequestServices
.GetService(serviceType: typeof(IOptions<MvcOptions>)) as IOptions<MvcOptions>;
var mvcOptions = options.Value;
mvcOptions.InputFormatters.OfType<SystemTextJsonInputFormatter>().First()
.SupportedMediaTypes.Add(
new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("application/csp-report")
);
base.OnResultExecuting(context);
}
}

IAuthorizationPolicyProvider: can I use multiple policy providers or I have to consider all cases inside one general policy provider?

In my program I want to
Check if users are registered in a certain users table for all possible actions.
Just for certain actions, I want also to check if the user has the appropriate CRUD rights.
I check the 1st condition in startup with the following code:
services.AddAuthorization(options =>
{
// This policy checks if a user is registered in our Users table.
options.AddPolicy(
"UserIsRegistered",
new AuthorizationPolicyBuilder()
.AddRequirements(new RegistrationRequirement())
.Build());
});
I also add
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers().RequireAuthorization("UserIsRegistered");
});
and I define the RegistrationRequirement and the RegistrationAuthorizationHandler accordingly.
For the 2nd condition, I created an attribute CrudAuthorizeAttribute with its CrudAuthorizationHandler. Since I have one different police for each possible Crud action, I created a CrudPolicyProvider.
Then I registered everything in Startup:
services.AddTransient<IAuthorizationHandler, RegistrationAuthorizationHandler>();
services.AddTransient<IAuthorizationHandler, CrudAuthorizationHandler>();
services.AddTransient<IAuthorizationPolicyProvider, CrudPolicyProvider>();
Now I see when I am checking the 1st condition I'm getting the policy from CrudPolicyProvider but I expect this policy generator to provide policies only in the 2nd condition.
Therefore:
Is there any way to specify that CrudPolicyProvider has to be used only with the CrudAttribute and nowhere else?
More generally, can I define two policy providers (as I can do with IAuthorizationHandler)
services.AddTransient<IAuthorizationPolicyProvider, FirstPolicyProvider>();
services.AddTransient<IAuthorizationPolicyProvider, SecondPolicyProvider>();
and use each one only when required?
If the answer is no, does it mean that I have to define a single GeneralPolicyProvider and inside this provider check which policies I have to provide each time depending on the situation I am? (something like using the POLICY_PREFIX here?).
Thanks!
can I define two policy providers (as I can do with IAuthorizationHandler)and use each one only when required
You could. But the two separated policy providers won't be activated correspondingly. You might have multiple policy providers, but only one of them will be used at the same time. Also there's no magic when using IAuthorizationPolicyProvider.
define a single GeneralPolicyProvider .... check which policies I have to provide each time depending on the situation I am? (something like using the POLICY_PREFIX here?).
Yes. But you don't have to use Policy_Prefix everywhere. In that way you'll repeat yourself too many times.
A better way is to inject a IHttpContextAccessor service into GeneralPolicyProvider, such that you can check the current EndPoint/HttpContext at run-time, and then you can resolve the target Policy Provider dynamically.
An implementation looks like:
public class GenericPolicyProvider : IAuthorizationPolicyProvider
{
private readonly IHttpContextAccessor _httpContextAccessor;
private AuthorizationOptions _authZOpts { get; }
public DefaultAuthorizationPolicyProvider FallbackPolicyProvider { get; }
private IAuthorizationPolicyProvider _fstPolicyProvider {get;set;}
private IAuthorizationPolicyProvider _sndPolicyProvider {get;set;}
public GenericPolicyProvider(IHttpContextAccessor httpContextAccessor, IOptions<AuthorizationOptions> options)
{
this._httpContextAccessor = httpContextAccessor;
this._authZOpts = options.Value;
this.FallbackPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
this._fstPolicyProvider = new FirstPolicyProvider(options.Value);
this._sndPolicyProvider = new SecondPolicyProvider(options.Value);
}
// use the target provider to provide policy
public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
{
var targetPolicyProvider = this.GetPolicyProvider(policyName);
return targetPolicyProvider.GetPolicyAsync(policyName);
}
// get the target provider dynamically
private IAuthorizationPolicyProvider GetPolicyProvider(string policyName)
{
var httpContext = this._httpContextAccessor.HttpContext;
if(httpContext==null) throw new Exception("HttpContext must not be null");
// now you get the HttpContext
// check HttpContext to determine which policy provider should be used
// ...
// or check endpoint,e.g. get a mark filter by endpoint.Metadata.GetMetadata<...>()
var endpoint = httpContext.GetEndpoint();
var someMarker = endpoint.Metadata.GetMetadata<SomeMarker>();
// in short, resolve the policy provider dynamically:
if(shouldUseFirstPolicyProvider())
return this._fstPolicyProvider;
else if(shouldUseSecondPolicyProvider())
return this._sndPolicyProvider;
else
return this.FallbackPolicyProvider;
}
...
}
Finally, don't forget to register this GenericPolicyProvider in Startup.

Extending Restlet 2.3 ClientInfo

Is it possible to extend org.restlet.data.ClientInfo? I need a convenient way of adding a List<String> permissions to complement the existing List<Role> roles. In a perfect world I would be able to add List<Permission> permissions but the former is perfectly acceptable.
I need to be able to get this from the request: org.restlet.resource.Resource.getRequest().getClientInfo().getPermissions()
I don't think that it's possible to add something within the class ClientInfo since it's a class that is managed by the Restlet engine. You can't subclass it to add a field permissions (you don't have the hand on the client info instantiation).
That said, you can leverage the context attributes. I mean that you can fill within your Enroler implementation an attribute permissions for the request, as described below:
public class MyEnroler implements Enroler {
private Application application;
public MyEnroler(Application application) {
this.application = application;
}
public void enrole(ClientInfo clientInfo) {
// Roles
Role role = new Role(application, "roleId",
"Role name");
clientInfo.getRoles().add(role);
// Permissions
Request request = Request.getCurrent();
List<Permission> permissions = new ArrayList<Permission>();
request.getAttributes().put("permissions", permissions);
Permission permission = (...)
permissions.add(permission);
}
Hope it helps you,
Thierry

Yii2 per content visibility depending on role

We have used RBAC to implement simple role based permissions for CRUD, but now we need to also add a 'visibility' functionality which makes it possible to limit content visibility (R) to only registered users or only the content owners.
So, how can we limit content visibility on different levels, for example
PUBLIC: anybody can see the content, including anonymous
INTERNAL: only registered users can see the content
PRIVATE: only the creator can see the content
What would be the best way to implement this, it looks like RBAC does not have a straightforward way of dealing with this.
I think that the problem can be solved by using defaultScope in models. Thus, before giving the content, we can check the current role of the user data and give the necessary conditions.
public static function find()
{
$userRoleArray = \Yii::$app->authManager->getRolesByUser(Yii::$app->user->getId());
$userRole = current($userRoleArray)->name;
if ($userRole == 'admin') {
return parent::find()->where("Your condition");
} elseif ($userRole == 'moderator') {
return parent::find()->where("Your condition");
}
}
you can make a permission function and run in each function that will take user role as argument and returns true or redirect to not allowed page.
Here is something I tried but you can modify according to your need.
public function allowUser($min_level) {
//-1 no login required 0..3: admin level
$userRole = //get user role;
$current_level = -1;
if (Yii::$app->user->isGuest)
$current_level = 0;
else
$current_level = userRole;
if ($min_level > $current_level) {
$this->redirect(array("/pages/not-allowed"),true);
}
}

Modifing CheckAccessCore(ctx) to permit WCF Help pages w/o authentication

I need to apply a different set of security policies to the "Help" urls on a WCF service. How can I get the full URL of the WCF service.. namely Session or Session.svc?
http://localhost:62302/Session.svc/help
http://localhost:62302/Session.svc/help/operations/GetSession
http://localhost:62302/Session/help
http://localhost:62302/Session/help/operations/GetSession
Since this is security-related, I need to vet anything I come up with against the community. The author here suggests that I simply check if the string ends in "help" and then blindly permit that query (which is obviously incorrect)
Code snip
public class APIKeyAuthorization : ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
if (this.IsHelpPage(operationContext.RequestContext.RequestMessage) || IsValidAPIKey(operationContext))
{
return true;
}
else
{
string key = GetAPIKey(operationContext);
// Send back an HTML reply
CreateErrorReply(operationContext, key);
return false;
}
}
private bool IsHelpPage(Message requestMessage)
{
return requestMessage.Headers.To.AbsolutePath.ToLower().EndsWith("help");
}
}
full source
This may be over-simplifying your original question but why not put the help section in its own unprotected area? You can create a Help controller who's sole purpose is to serve up help pages. You will then need to configure your web.config to allow users to access the help section with no authentication. Again this may be over-simplifying it but it's worth a shot.