1. ホーム
  2. asp.net-mvc

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

2023-09-08 09:18:22

質問事項

次のようなアーキテクチャが欲しいのですが(この例では製品名を作りました)。

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などの外部アカウントを登録する以外は、すべて動作します。

を作成するための正しいフローがわかりません。 外部 アカウントを作成する正しいフローがわかりません。

認証の流れについて公開されているほとんどのドキュメントを調べましたが、こんな感じです。

OWINの新しいIdentityモデルについて、できる限りのことを読みました。

私は Visual Studio 2013 で SPA テンプレートを調べました。私が必要とすることのほとんどを行う方法を示していますが、クライアントと API が同じホスト上にある場合のみです。複数のクライアントが私の API にアクセスし、Google などを通じてユーザーがサインアップできるようにしたい場合、うまくいかず、私が知る限り、OWIN 認証フローが壊れています。

ここまでの流れはこんな感じです。

  • ユーザーは www.webpics.com/Login
  • www.webpics.com コール api.prettypictures.com/Account/ExternalLogins (このとき returnUrl でのコールバックに戻るように設定されています。 www.webpics.com にあるコールバックに戻るように設定されています) そして、結果として得られるリンクをユーザーに表示します。
  • ユーザーは "Google"をクリックします。
  • ブラウザは api.prettypictures.com/Account/ExternalLoginにリダイレクトされます。 をプロバイダ名などで指定します。
  • API の ExternalLogin アクションは google.com
  • ブラウザがリダイレクトされる先は google.com
  • ユーザはユーザ名とパスワードを入力します (まだ google.com )
  • グーグルドットコム は、現在、セキュリティクリアランスを提示しています。 "api.prettypictures.com" は、あなたの電子メールアドレス、名前、妻、子供などへのアクセスを希望しています。これはOKですか?
  • ユーザーは "Yep"をクリックし、次のページに移動します。 api.prettypictures.com/Account/ExternalLoginに戻されます。 をクリックすると、Googleが設定したCookieで

ここで私は行き詰ってしまいました。次に起こるはずのことは、何らかの方法でクライアントアプリに、ユーザーが google.com での認証に成功し、後でアクセストークンと交換するための1回限りのアクセスコードが渡されることです。クライアントアプリは、必要であれば、ユーザーがgoogle.comと関連付けるユーザー名を入力する機会を持つべきです。 google.com ログインに関連付けるユーザー名を入力する必要があります。

どうすればスムーズにできるのかわかりません。

実際この時点では、ブラウザは結局 api.prettypictures.com/Account/ExternalLoginに座っています。 エンドポイントに座っています。APIはGoogleのためにサインインしていますが、クライアントはそれを処理する方法を知らないのです。そのクッキーをパイプで www.webpics.com ?

SPAアプリでは、AJAXで行われ google.com は URL 断片としてトークンを返し、すべてが 1 つのドメイン上にあるため、うまく機能します。しかし、これは、複数のクライアントが完全に使用できる API を持つことの重要性の多くを無視しています。

助けてください!

どのように解決するのですか?

更新:1月にこの記事を書いたときとは状況が変わっています。 : MSFT は公式の OpenID connect クライアントミドルウェアをリリースし、私は @manfredsteyer とともに、Katana に組み込まれた OAuth2 認証サーバーを OpenID connect に適応させるべく懸命に働きました。この組み合わせにより、カスタムクライアントコードを必要とせず、標準的なOAuth2/OpenID connectクライアントと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


ジョシュ、あなたは間違いなく正しい道を歩んでいますし、あなたの 委任/フェデレート認証 の実装はかなり良さそうです(私は、あなたが Microsoft.Owin.Security.Facebook/Google/Twitter ).

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

ベストプラクティスは別のプロジェクト(しばしば "AuthorizationServer" と呼ばれる)を作成することですが、個人的には、複数の API にわたって使用することを意図しない場合、私の "API project" に追加することを好みます(ここでは、 "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 ファイルを使って、どのように承認同意書が実装されたかを見るために、遠慮なくプロジェクト全体をブラウズしてください。ASP.NET MVC や NancyFX のような上位のフレームワークを好む場合は、独自の AuthorizationController コントローラと Authorize メソッドを追加し (GET と POST の両方を受け付けるようにしてください)、属性ルーティングを使用して OAuth2 認証サーバーで定義されている AuthorizeEndpointPath に一致させます (例. [Route("oauth2/authorize")] を変更したサンプルです。 AuthorizeEndpointPath を使用するように変更しています。 oauth2/ をパスのベースとして使用します)。

もうひとつ必要なのは、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 , GoogleOAuth2AuthenticatedContextGoogleOAuth2ApplyRedirectContext . これらのファイルをホスティングしているプロジェクトに挿入したら、ファイル名を適宜変更し、認証とアクセストークンのエンドポイント URL を GoogleOAuth2AuthenticationHandler にある認証とアクセストークンのエンドポイント URL を、OAuth2 認証サーバーで定義したものと同じになるように変更します。

次に、リネームした/カスタムの GoogleAuthenticationExtensions をOWINスタートアップ・クラスに追加します。私は AuthenticationMode.Active を使用することをお勧めします。そうすれば、ユーザーはあなたの API OAuth2 認証エンドポイントに直接リダイレクトされることになります。したがって、quot;api.prettypictures.com/Account/ExternalLogins" のラウンドトリップを抑え、OAuth2クライアントミドルウェアが401レスポンスを変更してクライアントをあなたのAPIにリダイレクトさせるようにする必要があります。

幸運を祈ります。そして、より多くの情報が必要な場合は、躊躇しないでください;)