web-dev-qa-db-ja.com

OWIN Identityを使用して複数のAPIクライアントからWeb API 2外部ログインを登録する

次のアーキテクチャが必要です(この例では製品名を作成しました)。

1台のサーバーで実行されているWeb API 2アプリケーションhttp://api.prettypictures.com

別のサーバーで実行されているMVC 5クライアントアプリhttp://www.webpics.com

www.webpics.comクライアントアプリでPretty Pictures APIを使用して、次のことを行いたい:

  • ユーザー名とパスワードで新しいアカウントを登録する
  • Facebook/Google/Twitter/Microsoftに新しいアカウントを登録します
  • ログイン
  • 写真を取得する

Facebook、Googleなどに外部アカウントを登録することを除いて、上記のすべてが機能します。

APIの別のクライアントユーザーからexternalアカウントを作成する正しいフローを作成できません。

次のように、認証フローで利用可能なほとんどのドキュメントを調査しました。 enter image description here

OWINの新しいIdentityモデルでできることはほとんどすべて読みました。

Visual Studio 2013でSPAテンプレートを調べました。これは、クライアントとAPIが同じホスト上にある場合にのみ、必要なほとんどのことを行う方法を示しています。複数のクライアントが自分のAPIにアクセスし、ユーザーがGoogleなどを介してサインアップできるようにしたい場合は機能しません。また、OWIN認証フローが中断することを伝えることができます。

これまでの流れは次のとおりです。

  • ユーザーはwww.webpics.com/Loginを参照します
  • www.webpics.com呼び出しapi.prettypictures.com/Account/ExternalLoginsreturnUrl www.webpics.com)のコールバックに戻るように設定し、結果のリンクをユーザーに表示します
  • ユーザーが「Google」をクリックします
  • ブラウザーは、プロバイダーの名前などを使用してapi.prettypictures.com/Account/ExternalLoginにリダイレクトします。
  • APIのExternalLoginアクションは、google.comへのチャレンジをインスタンス化します
  • ブラウザはgoogle.comにリダイレクトされます
  • ユーザーはユーザー名とパスワードを入力します(まだログインしていない場合google.com
  • google.comはセキュリティクリアランスを提示します: "api.prettypictures.com"はあなたのメールアドレス、名前、妻、子供などへのアクセスを希望します。これでいい?
  • ユーザーが「はい」をクリックすると、Googleが設定したCookieを使用してapi.prettypictures.com/Account/ExternalLoginに戻ります。

これは私が立ち往生しているところです。次に何が起こるかは、ユーザーがgoogle.comで正常に認証されたことをクライアントアプリに通知し、アクセストークンを交換するための使い捨てのアクセスコードを与える必要があることです。後で。クライアントアプリには、必要に応じて、ユーザーにgoogle.comログインに関連付けるユーザー名の入力を求める機会があります。

これを容易にする方法がわかりません。

実際、この時点でブラウザーは、Googleからのコールバックの後、api.prettypictures.com/Account/ExternalLoginエンドポイントに座っています。 APIはGoogleにサインインしていますが、クライアントはそれを処理する方法を知りません。そのCookieをwww.webpics.comにパイプで戻す必要がありますか?

SPAアプリでは、AJAXを介して行われ、google.comはURLフラグメントとしてトークンを返します。すべてが1つのドメインにありますが、複数のクライアントが完全に使用できる「API」を持っているという点の多くに反しています。

助けて!

74
joshcomley

更新:1月にこの投稿を書いてから状況が変化しました:MSFTは公式のOpenID接続クライアントミドルウェアをリリースし、@ AuthN2カタナに組み込まれた認可サーバーからOpenIDへの接続。この組み合わせにより、カスタムクライアントコードを必要とせず、標準のOAuth2/OpenID接続クライアントと100%互換性のある、はるかに簡単で強力なソリューションが実現します。 1月に述べたさまざまな手順は、わずか数行で置き換えることができます。

サーバー:

_app.UseOpenIdConnectServer(options =>
{
    options.TokenEndpointPath = new PathString("/connect/token");
    options.SigningCredentials.AddCertificate(certificate);

    options.Provider = new CustomOpenIdConnectServerProvider();
});
_

クライアント:

_app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    Authority = "http://localhost:55985/",

    ClientId = "myClient",
    ClientSecret = "secret_secret_secret",
    RedirectUri = "http://localhost:56854/oidc"
});
_

GitHubリポジトリですべての詳細(および異なるサンプル)を見つけることができます。

https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server

https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/tree/dev/samples/Nancy


ジョシュ、あなたは間違いなく正しい軌道に乗っており、あなたの委任/統合認証実装はかなり良いようです(事前定義されたOWINミドルウェアを使用したと思います_Microsoft.Owin.Security.Facebook/Google/Twitter_)から。

必要なことは、独自のカスタムOAuth2許可サーバーを作成することです。これを実現するためのオプションはたくさんありますが、おそらく最も簡単な方法は、OWINスタートアップクラスにOAuthAuthorizationServerMiddlewareをプラグインすることです。 _Microsoft.Owin.Security.OAuth_ Nugetパッケージにあります。

ベストプラクティスは個別のプロジェクト(「AuthorizationServer」と呼ばれることが多い)を作成することですが、複数のAPIで使用することを意図していない場合、個人的に「APIプロジェクト」に追加することを好みます(ここでは、挿入する必要があります) 「api.prettypictures.com」をホストしているプロジェクトで)。

Katanaリポジトリにすばらしいサンプルがあります。

https://katanaproject.codeplex.com/SourceControl/latest#tests/Katana.Sandbox.WebServer/Startup.cs

_app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
    AuthorizeEndpointPath = new PathString("/oauth2/authorize"),
    TokenEndpointPath = new PathString("/oauth2/token"),
    ApplicationCanDisplayErrors = true,

    AllowInsecureHttp = true,

    Provider = new OAuthAuthorizationServerProvider
    {
        OnValidateClientRedirectUri = ValidateClientRedirectUri,
        OnValidateClientAuthentication = ValidateClientAuthentication,
        OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
    },
    AuthorizationCodeProvider = new AuthenticationTokenProvider
    {
        OnCreate = CreateAuthenticationCode,
        OnReceive = ReceiveAuthenticationCode,
    },
    RefreshTokenProvider = new AuthenticationTokenProvider
    {
        OnCreate = CreateRefreshToken,
        OnReceive = ReceiveRefreshToken,
    }
});
_

単純なRazorファイルを使用して承認同意フォームがどのように実装されているかを確認するために、プロジェクト全体を参照することをheしないでください。 ASP.NET MVCやNancyFXなどの高レベルのフレームワークを好む場合は、独自のAuthorizationControllerコントローラーとAuthorizeメソッドを作成し(GETとPOSTの両方を受け入れてください)、属性ルーティングを使用して一致させますOAuth2承認サーバーで定義されたAuthorizeEndpointPath(つまり、サンプルの[Route("oauth2/authorize")]AuthorizeEndpointPathを変更して、パスベースとして_oauth2/_を使用しています)。

もう1つ必要なことは、WebアプリにOAuth2認証クライアントを追加することです。残念ながら、Katanaには一般的なOAuth2クライアントのサポートがないため、独自に構築する必要があります。個人的にKatanaチームに提案を提出しましたが、拒否されました。しかし、パニックにならないでください、それはやや簡単です:

そこにあるMicrosoft.Owin.Security.Googleリポジトリから適切なファイルをコピーします。 https://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationHandler.cs =

_GoogleOAuth2AuthenticationHandler_、_GoogleOAuth2AuthenticationMiddleware_、_GoogleOAuth2AuthenticationOptions_、GoogleAuthenticationExtensions(Google OpenID実装に対応する最初の2つのメソッドを削除する必要があります)、_IGoogleOAuth2AuthenticationProvider_、_GoogleOAuth2ReturnEndpointContext_、_GoogleOAuth2AuthenticationProvider_、_GoogleOAuth2AuthenticatedContext_および_GoogleOAuth2ApplyRedirectContext_。 「webpics.com」をホストしているプロジェクトにこれらのファイルを挿入したら、それに応じて名前を変更し、OAuth2承認サーバーで定義したものと一致するように_GoogleOAuth2AuthenticationHandler_の承認およびアクセストークンエンドポイントURLを変更します。

次に、名前を変更したカスタムGoogleAuthenticationExtensionsからUseメソッドをOWINスタートアップクラスに追加します。ユーザーがAPI OAuth2承認エンドポイントに直接リダイレクトされるように、_AuthenticationMode.Active_を使用することをお勧めします。したがって、「api.prettypictures.com/Account/ExternalLogins」ラウンドトリップを抑制し、OAuth2クライアントミドルウェアが401応答を変更してクライアントをAPIにリダイレクトするようにする必要があります。

がんばろう。さらに情報が必要な場合は、;しないでください;)

46
Pinpoint