I have ported Migrations from a web app to a class library project.
Everything works fine, except that I can't call the static class Roles.
I have included the namespace using System.Web.Security; which is where the Roles are located.
Here is the Configuration.cs file contents:
namespace _DataContext.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
using WebMatrix.WebData;
using System.Web.Security;
internal sealed class Configuration : DbMigrationsConfiguration<_DataContext.DataContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(_DataContext.DataContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
SeedMembership();
}
private void SeedMembership()
{
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
// doesn't work either:
//var roles = (SimpleRoleProvider)Roles.Provider;
//var membership = (SimpleMembershipProvider)Membership.Provider;
if (Roles.RoleExists("Administrator"))
Roles.CreateRole("Administrator");
}
}
}
Error message is:
The name 'Roles' does not exist in the current context
What am I missing here?
[Edit]
I have been doing some more research and it appears that i have to create an object from SimpleRoleProvider in order to access the RoleExists method.
But why do i have to do it this way? Why can't i just use:
if (Roles.RoleExists("Administrator"))
Roles.CreateRole("Administrator");
Roles comes from a static class?
Have you added the roleManager element to the system.web section of your Web.config file? From the MSDN page on Roles:
To enable role management for your ASP.NET application, use the roleManager element of the system.web section in the Web.config file for your application, as shown in the following example.
The section looks like this:
<roleManager defaultProvider="SqlProvider"
enabled="true"
cacheRolesInCookie="true"
cookieName=".ASPROLES"
cookieTimeout="30"
cookiePath="/"
cookieRequireSSL="false"
cookieSlidingExpiration="true"
cookieProtection="All" >
<providers>
<add
name="SqlProvider"
type="System.Web.Security.SqlRoleProvider"
connectionStringName="SqlServices"
applicationName="SampleApplication" />
</providers>
</roleManager>
You should be able to access Roles directly, but I would not recommend it when using the SimpleMembership providers. That being said, do you have the assembly System.Web referenced in your project?
The preferred method for getting the role provider is to do something like this:
var roles = (WebMatrix.WebData.SimpleRoleProvider)Roles.Provider;
if (!roles.RoleExists("Admin"))
{
roles.CreateRole("Admin");
}
If you compare the definition of Roles versus SimpleRoleProvider you will see there is quite a bit of difference. It looks like the SimpleRoleProvider does not implement the complete interface for Roles, which is not required when implementing a custom provider. You may get a "not implemented" exception on some the methods if you call them directly from Roles. SimpleRoleProvider also provides additional methods/properties that can be useful when using SimpleMembership.
You are using seeding method in Class Library project.
You have to add two references
1. System.Web
2. System.Web.ApplicationServices
then resolve Roles, Membership from these references.
Related
.Net framework 4.6.1, class library project (web API)
I have added the swagger/swashbuckle nuget to the project, and added the SwaggerConfig.cs file to my App_Start folder.
Snip of SwaggerConfig.cs
using System.Web.Http;
using WebActivatorEx;
using MyService;
using Swashbuckle.Application;
[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]
I then go on and register the service
public class SwaggerConfig
{
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "My API");
c.IncludeXmlComments(string.Format(#"{0}\swaggerdoc.XML",
System.AppDomain.CurrentDomain.BaseDirectory));
c.BasicAuth("basicauth").Description("Basic HTTP Authentication");
})
.EnableSwaggerUi(c =>
{
});
}
}
But I am not sure where I set the username/password required to view the documentation. The API methods all use a token for authentication, but I am trying to add a layer of security to stop a random user stumbling across the API documentation, by using basic auth.
If you want to secure the documentation, you have to to this on the webserver itself, with .net 4.x I assume IIS.
The method you are using is intended to tell Swagger to show a username/password logon form to call the service endpoints using these credentials with a basic HTTP authorization header.
To secure your swagger doc's using your basic authentication, you will need to enable it in the SwaggerConfig.cs file and couple it with a corresponding "security" property at the document or operation level.
Please note the below full comment from the SwaggerConfig.cs for Enabling Basic Authentication:
// You can use "BasicAuth", "ApiKey" or "OAuth2" options to describe security schemes for the API.
// See https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md for more details.
// NOTE: These only define the schemes and need to be coupled with a corresponding "security" property
// at the document or operation level to indicate which schemes are required for an operation. To do this,
// you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties
// according to your specific authorization implementation
//
c.BasicAuth("basic").Description("Basic HTTP Authentication");
how to couple it with the corresponding "security" property? You can add a class to implement that filter as:
public class SwaggerHeaderFilter : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var filterPipeline = apiDescription.ActionDescriptor.GetFilterPipeline();
// check if authorization is required
var isAuthorized = filterPipeline
.Select(filterInfo => filterInfo.Instance)
.Any(filter => filter is IAuthorizationFilter);
// check if anonymous access is allowed
var allowAnonymous = apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any();
if (isAuthorized && !allowAnonymous)
{
if (operation.security == null)
operation.security = new List<IDictionary<string, IEnumerable<string>>>();
var auth = new Dictionary<string, IEnumerable<string>>
{
{"basic", Enumerable.Empty<string>()}
};
operation.security.Add(auth);
}
}
}
and in the swaggerConfig.cs file, add this to the configurations:
c.OperationFilter<SwaggerHeaderFilter>();
And Don't forget to decorate your Api's with the [Authorize] tag
reference:
https://codingsight.com/swashbuckle-swagger-configuration-for-webapi/
I've spent a few weeks trying to figure this out, this is a duplicate of a question I asked previously but did not get a response to, so I am refining the question here.
I've created a custom class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Configuration;
namespace mssql_gui
{
public class TestConfigSection : ConfigurationSection
{
[ConfigurationProperty("", IsRequired = true, IsDefaultCollection = true)]
public TestConfigInstanceCollection Instances
{
get { return (TestConfigInstanceCollection)this[""]; }
set { this[""] = value; }
}
}
public class TestConfigInstanceCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new TestConfigInstanceElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((TestConfigInstanceElement)element).Key;
}
}
public class TestConfigInstanceElement : ConfigurationElement
{
[ConfigurationProperty("key", IsKey = true, IsRequired = true)]
public string Key
{
get { return (string)base["key"]; }
set { base["key"] = value; }
}
[ConfigurationProperty("value", IsRequired = true)]
public string Value
{
get { return (string)base["value"]; }
set { base["value"] = value; }
}
}
}
I've implemented it:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="testSection" type="mssql_gui.TestConfigSection"/>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
</startup>
<appSettings>
<add key="Data Source" value="localhost\SQLEXPRESS"/>
<add key="Initial Catalog" value="(empty)"/>
<add key="Integrated Security" value="SSPI"/>
</appSettings>
<testSection>
<add key ="testKey" value="tesValue"/>
</testSection>
</configuration>
and I have tried to access it, I am getting:
An error occurred creating the configuration section handler for testSection: Could not load type 'mssql_gui.TestConfigSection' from assembly 'System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
I understand that in the type, I should be declare an assembly dll, but I'm confused about that...because in the official instructions by MS, it says to create a new class for the handler:
Create a public class that inherits from the
System.Configuration.ConfigurationSection class.
Add code to define the section's attributes and elements.
Adding the class (at least through the visual studio interface) creates a .cs file, not a .dll assembly file, so how to I add that custom class to an assembly file in order to reference it in the <configSections> part of app.config?
If I understand correctly, you have problem with resolving what actually your Assembly is, since you are only creating .cs files that determine types that this file hold.
Assembly (in maybe not so accurate shorcut) is just the project you have in your solution. It will get compiled into its seperate assembly - the .dll you mentioned - later on.
When you add class to any .cs file in given project, on compile it will be included in project's assembly.
By default, if you won't provide assembly for configSection where its corresponding type should be found, App.config defaults to System.Configuration assembly - that's where you get your error from, since you've declared your section in your own assembly (== project).
Right click in Visual Studio on your project that holds App.config file and choose Properties to check its Assembly name:
Then add this name to your App.config section declaration. In my example its ConsoleApp1, so I will add it to configuration accordingly:
<configSections>
<section name="testSection" type="mssql_gui.TestConfigSection, ConsoleApp1"/>
</configSections>
Ensure that the type attribute of the section element matches the
manifest of the assembly (ensure that you specify both the correct
namespace and type name).
You need to add the name of the assembly (where the type relies) to the type attribute:
You'll get the name of the assembly from the AssemblyInfo.cs within the project where TestConfigSection class is defined.
<section name="testSection" type="mssql_gui.TestConfigSection, ASSEMBLYNAME"/>
Example asuming your assembly names mssql_gui
<section name="testSection" type="mssql_gui.TestConfigSection, mssql_gui"/>
You read it like this:
Configuration config =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
TestConfigSection mySec = (TestConfigSection)config.Sections["testSection"];
See more details at MSDN
How to: Create Custom Configuration Sections Using ConfigurationSection
I want to add some additional claims to a Principal during authentication. I am trying to implement a custom ClaimsAuthenticationManager in my MVC 4.5 project which uses Windows Authentication:
namespace Project.Infrastructure
{
public class ClaimsTransformer : ClaimsAuthenticationManager
{
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated == true)
{
((ClaimsIdentity)incomingPrincipal.Identity).AddClaim(new Claim(ClaimTypes.Role, "Admin"));
}
return incomingPrincipal;
}
}
}
I have the web.config set up to use my custom class:
<configSections>
<section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</configSections>
and
<system.identityModel>
<identityConfiguration>
<claimsAuthenticationManager type="Project.Infrastructure.ClaimsTransformer, [AssemblyName]" />
</identityConfiguration>
</system.identityModel>
But the Authenticate method never gets called. Am I missing something?
The missing step is that you need to add an HTTP Module to kick all of this off.
So, you need a class that looks like this:
public class MyClaimsAuthenticationModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PostAuthenticateRequest += Context_PostAuthenticateRequest;
}
public void Dispose()
{
// Nothing to dispose, method required by IHttpModule
}
void Context_PostAuthenticateRequest(object sender, EventArgs e)
{
var transformer = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager;
if (transformer != null)
{
var context = ((HttpApplication)sender).Context;
var principal = context.User as ClaimsPrincipal;
var transformedPrincipal = transformer.Authenticate(context.Request.RawUrl, principal);
context.User = transformedPrincipal;
Thread.CurrentPrincipal = transformedPrincipal;
}
}
}
This will pick up the transformer you specified in the web.config and call authenticate on it, then attach the returned principal to the HttpContext and the current thread.
You will also need something like the following in your web.config:
<system.webServer>
<modules>
<add name="MyClaimsAuthenticationModule" type="MyApplication.MyHttpModels.MyClaimsAuthenticationModule, MyApplicationAssembly" />
</modules>
</system.webServer>
Update
You can, of course, put the code from the method Context_PostAuthenticationRequest in the PostAuthenticateRequest handler in your Global.asax.cs class file. However, I prefer to keep the responsibilities of the classes small so I go for an implementation of IHttpModule so that the module does its thing and it is obvious what that is, and it is separate from other things that may be happening at various stages of the pipeline.
If your Global.asax.cs file is small then there is no problem with putting the code there. It should still work. However, you are mixing responsibilities in the class and it could get unwieldy in the future.
Are you calling the Authenticate method with something like this, and the Authentication is not taking place?
ClaimsTransformer manager = new ClaimsTransformer();
manager.Authenticate("resource", incomingPrincipal )
You may want to replace the "return incomingPrincipal" from inside the ClaimsTransformer class with a call to:
return base.Authenticate(resourceName, incomingPrincipal);
Also why do you need Windows Authentication?
I see the same issue as this question, but the scenario presented there doesn't seem to apply so I think I have a different issue. In fact, I'm seeing several questions on SO that are similar, each with different causes and solutions, so I think this error must be caused from a high level. That said...
I have an EF code-first database model and I'm trying to use IdentityUser to extend a standard registration for my MVC 5 site.
I have my extended UserModel:
namespace MyMvcSite.Models
{
public class UserModel : IdentityUser
{
public string BillingId { get; set; }
public virtual ICollection<DatabaseModel> Databases { get; set; }
}
}
And my context:
using MyMvcSite.Models;
namespace MyMvcSite.Web
{
public class AuthContext : IdentityDbContext<UserModel>
{
public AuthContext() : base("AuthContext") { }
}
}
Now, when I execute the code to register a user:
public async Task<IdentityResult> RegisterUser(UserModel user)
{
user.Email = user.UserName;
var result = await _userManager.CreateAsync(user);
return result;
}
I get this error:
The entity type IdentityUser is not part of the model for the current context.
I can't figure out what this error means, because it looks like I have everything correct. Can anyone tell what might be going wrong???
I know my connectionString AuthContext is correct because I have used it previously.
When you are using a custom user class with ASP.NET Identity, you have to make sure that you explicitly specify the custom user class type <T> to both the UserManager and the UserStore on instantiation.
private UserManager<UserModel> _userManager;
public AccountController()
{
AuthContext _ctx = new AuthContext();
UserStore<UserModel> userStore = new UserStore<UserModel>(_ctx);
_userManager = new UserManager<UserModel>(userStore);
}
or in shorter form (like your reply comment):
private UserManager<UserModel> _userManager;
public AccountController()
{
AuthContext _ctx = new AuthContext();
_userManager = new UserManager<UserModel>(new UserStore<UserModel>(_ctx));
}
If the type is allowed to defaulted to IdentityUser when you want to use a custom class you will experience the error you reported.
I was having this same problem, and I recall having a similar problem working with SimpleMembership in MVC4.
I’m doing database first development, so I have an EDMX file. Turns out, ASP.NET Identity does not like the connection string that is created when you generate your .edmx model file. If you are using a. EDM connection string in :base(“EDMConnString”) you will most likely have this problem.
I fixed this by creating a standard connection string that pointed to the database where the ASP.NET Identity tables are (in my case the same database), used that connection string in :base, and it worked.
Something like this
<add name="IdentityConnection" connectionString="data source=THEJUS\SQLSERVER2014;initial catalog=IdentitySample;integrated security=True;MultipleActiveResultSets=True;App=IdentitySample.Admin" providerName="System.Data.SqlClient" />
I got this error when I introduced DI to my project. Using AutoFac and Identity I had to add the following: builder.RegisterType<ApplicationDbContext>().As<DbContext>().InstancePerLifetimeScope();
Without this, when AutoFac was creating my UserStore instance, it was using the default UserStore() ctor which creates a new IdentityDbContext, not my ApplicationDbContext.
With this line, UserStore(DbContext context) ctor gets called, with my ApplicationDbContext.
Here is some step i figured out while resolving this issue
First Check your database for Table of ASP.Net Identity
Create these table on your database if not exist you can also apply migration
Check the below image and verify your code
Register Action
IdentityDbContext Class
I have a traditional ASP.NET WebForms application. I want to migrate it over to ASP.NET MVC 3. One of the central components of my WebForms application is a heavy use of the ProfileCommon instance that is automatically generated. Unfortunately, that object isn't available in ASP.NET MVC 3 applications.
I have created a ProfileCommon class using the advice found in the following thread: Implementing Profile Provider in ASP.NET MVC
My ProfileCommon class looks like the following:
public class ProfileCommon : ProfileBase
{
public virtual string FirstName
{
get { return ((string)(this.GetPropertyValue("FirstName"))); }
set { this.SetPropertyValue("FirstName", value); }
}
public virtual string LastName
{
get { return ((int)(this.GetPropertyValue("LastName"))); }
set { this.SetPropertyValue("LastName", value); }
}
public static new ProfileCommon Create(string username)
{
return ProfileBase.Create(username) as ProfileCommon;
}
public virtual ProfileCommon GetProfile(string username)
{
return Create(username) as ProfileCommon;
}
}
In my web.config, I have:
<profile inherits="MyCompany.Namespace1.ProfileCommon" defaultProvider="CustomTableProfileProvider">
<providers>
<clear/>
<add name="CustomTableProfileProvider" type="MyCompany.Namespace2.SqlTableProfileProvider" connectionStringName="MyDatabaseCS" table="MyTable" applicationName="MyApplication" />
</providers>
</profile>
I then have the following code in my method in my controller that looks like this:
ProfileCommon userProfile = (ProfileCommon)(ProfileCommon.Create(username));
string greeting = "Hello " + userProfile.FirstName;
When the second line gets executed (the greeting), I get an exception. The exception says:
System.Configuration.Provider.ProviderException: The CustomProviderData attribute is required on each provider property in the web.config file.
I do not understand what that means or what I need to do. I'm slightly confused because the individual in the previous aforementioned thread says everything worked. But it doesn't for me. Can someone please help me correct this error?
Thank you!