自定义UserManager在OAuthAuthorizationServerProvider中不可用

时间:2015-01-01 15:06:01

标签: asp.net-identity asp.net-identity-2

我在WebApi系统中实现ASP.Net Identity 2。要管理新帐户的电子邮件确认,我必须创建一个自定义ApplicationUserManager并注册它,以便为每个请求创建它:

public class IdentityConfig{
    public static void Initialize(IAppBuilder app)
    {
        [snip]
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    }

它在ApiController中正常工作,如下所示:

public class AccountController : ApiController
{
    public ApplicationUserManager UserManager
    {
        get
        {
            return HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
        }
    }

我遇到的问题是在我尝试在OAuth令牌创建方法中访问它之前未调用ApplicationUserManager.Create方法:

public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        var mgr = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();

在上面的代码中,mgr为null,因为GetUserManager检索null

令牌创建方法是否在某种程度上早于管道中,以便CreatePerOwinContext方法尚未被调用?如果是这样,那么缓存ApplicationUserManager以便在GrantResourceOwnerCredentials内使用它的最佳方式是什么?

3 个答案:

答案 0 :(得分:14)

这个很棘手。事实证明,启动代码必须按特定顺序完成。

此代码可以使用。

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());
    }
}

如果您更改了使用应用程序注册代码的顺序,则可能会产生意想不到的后果。此代码导致ApplicationUserManager在令牌生成方法GrantResourceOwnerCredentials

中为null
// 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);

虽然我在这里,但另一件事可能会让某人绊倒。这些行导致AuthContext在令牌生成方法内为null 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());

答案 1 :(得分:4)

不要在HttpContext.Current.GetOwinContext()中使用GrantResourceOwnerCredentials,因为您已有上下文:(OAuthGrantResourceOwnerCredentialsContext context)

而是这样做:

var mgr = context.OwinContext.GetUserManager<ApplicationUserManager>();
为每个请求创建了

CreatePerOwinContext,因此您应该能够获取对象ApplicationUserManager。 它应该立即在Startup调用。也许你的启动实现不正确。 我写了一个答案here,其中包含一些实施细节。

答案 2 :(得分:1)

如果app.UseWebApi(config);询问ApplicationUserManager的OwinContext,也可以返回null line是在Oauth设置之前。

以下内容会导致大多数来电 HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();

返回null。

        HttpConfiguration config = new HttpConfiguration();

        WebApiConfig.Register(config);
        app.UseWebApi(config); <-- Bad location

        OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
            Provider = new ApplicationOAuthProvider("clientId"),
            RefreshTokenProvider = new SimpleRefreshTokenProvider()
        };

        app.UseOAuthAuthorizationServer(OAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
        app.UseOAuthBearerTokens(OAuthOptions);

在app.UseOAuth方法下方移动app.UseWebApi(config);将允许您从OwinContext获取ApplicationUserManager。

这对我有用:

        HttpConfiguration config = new HttpConfiguration();
        WebApiConfig.Register(config);

        OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
            Provider = new ApplicationOAuthProvider("clientId"),
            RefreshTokenProvider = new SimpleRefreshTokenProvider()
        };

        app.UseOAuthAuthorizationServer(OAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
        app.UseOAuthBearerTokens(OAuthOptions);

        app.UseWebApi(config); // <- Moved