2015-01-01 9 views
9

WebApiシステムにASP.Net Identity 2を実装しています。新しいアカウントの確認メールを管理するために、私は、カスタムApplicationUserManagerを作成し、それをリクエストごとに作成されるように、それを登録する必要がありました:カスタムUserManagerはOAuthAuthorizationServerProviderでは利用できません

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

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

私が直面してる問題は、私はOAuthのトーク​​ンの作成方法でそれにアクセスしようとする前に、ApplicationUserManager.Createメソッドが呼び出されていないということですGetUserManagerがnullを取得するため、上記のコードでは、

CreatePerOwinContextメソッドがまだ呼び出されていないような方法で、その場合は、ApplicationUserManagerをキャッシュしてGrantResourceOwnerCredentialsの内部で使用できるようにするにはどうすればよいでしょうか?

答えて

14

この1つはトリッキーでした。スタートアップコードは特定の順序で行われなければならないことが判明しました。

このコードは機能します。

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

// 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); 

内NULLになり、ここで誰かをつまずかことができ、別のものです。これらの行は、app.UseWebApi(config); ラインがのOAuth設定の前にある場合ApplicationUserManagerためOwinContextを尋ねるときにもnullが返さ取得することができ

// 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()); 
4

すでにコンテキストを持っているようGrantResourceOwnerCredentialsHttpContext.Current.GetOwinContext()を使用しないでください:あなたがオブジェクトApplicationUserManagerを取得することができるはずですので

var mgr = context.OwinContext.GetUserManager<ApplicationUserManager>(); 

CreatePerOwinContextが要求ごとに作成されます。(OAuthGrantResourceOwnerCredentialsContext context)

は、代わりにこれを行います。 すぐにStartupに電話する必要があります。たぶんあなたのスタートアップの実装が正しくない可能性があります。 私は、実装の詳細についてはhereという回答を書いています。

+0

私もcontext.OwinContextを試してみましたが、それは助けにはなりませんでした。あなたはスタートアップコードとは何か関係があったという正しい軌道にいました。スタートアップコードは特定の順序で実行する必要があります。答えにつながったヒントをありがとう。 – Brian

+0

私の 'OAuthAuthorizationServerProvider'実装のどこかに' UserManager'を置くべきでしょうか? – Shimmy

+1

@Shimmy:その必要はないはずです。 'UserManager'は' IDisposable'を実装し、 'CreatePerOwinContext'は要求に対してのみオブジェクトを登録します。 – LeftyX

1

AuthContextは、トークン生成方法のGrantResourceOwnerCredentialsの内側にヌルにさせます。以下は

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.UseWebApi(config);を移動。UseOAuthメソッドを使用すると、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 
+0

Web APIの初期化を行う前に、すべてのID起動操作を行うことを意味しますか? – Brian

+0

私は答えを言い直すつもりは、それはよく言われていませんでした。私も同じ問題を抱えていましたが、あなたの受け入れられた答えは私を私の解決に導いたのです。私のアプリの前に '; ' HttpContext.Current.GetOwinContext()GetUserManager ();私は 'app.UseWebApi(設定)を持っていた場合 'はnullを返します:私にとって 、すべての呼び出し。。 UseOAuthコール。 移動する 私のOAuthの設定後に 'app.UseWebApi(con​​fig);' to GetUserManager コールが動作するようになります。 あなたの質問に直接答えるためには、それが私のために働く原因でした。 –

+0

チャドは意味をなさない。更新していただきありがとうございます。 – Brian

関連する問題