new RoleManager<IdentityRole> error missing arguments in VS 2015 - model-view-controller

I want to implement User and Role Manager in VS 2015 using the Identity.EntityFramework": "3.0.0-rc1-final".
Among others I have created a class IdentityManager.
My main problem is creating a method to check the existence of a Role as follows.
public bool RoleExists(string name)
{
var RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));
return RoleManager.RoleExists(name);
}
I keep getting the error on new RoleManager<IdentityRole>:
There is no argument given that corresponds to roleValidators, keyNormalizer, errors, logger,contextAccessor"
Yes, basically all the parameters I am not specifying but I have no idea how to approach these.
I am very new at this and have been searching and trying for days now, if someone can just point me in the right direction I am willing to do the legwork and testing, I just need some documentation.

I am having a similar issue - it looks like the roles are not the best option in identity 3.0
This thread (ASP .NET 5 MVC 6 Identity 3 Roles Claims Groups) helped me get something working, but its sad that this is not better documented.
Here are my attempts at improving that. Asp.net.Identity (3.0.0.0-rc1-final)
in Startup.cs --> ConfigurationServices
//Define your policies here, they are strings associated with claims types, that have claim strings...
//they need to be in AspNetUserClaims table, user id, department, Dev to be allowed access to the Dev policy
//add the auth option, below that makes it work, and in the api controller, add the
//[Authorize("Dev")] attribute
//services.AddAuthorization(
// options =>
// {
// options.AddPolicy("Dev", policy => { policy.RequireClaim("department", "Dev"); });
// });

Related

Multiple IdPs with Sustainsys.Saml2 for the HTTPModule and AspNetCore

In a previous post (Sustainsys.SAML2 with a multitenant application) I asked about the process of adding multiple IdPs to my configuration. I have that working but need a little help on implementing this for a multitenant application.
Anders posted this response from Sustainsys:
The IdentityProviders property on the options is a collection. Just add more IdentityProvider objects to it. To select what Idp to invoke, put an item in the AuthProps with key idp and set the value to the EntityId of the Idp you want to use. It's possible to alter the collection when running.
I just need a quick code example of Anders' response of "To select what Idp to invoke, put an item in the AuthProps with key idp and set the value to the EntityId of the Idp you want to use." It seems the IdP gets put into the relaystate so when the ACS gets hit, it knows which IdP to use. Anyway, just need some help to complete my understanding of this for use in our multitenant application.
I answered my own question back in the original post. Check out:
Sustainsys.SAML2 with a multitenant application
A quick code (.NET Core using Sustainsys.Saml2) example:
var actionParams = new { authenticationType = "Saml2", returnUrl };
var properties = new AuthenticationProperties
{
RedirectUri = _linkGenerator.GetUriByAction(HttpContext, "LoginExternalCallback", null, actionParams)
};
properties.Items.Add("idp", new EntityId("someID").Id); // <--- **That's the important line**
return Challenge(properties, "Saml2"); // <--- Return Challenge from the controller

With Elsa Workflow 2.0 how to create an activity based on HttpEndpoint

We're trying to use Elsa for a project, but we're facing some difficulties now, so need suggestions badly. One thing we're trying to do is to create an Activity based on existing HttpEndpoint. However, with the source code got from https://github.com/elsa-workflows/elsa-core, after googled some docs and samples, we haven't been able to figure it out.
Here is what exactly we're attempting to do.
create a new Activity based on HttpEndpoint
make the Path include WorkflowInstanceId by default
a little bit more customizations needed in our scenario
Looking forward to suggestions and guidance. Thanks!
You could do something like what the Webhooks module is doing. Instead of
inheriting from HttpEndpoint, it uses an IActivityTypeProvider implementation that dynamically yields new activity types that reuse HttpEndpoint.
In your case, your activity type provider would only have to yield a single activity type (e.g. MyEndpoint) that pre-configures any and all aspects that you want, including the default Path property value.
Deriving a new activity type from HttpEndpoint directly works too. You will have to implement your own bookmark provider that provides HttpEndpointBookmark objects - the HTTP middleware for the HttpEndpoint activity relies on that.
Example:
public class MyEndpointBookmarkProvider : BookmarkProvider<HttpEndpointBookmark>
{
public override bool SupportsActivity(BookmarkProviderContext context) => context.ActivityType.TypeName == nameof(MyEndpoint);
public override async ValueTask<IEnumerable<BookmarkResult>> GetBookmarksAsync(BookmarkProviderContext context, CancellationToken cancellationToken)
{
var path = await context.ReadActivityPropertyAsync<MyEndpoint, PathString>(x => x.Path, cancellationToken);
var methods = (await context.ReadActivityPropertyAsync<MyEndpoint, HashSet<string>>(x => x.Methods, cancellationToken))?.Select(ToLower) ?? Enumerable.Empty<string>();
BookmarkResult CreateBookmark(string method) => Result(new(path, method), nameof(HttpEndpoint));
return methods.Select(CreateBookmark);
}
private static string ToLower(string s) => s.ToLowerInvariant();
}
The above bookmark provider provides bookmarks for your custom activity when the activity being indexed is of type "MyEndpoint".
Alternatively, you might go a different route altogether and simply implement an API endpoint (an ASP.NET Core controller, middleware or route endpoint) that triggers workflows based on your custom activity. I've written some documentation about that process here: https://elsa-workflows.github.io/elsa-core/docs/next/guides/guides-blocking-activities

Can't save object in Cloud Code

I'm having an issue when running a function in Cloud Code. It is supposed to check the existence of an object and, if it does exist, create a new user:
Parse.Cloud.define("createUser", function(request, response) {
// Query the existing company by id
var query = new Parse.Query(Parse.Object.extend("Company"));
query.equalTo("objectId", request.params.company.existing.id);
query.find().then(function(result){
var user = new Parse.User();
user.set("username", request.params.username);
user.set("password", request.params.username);
user.set("email", request.params.email);
user.set("permissions", ["User"]);
var company = result[0];
user.signUp(null, {
success: function(user){
// Asign company ACL for User write permission
var cACL = company.getACL();
cACL.setWriteAccess(user.id, true);
company.setACL(cACL);
// Save company
company.save();
console.log(company);
// Establish user-company relationship
var cRelation = user.relation("associated");
cRelation.add(company);
// Save user
user.save();
console.log(user);
// Finish
response.success(user);
},
error: function(user, error){
response.error(JSON.stringify({code: -8000, message: "User creation failed"}));
}
});
}, function(error){
response.error(JSON.stringify({code: -8001, message: "Invalid company"}));
});
});
I first query Parse for the existence of said object. If it does exist I create a new user with the parameters received. In the completion block of the user creation I assign the proper ACLs (to the company object) and later on save them. That's when I encounter the first issue: the ACLs are not saved (checked in the dashboard). I console.log the company for debugging purposes and it shows the ACLs are correctly set. So I assume it must be a saving problem.
NOTE: The user is created, but whatever I try to do later doesn't work.
Later on I add this object to a relationship previously defined in the dashboard, but I have the same problem with that: the relationship does not come up in the dashboard, even though when I console.log the object it shows that the relationship was properly set.
I'm lost here. I don't understand why this isn't working and I've read tons of online documentation and still can't find the answer.
Okay, after a day of work I finally found out my problem. I had ACLs set everywhere and I had no privilege for saving the objects I was trying to save. So saving was indeed failing.
I should note that if you are having the same problem I did, you can easily solve it using the Master Key. To do so, you need to call Parse.Cloud.useMasterKey() before executing any requests that must be authenticated.
This only works in Cloud Code, and you should definitely know what you are doing when you use the Master Key because it basically gives read and write privileges to anyone, everywhere, for everything. So make sure your logic is flawless because you might get big security problems if it's not used wisely. As Uncle Ben said: With great power comes great responsibility.
Hope this helps someone.

How can I make the [Authorize] attribute more flexible?

I have an MVC 5 application that I lock down by only allowing certain authenticated users to have access to specific actions within my controller. I utilize the authorize attribute at the top of the class allowing only the user(s) I want to gain access after login. I do this with the following attribute placed at top of my class...
[Authorize(Users="user1,user2")]
This works great! However, what if I don't want to recompile and deploy the application everytime I want to add a new user to this specific controller?
I thought I might add this in my web.config file under as a key like so...
<appSettings>
<add users="user1,user2"/>
</appSettings>
But when I try to access this key in my controller like so: [Authorize(Users=ConfigurationManager.AppSettings["users"])] I am getting an error: Cannot resolve symbol 'AppSettings'.
Is there a way to do this?
I'm not sure why an answer that didn't answer the question was accepted. Regardless, I thought it might be worth adding an answer for any future travelers.
While this functionality isn't provided out of the box, it's certainly possible by writing your own authorize attribute.
public class ConfigAuthorize : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var allowedUsers = ConfigurationManager.AppSettings["CoolActionAllowedUsers"];
var allowedUsersArray = allowedUsers.Split(',');
if (httpContext.User.Identity != null && allowedUsersArray.Contains(httpContext.User.Identity.Name))
{
return true;
}
return false;
}
}
And to use the attribute:
[ConfigAuthorize]
public ActionResult CoolAction() {
//...
}
In the code above when your authorization is performed in AuthorizeCore, the configuration value from CoolActionAllowedUsers will be pulled into memory and the currently authenticated user will be verified if they are in the list of allowed users. If you make a change to your config file it won't be a problem; the application pool will automatically restart and the next time the code runs to read the config file your new value will be read.
I completely agree with #Shoe that roles should be used. Managing a list of users in your code is just a pain in the arse. In fact, at work, anytime I get a request for just one random user to have access to a page I always require a group to be setup. However the code above could apply to a list of roles as well.
Instead of using the Users parameter use the Roles parameter.
[Authorize(Roles="CanExecuteActions")]
Now you can manage what users have access to your controller by giving them this role. Any user without the role can't execute any actions of the controller.

Sentry & Laravel, getting users within a group. changing findAllUsersWithAccess to have pagination

I'm trying to find all users w/ a specific permissions list in Sentry with laravel. The problem is that Sentry::findAllUsersWithAccess() returns an array().
as stated in their github repository i pinpointed their code to be
public function findAllWithAccess($permissions)
{
return array_filter($this->findAll(), function($user) use ($permissions)
{
return $user->hasAccess($permissions);
});
}
right now, it gets all users and filter it out with users with permission list. the big problem would be when I as a developer would get the set of users, it'll show ALL users, i'm developing an app which may hold thousands of users and i only need to get users with sepcific permission lists.
With regards to that would love to use one with a ->paginate() capability.
Any thoughts how to get it without getting all the users.
Why dont you override the findAllWithAccess() method and write your own implementation, which uses mysql where instead of array_filter().
I dont know your project structure and the underlying db schema, so all i can give you atm is the link to the eloquent documentation Querying Relations (whereHas).
In case you dont know where to start: its always a good idea to look at the ServiceProvider (SentryServiceProvider, where the UserProvider, which holds the findAllWidthAccess() method, is registered). Override the registerUserProvider method and return your own implementation of the UserProvider (with the edited findAllWithAccess() method).
Hope that will point you in the right direction.
In Laravel you can do pagination manually on arrays:
$paginator = Paginator::make($items, $totalItems, $perPage);
Check the docs: http://laravel.com/docs/pagination

Resources