Invalid Token when using ASP.NET MVC 5 and Dependency Injection with Unity - asp.net

I am building an ASP.NET MVC 5 website and am using Unity for dependency injection. I get an Invalid Token exception when some time has passed (more than an hour, less than a day) between the token generation and the token validation.
I have the following code in my Startup.cs:
internal static IDataProtectionProvider DataProtectionProvider { get; private set; }
public void Configuration(IAppBuilder app)
{
DataProtectionProvider = app.GetDataProtectionProvider();
ConfigureAuth(app);
}
I have the following code in the conctructor of my ApplicationUserManager class (timespan is set to 7 days now just to make sure that is not the issue):
var dataProtectionProvider = Startup.DataProtectionProvider;
if (dataProtectionProvider != null)
{
this.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser> (dataProtectionProvider.Create("ASP.NET Identity")) {
TokenLifespan = TimeSpan.FromDays(7)
};
}
In Startup.Auth.cs, I have the following line of code in the ConfigureAuth method:
app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<ApplicationUserManager>());
In UnityConfig.cs, I have set up dependency injection:
container.RegisterType<ApplicationDbContext>();
container.RegisterType<ApplicationSignInManager>();
container.RegisterType<ApplicationUserManager>();
container.RegisterType<ApplicationRoleManager>();
container.RegisterType<IAuthenticationManager>(
new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication)
);
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(
new InjectionConstructor(typeof(ApplicationDbContext))
);
container.RegisterType<IRoleStore<IdentityRole, string>, RoleStore<IdentityRole>>(
new InjectionConstructor(typeof(ApplicationDbContext))
);
I have to add that one of my scenarios allows for the creation of a Contact with an associated user account. The Contact and associated user account are created in the ContactController, while the ConfirmEmail method is in the AccountController. Both take ApplicationUserManager as a constructor parameter, which means the ApplicationUserManager is injected into the controllers.
That does not appear to be the issue, since everything works fine if I confirm right after receiving the confirmation email. However, if I wait an hour or so, and then try to confirm, I get the Invalid Token exception.
I have already verified that I am not accidentally mixing different token types, both generation and verification are for email confirmation. I have also verified that I am url encoding (and decoding) the token.
I am currently testing on an Azure virtual machine with a static IP that is running its own IIS, the production environment will most likely be on a non-Azure VPS, als running its own IIS. I am not an Azure expert, but to my knowledge, I didn't select any options that are related to load balancing.
I would really appreciate your help, as I have already tried any possible solutions I was able to find here and on other websites.

The Invalid token issue has been solved. Since it only happened after some time had passed, I figured it might have something to do with my application recycling.
I managed to get rid of the problem by setting a fixed MachineKey in my web.config. You can use IIS Manager to generate it, as described here: https://blogs.msdn.microsoft.com/vijaysk/2009/05/13/iis-7-tip-10-you-can-generate-machine-keys-from-the-iis-manager/
Please note: for some reason, IIS adds the IsolateApps when it generates a machine key. However, this results in ASP.NET throwing an exception. After you manually remove the IsolateApps and save, it should work as expected.

Related

"System.Net.HttpListener" not available in IAppBuilder properties

I am developing a web app with mix authentication (Owin Token Based and Windows authentication). I have implemented Owin token based authentication and want to implement windows authentication for the users which are marked as active directory users.
In Owin middleware, I want to get requesting user's windows username. I am getting object in OwinContext.Request.User.Identity. However, OwinContext.Request.User.Identity.Name is always blank string.
I found that I should add below lines in startup.cs:
var listener = (HttpListener)app.Properties["System.Net.HttpListener"];
listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
However, I am getting key not found exception. "System.Net.HttpListener" is not present in Properties array. I have installed Microsoft.Owin.SelfHost, Microsoft.Owin.Host.HttpListener. However, I am still getting the error.
Any help is greatly appreciated.
Thanks,
GB
For me issue was that project was started as shared lib, not a web app.
Solution was to add a line into .cspro file after <ProjectGuid> line.
<ProjectTypeGuids>{349C5851-65DF-11DA-9384-00065B846F21};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
Then you dont need to add HttpListener explicitly, just reload project and follow this instructions starting from Properties edition part.
Enabling Windows Authentication in Katana
You can access principal the same ways:
Get the user in an OWIN middleware:
public async Task Invoke(IDictionary<string, object> env)
{
OwinContext context = new OwinContext(env);
WindowsPrincipal user = context.Request.User as WindowsPrincipal;
//...
}
Get the user in a Web API Controller:
// In a web api controller function
WindowsPrincipal user = RequestContext.Principal as WindowsPrincipal;
UPD: List of Visual Studio Projects GUIDs

Spring Social Facebook

I am developing with Spring Social and Thymeleaf from the quick start example, but I realised that it only supports one Facebook object per controller. This means the sample can't provide support for multiple users and I am guessing it has to do with the #Scope of the variable. Its runs in a Spring boot container and I wonder how I can configure this so that each session has its own Facebook object.
As you suggested, the Facebook object should be configured with request scope. If you're using the configuration support and/or Spring Boot, then it will be request scoped. Therefore, even though the controller is injected once with a Facebook instance, that instance is really a proxy that will delegate to a real FacebookTemplate instance that is created at request time for the authenticated user.
I can only assume that you're referring to the getting started guide example at http://spring.io/guides/gs/accessing-facebook/. In that case, it's using the most simple Spring Boot autoconfiguration possible for Spring Social, which includes a basic (yet not intended for production) implementation of UserIdSource which always returns "anonymous" as the user ID. Therefore, after you create the first Facebook connection, the second browser tries to find a connection for "anonymous", finds it, and gives you an authorized Facebook object.
This may seem peculiar, but it is an example app intended to get you started...and it does that. All you need to do to get a real UserIdSource is to add Spring Security to the project. That will tell Spring Social autoconfiguration to configure a UserIdSource that fetches the current user ID from the security context. This reflects a more real-world use of Spring Social, albeit obviously more involved and beyond the scope of the getting started guide.
But you can look at https://github.com/spring-projects/spring-social-samples/tree/master/spring-social-showcase-boot for a more complete example of Spring Social within Spring Boot.
Spring Boot autoconfigures a lot of things behind the scenes. It does autoconfigure the Facebook, LinkedIn and Twitter properties and sets up the connection factories for social providers.
However, the implementation of UserIdSource always returns “anonymous” as the user ID. Once the first Facebook connection is established the second browser will try to find a connection for “anonymous” which it finds and gives you an authorised Facebook object.
#Configuration
#EnableSocial
#ConditionalOnWebApplication
#ConditionalOnMissingClass("org.springframework.security.core.context.SecurityContextHolder")
protected static class AnonymousUserIdSourceConfig extends SocialConfigurerAdapter {
#Override
public UserIdSource getUserIdSource() {
return new UserIdSource() {
#Override
public String getUserId() {
return "anonymous";
}
};
}
}
Solution
The solution is to override the “anonymous” as the UserId for each new user/session. So for each session, we can simply return a SessionID, however, it may not be unique enough to identify users, especially if it’s being cached or stored somewhere in a connection database.
#Override
public String getUserId() {
RequestAttributes request = RequestContextHolder.currentRequestAttributes();
String uuid = (String) request.getAttribute("_socialUserUUID", RequestAttributes.SCOPE_SESSION);
if (uuid == null) {
uuid = UUID.randomUUID().toString();
request.setAttribute("_socialUserUUID", uuid, RequestAttributes.SCOPE_SESSION);
}
return uuid;
}
The solution for above problem has been talked about in detail over here

authentication in singalR selfhost server- and web client in SSL

I have a singalR self host server that is hosting my singalR in a console application on https
I am using this packages to self host:
Install-Package Microsoft.Owin.Hosting -pre
Install-Package Microsoft.Owin.Host.HttpListener -pre
Install-Package Microsoft.AspNet.SignalR.Owin
i have a web client which is backed by WebApi, I can connect to my selfhosted singalR from my webclient and send messages however I would now like to add authentication to this, which means only logged in users can send messages to my selfhosted singalR server.
I used [Authorize] attribute before my method
[Authorize]
public void Test(string test)
{
Console.WriteLine(test);
}
I have my web client authentication done via forms authentication however after logging in sucessfully in my webclient, when i do call singalR method, i recieve javascript error
Uncaught Value cannot be null. Parameter name: user
It tells that my method is protected but somehow my user is not passed to my self hosted singalR server, What is missing here?
Support for this was introduced with SignalR 1.0, you can read a little about that on David Fowlers blog. The problem is, with it being so new it's a little sparsely documented.
I'm not exactly sure what's going on in your application at the moment but you can find a similar question already on Stack Overflow which might help you get on the right track: Integrating SignalR with existing Authorization
Basically, you can create a SignalR Attribute that implements IAuthorizeHubConnection and IAuthorizeHubMethodInvocation, then decorate your Hubs/Methods that you want authorized.
public class HubAuthorizeAttribute : Attribute, IAuthorizeHubConnection, IAuthorizeHubMethodInvocation {
public virtual bool AuthorizeHubConnection(HubDescriptor hubDescriptor, Microsoft.AspNet.SignalR.IRequest request) {
IAuthorizationProvider authorizationProvider = DependencyResolver.Current.GetService<IAuthorizationProvider>();
return authorizationProvider.IsAuthorizedController(hubDescriptor.Name);
}
public virtual bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext) {
IAuthorizationProvider authorizationProvider = DependencyResolver.Current.GetService<IAuthorizationProvider>();
return authorizationProvider.IsAuthorizedAction(hubIncomingInvokerContext.MethodDescriptor.Hub.Name, hubIncomingInvokerContext.MethodDescriptor.Name);
}
}
Alternatively, you could add the HubAuthorizeAttribute as a HubPipeline Module to Globally require Authorization.
var globalAuthorizer = new HubAuthorizeAttribute ();
GlobalHost.HubPipeline.AddModule(new AuthorizeModule(globalAuthorizer, globalAuthorizer));
I've asked a similar question a few times over the last days in the SignalR JabbR chat and haven't got any answer.
When I was about to post my question here I found your question and this other one. Unfortunately, from the answer given there a couple of weeks ago, it seems like SignalR itself provides no Authentication support, so that's a huge problem for many selfhosted applications (we were intending to use Integrated Windows Authentication with SignalR...)

Thinktecture.IdentityModel with SimpleMembership

I want to use ASP.NET SimpleMembership to authenticate users that consume my WebAPI. Thinktecture has a wonderful authentication library called Thinktecture.IdentityModel (http://thinktecture.github.com/Thinktecture.IdentityModel.45/) with an example that ties Forms Auth with Basic Auth (source). However, the example uses Membership.ValidateUser() which doesn't work without a ASP.NET Membership provider, which isn't supported by SimpleMembership (source) (edit: this isn't entirely true, see Mark's answer below).
Edit:
Here's what I did:
1) Create a new MVC Internet Application
2) Install Thinktecture.IdentityModel via NuGet
3) Create a model and an api controller via scaffolding:
public class Goober
{
public int GooberId { get; set; }
public string GooberWords { get; set; }
}
4) Ran the project, created a new user and created a new Goober using Fiddler
5) Added [Authorize] to GetGoober(int id)
6) In WebApiConfig.cs added:
var authConfig = new AuthenticationConfiguration();
authConfig.AddBasicAuthentication((userName, password) =>
Membership.ValidateUser(userName, password));
config.MessageHandlers.Add(new AuthenticationHandler(authConfig));
When I run the project and hit api/goober/1 with Fiddler I get a 401 www-Authenticate: unspecified. But if I log in first using the AccountController then use Fiddler I get a 200 and everything is peachy.
Edit
Okay, I think the problem isn't related to my initial question. I suspect it's related to the initialization of SimpleMembership in the template. When I open the project and run debug then hit the api with Fiddler I can't get past Auth. But when I simply click the "register" link on the web frontend I get past Auth. I'm guessing it's because the InitializeSimpleMembershipAttribute is called at the AccountController so doesn't initialize until the controller is called?
I've tried using WebSecurity.Login() in the place of Membership.ValidateUser() but that doesn't work.
I'm at a loss on how to actually implement this. Does anyone have any advice? Or maybe I'm attempting to tackle this problem from the wrong angle?
You are correct that ASP.NET Membership provider is not compatible with the SimpleMembershipProvider however SimpleMembershipProvider does support ValidateUser, see here. Assuming SimpleMembership is correctly configured and initalised you should still be able to call Membership.ValidateUser().
If you have already tried Membership.ValidateUser() and got an error please let me know and we can try resolve it.
Update
So having followed your reproduction steps I have managed to pin-point an error. Having brought the Thinktecture AuthenticationHandler handler inline and run in debug. 30 seconds after a request to the api controller a database connection error is being raised. This is failing asynchronously and silently.
After some fiddling around I believe it is the DefaultConnection connection string which is at fault.
Like me your default connection probably contains a file name like this:
AttachDBFilename=|DataDirectory|\aspnet-MvcApplication3-20121215104323.mdf"
When ValidateUser is called inside the delegate registered at app start up (for validating the credentials) it appears to be failing to resolve |DataDirectory| I found that by updating this path to the full name my connection problems went away.
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-MvcApplication3-20121215104323;Integrated Security=SSPI;AttachDBFilename=C:\mydatabase\file\path\example\aspnet-MvcApplication-20121215104323.mdf" providerName="System.Data.SqlClient" />
</connectionStrings>
I then found this post here, it indicates that the AppDomain has not had it's data directory set correctly at this point.
So once the config set up and the connection string altered with a proper file path and a user name "test" and a password "testing" this request through fiddler got a 200:
GET http://localhost/api/goober/1
User-Agent: Fiddler
Host: localhost
Authorization: Basic dGVzdDp0ZXN0aW5n
As an aside
I found that to get the forms authorisation token to also allow access to the api controllers I had to add this. Otherwise the Thinkteckture code sets the principle back to anonymous:
Add this
authConfig.InheritHostClientIdentity = true;
To counteract this (line 52):
if (_authN.Configuration.InheritHostClientIdentity == false)
{
//Tracing.Information(Area.HttpAuthentication, "Setting anonymous principal");
SetPrincipal(Principal.Anonymous);
}

.NET Web Service that takes email id as input and searches the Active Directory?

How to write a .NET Web Service that takes email id as input and searches the Active Directory to see if that user exists and returns a flag. I have an userID and Password that is used to query AD. Please describe how to do this and what else do I need?
Using WCF, you can achieve this fairly easily.
Step 1 - define a service contract
This defines your operations that you want, including the parameters they might need. Not knowing what exactly you might need, I just guessed and came up with something like this:
using System.ServiceModel;
namespace SearchAD
{
[ServiceContract]
public interface ISearchADService
{
[OperationContract]
bool EMailAddressExists(string emailAddress);
}
}
Step 2 - implement the service class
This means adding the "meat" to the bone (the service contract) - this is where you actually do what you're trying to do:
using System;
using System.DirectoryServices.AccountManagement;
namespace SearchAD
{
public class SearchADService : ISearchADService
{
public bool EMailAddressExists(string emailAddress)
{
// establish the Active Directory domain context to search in
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "YOURDOMAIN", userName, password);
// define your "query-by-example" user to search for
UserPrincipal qbeUser = new UserPrincipal(ctx);
qbeUser.EmailAddress = emailAddress;
// instantiate the searcher to find that user
PrincipalSearcher findUserByMail = new PrincipalSearcher(qbeUser);
// search for the user - did we find one?
UserPrincipal userByEmail = findUserByMail.FindOne() as UserPrincipal;
return userByEmail != null;
}
}
}
Of course, in this setup - you'll need to get your domain name, the user name and the password (for querying Active Directory) from somewhere - a config file, constants in your service class - whatever works for you!
With this, you basically have your WCF service that takes an e-mail address and searches Active Directory for a user account matching that e-mail address. If found, true is returned - false otherwise.
Now, with your WCF service, you now only need to know how to host it (in IIS or self-hosting), and how to create clients for it to use the service - but that's just very basic WCF know-how, you shouldn't have any trouble finding the necessary infomrmation and tutorials, if you don't have that know-how already !
The mechanism used to search Active Directory is the System.DirectoryServices.AccountManagement namespace, which is part of .NET 3.5 and newer. Read all about it here:
Managing Directory Security Principals in the .NET Framework 3.5
MSDN docs on System.DirectoryServices.AccountManagement

Resources