新しいMVC5 Webアプリケーションを作成しました。GoogleまたはFacebookでログインしようとすると、ExternalLoginCallback
のAccountController
アクションが呼び出されますが、GetExternalLoginInfoAsync()
は常に返されますヌル:
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
return RedirectToAction("Login");
}
常にnullであるため、ログインページにリダイレクトされ、プロセスが最初からやり直されます。どうすれば修正できますか?
OWINのGoogleログインを取得して、標準のVisual Studio 2013、ASP.Net MVC5サイトで適切に機能させるには、次のことを行う必要がありました。
https://console.developers.google.com/project でGoogle OpenIdアカウントを設定します
コールバックURLを_blah/signin-google
_に設定します。
あなたがしてはいけないことに関する重要な注意事項:
GoogleにHTTPSを使用してリダイレクトする必要はありません。プレーンな http:// localhost にリダイレクトすることもできます。問題ありません。
リダイレクトURLに何も設定する必要はありません-Web.Configにルート、コントローラーアクション、または特別なアクセス許可はありません。リダイレクトURLは常に/ signin-googleであり、OWINはこれをバックグラウンドで処理します。
例として、サイトがme.comの場合、Google Developer Consoleに次の3つのコールバックURLがあります。
_http://localhost:53859/signin-google
http://test.me.com/signin-google
https://me.com/signin-google
_
VSがプロジェクトに提供したポート番号を含む最初のもの。
/account/ExternalLoginCallback
_へのリクエストに_&error=access_denied
_。これは、OWINがユーザーのGoogle+基本プロファイルに対して行った許可要求に対してGoogleがノーと言ったためです。これが誰のせいなのか、GoogleとMicrosoftのどちらが原因なのかわかりません。デベロッパーコンソールでGoogle+ APIを有効にするには、左側の[API]をクリックし、Google +を探してクリックし、[有効にする]をクリックします。はい、本当にそうする必要があります。 そうしないとうんざりです
GoogleがDevelopers Consoleで提供したClientIdとClientSecretをStartup.Authに追加しますが、OAuth2を明示的に使用し、ユーザーのメールアドレスを明示的に要求するようにプロセスのコードを改善します。
_var google = new GoogleOAuth2AuthenticationOptions()
{
ClientId = "123abc.apps.googleusercontent.com",
ClientSecret = "456xyz",
Provider = new GoogleOAuth2AuthenticationProvider()
};
google.Scope.Add("email");
app.UseGoogleAuthentication(google);
_
それでおしまい。それがついに機能しました。
もう一度繰り返しますが、OWIN/Googleが機能しておらず、現在のVS2013/MVC5/OWINテンプレートではほとんどすべてが間違っているという点で、これに関する多くの回答があります。
Web.Configを変更する必要はまったくありません。
特別なルートを作成する必要はありません。
_/signin-google
_を別の場所にポイントしたり、別のコールバックURLを使用したりしないでください。また、_/account/externallogincallback
_またはexternalloginconfirmation
に直接結び付けないでください。 _/signin-google
_とOWIN/Googleプロセスで必要な手順の両方が異なります。
OK、なぜnullなのかがわかりました。 GoogleコンソールでGoogle + APIを有効にする必要があります。また、秘密鍵をコードに貼り付けた後、秘密鍵が最後にスペースで連結されていないことを確認してください。なぜ通常のエラーを返せないのですか?知りません。
NugetパッケージMicrosoft.Owin.Security.Facebookバージョン3.0.1はFacebook Loginで動作しなくなったようです。
このパッケージをプレリリース3.1.0バージョンに更新すると、次を使用できます。
インストールパッケージMicrosoft.Owin.Security.Facebook -Pre
これは私の問題を解決しました:
Google+ APIを有効にします。これは落とし穴であり、ここでの質問の問題の根本的な原因です。これを行わないと、/account/ExternalLoginCallback
へのリクエストに&error=access_denied
が含まれていることを簡単に見逃してしまいます。 OWINがユーザーのGoogle+基本プロファイル用に作成した許可要求に対していいえ。これが誰のせいなのか、GoogleとMicrosoftのどちらなのかわかりません。
デベロッパーコンソールでGoogle+ APIを有効にするには、左側の[API]をクリックし、Google +を探してクリックし、[有効にする]をクリックします。
私はそれがばかげていることを知っていますが、長い闘争の後、IISを再起動すると問題が解決しました。
アプリケーション内のすべてのナゲットパッケージを更新するだけで機能するようになり、機能しました。
Web Apiでこの問題が発生している人向け。他の解決策は、Google Plus APIが有効になっていてもAuthenticationManager.GetExternalLoginInfoAsync();
が常にnullを返すのを助けません。
このカスタム関数を使用してlogininfoを取得します。明らかに、MicrosoftはWeb API経由でリクエストするときにGetExternalLoginInfoAsyncのバグを持っています。
private async Task<ExternalLoginInfo> AuthenticationManager_GetExternalLoginInfoAsync_WithExternalBearer()
{
ExternalLoginInfo loginInfo = null;
var result = await Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ExternalBearer);
if (result != null && result.Identity != null)
{
var idClaim = result.Identity.FindFirst(ClaimTypes.NameIdentifier);
if (idClaim != null)
{
loginInfo = new ExternalLoginInfo()
{
DefaultUserName = result.Identity.Name == null ? "" : result.Identity.Name.Replace(" ", ""),
Login = new UserLoginInfo(idClaim.Issuer, idClaim.Value)
};
}
}
return loginInfo;
}
今日この問題に出くわし、プロバイダーを割り当てた後にリモートCookieを定義したことがわかりました。
必ず配置してください...
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
前...
app.UseFacebookAuthentication(
appId: "",
appSecret: "");
私はそれを機能させるために次のことをしました。
開発者ポータルにログオンし、アプリケーションを見つけて以下を実行します。
私にとっては、古い移行ですが、.NET 4.6.1 MVC Webサイトをコア1.1に移行していました。動作する前に作業が停止し、バックアップを選択すると、2.xに移行していました。
私の問題は、Googleからのコールバックが私のサイトからの_404
_に遭遇したことでした。 _AccountController.ExternalLoginCallback
_をヒットするはずだと思ったので、それに[Route(...)]
を追加し、Googleのコールバックがアクションをヒットしたことを確認しました。
次に、この行で返されたnull
をヒットします(どのようなマニアがnull
を返しますか?)
_var externalLoginInfo = await this.SignInManager.GetExternalLoginInfoAsync();
_
私はそれをリバースエンジニアリングし、最終的にExternalScheme
のハンドラーを取得するようにしました。
それはすべて間違っているように見え、ミドルウェアはコールバックURIをインターセプトするだけであると感じたため、[Route(...)]
を削除し、_404
_の問題が戻ってきました。
その後、起動時にこれを追加する必要があることがわかりました。
_applicationBuilder.UseAuthentication();
_
これにより_404
_は解決されますが、別の問題が発生します。
AuthenticationSchemeが指定されておらず、DefaultSignInSchemeが見つかりませんでした。
ここにデフォルトのスキームを追加することにより、上記のエラーを解決します。
_serviceCollection.AddAuthentication(IdentityConstants.ExternalScheme)
.AddGoogle(googleOptions => Configuration.Bind("OAuth2:Providers:Google", googleOptions))
.AddExternalCookie();
_
これで_AccountController.ExternalLoginCallback
_が何らかの魔法によって再び呼び出されますが、null
戻り値に戻ります。
このコードを問題のある行の上に追加しました。これは基本的に内部で行われていることです(GitHubでMicrosoftのコードを見て)。興味深いことに、h
はCookieAuthenticationHandler
型であり、a
にはGoogleからの私の主張と情報がすべて含まれています!
_var authHandler = this.HttpContext.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
var h = await authHandler.GetHandlerAsync(this.HttpContext, IdentityConstants.ExternalScheme);
var a = await h.AuthenticateAsync();
var externalLoginInfo = await this.SignInManager.GetExternalLoginInfoAsync();
_
GitHubを掘り下げて、実行中の内部コードをコピーしてコントローラーにコピーすると、クレームで_ClaimTypes.NameIdentifier
_が見つからないことがわかります。これは後で使用されるProviderKey
です。
うーん...
古い1.x AccountController
コードと新しい2.x識別ビットを使用していたのではないかと心配していました。私が持っているものを続けます。
そこで、次に、追加のGoogleユーザーJSONペイロードアイテムをクレームにマッピングすることを調査します。私のGoogleアカウントID(数値、私が推測する)がマップされていれば、すべてが機能すると思います。
最終修正
「クレームアクション」を追加して、Googleから返されるJSONからGoogle識別子を引き出すことで、問題を最終的に解決しました。
_serviceCollection.AddAuthentication(IdentityConstants.ExternalScheme)
.AddGoogle(googleOptions =>
{
Configuration.Bind("OAuth2:Providers:Google", googleOptions);
googleOptions.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub", "string");
})
.AddExternalCookie();
_
sub
フィールドには、最終的にnameidentifier
クレームで終わり、ProviderKey
が必要とするAccountController
に至るものが含まれます。
Google plus Enabledが必要になるのは事実です。私にとって大きなことは、プロジェクトのURLでした。 VSでプロパティウィンドウ([表示]-> [プロパティウィンドウ])を開き、プロジェクトを右クリックしてプロパティを選択します。小さなプロパティウィンドウでSSL URLをコピーし、大きなプロパティウィンドウで[Web]タブを選択して、そのURLをプロジェクトURLに貼り付けます。
私の問題を修正しました。
上記の答えはすべて良いですが、私の場合、これらはどれも機能しませんでした-Googleの設定を確認して再確認し、Chris Moschiniに多くの誤解を招く情報があることに同意しました。
私にとっては、アウトオブプロセス状態サービスが開始されなかった! GetExternalLoginInfoAsync
からのNullだけで、エラーは発生しません(ログインは、ステートサービスがマシンで手動起動に設定されているリブート後に最初に試行したものでした)
これが誰かの助けになることを願っています。
私もこれに貢献したかった。私は最近これを機能させました。 GetExternalLoginInfoAsyncがnullを返す問題がありましたが、本番環境でのみ問題がありました。
多くの検索の後、私は最終的に私のデータベースの問題であるという答えを見つけました。本番環境では、正しく接続されないように間違った接続文字列を設定していましたが、基本的には無音でした。発生した唯一のことは、GetExternallLoginInfoAsyncがnullを返したことです。そのため、データベース接続文字列を確認してください。
また、補足として、これを機能させるために必要なことは次のとおりです。
HTTPSを有効にする必要はありません。カスタムルートを作成する必要もありません。ただし、データベースが正常に機能していることを確認してください!
Stackoverflowで多くの検索と頭をひっくり返し、多数の赤いニシンの答えをたどった後、最終的にGoogle開発コンソールのすべてのオプションを確認し、Google + APIの概要ページに小さな青い[有効]ボタンを見つけました。私はこれをクリックして、それがうまくいったと言った。コールバックURLとルート設定について読んだすべてのバロニーを忘れて、OWINはいずれの場合もgoogleデフォルト/ signin-googleリダイレクトuriをオーバーライドし、ExternalLoginCallbackに送り返します。デフォルトの実装に固執するだけで、Google + APIを有効にすればすべて問題ありません。