Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom UserManager not available in OAuthAuthorizationServerProvider

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 ?

like image 426
Brian Avatar asked Jan 01 '15 15:01

Brian


1 Answers

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());
like image 193
Brian Avatar answered Oct 21 '22 13:10

Brian