I'm implementing ASP.Net Identity 2 in a WebApi system. To manage email confirmation for new accounts, I had to create a custom ApplicationUserManager
and register it so that it would be created for every request:
public class IdentityConfig{
public static void Initialize(IAppBuilder app)
{
[snip]
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
}
It works correctly inside an ApiController like this:
public class AccountController : ApiController
{
public ApplicationUserManager UserManager
{
get
{
return HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
}
The problem I'm facing is that the ApplicationUserManager.Create
method is not being called before I try to access it in the OAuth Token creation method:
public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var mgr = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
In the above code, mgr is null because GetUserManager retrieves null
Is the token creation method somehow earlier in the pipeline such that the CreatePerOwinContext
methods haven't beeen called yet? If so, what's the best way cache an ApplicationUserManager
so that it can be used inside GrantResourceOwnerCredentials
?
This one was tricky. It turns out that the startup code has to be done in a certain order.
This code will work.
public class IdentityConfig{
public static void Initialize(IAppBuilder app)
{
// correct... first create DB context, then user manager, then register OAuth Provider
app.CreatePerOwinContext(AuthContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider()
};
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
If you change the order of how you register the code with the app, you can get unintended consequences. This code causes ApplicationUserManager to be null inside the token generation method GrantResourceOwnerCredentials
// wrong... these two lines must be after the ApplicationUserManager.Create line
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
[snip]
app.CreatePerOwinContext(AuthContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
While I'm at it, here's another thing that could trip someone up. These lines cause AuthContext to be null inside of the token generation method GrantResourceOwnerCredentials
// wrong... The AuthContext must be instantiated before the ApplicationUserManager
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext(AuthContext.Create);
[snip]
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());