簡體   English   中英

OWIN 的 GetExternalLoginInfoAsync 總是返回 null

[英]OWIN's GetExternalLoginInfoAsync Always Returns null

我創建了一個新的 MVC5 Web 應用程序,當我嘗試使用 Google 或 Facebook 登錄時,會調用AccountControllerExternalLoginCallback Action,但GetExternalLoginInfoAsync()始終返回 null:

var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
    return RedirectToAction("Login");
}

因為它始終為空,所以它只是重定向回登錄頁面並重新開始該過程。 我怎樣才能解決這個問題?

為了讓 OWIN Google 登錄在標准的 Visual Studio 2013、ASP.Net MVC5 站點上正常工作,我必須:

  1. https://console.developers.google.com/project設置 Google OpenId 帳戶

  2. 將那里的回調 URL 設置為blah/signin-google
    關於您不需要做的事情的重要說明:

    • 您不需要使用 HTTPS 來讓 Google 重定向回來; 你甚至可以重定向回普通的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 為您的項目提供的任何端口號。

  1. 啟用 Google+ API 這是一個隱藏的 b****,是這里問題中問題的根本原因 - 如果你不這樣做,很容易錯過對/account/ExternalLoginCallback的請求包含&error=access_denied ,這是因為 Google 拒絕了 OWIN 為用戶的 Google+ 基本個人資料提出的權限請求。 我不知道這是誰的錯,谷歌的還是微軟的。

要在開發人員控制台中啟用 Google+ API,請單擊左側的 API,搜索 Google+,單擊它並點擊啟用。 是的,您確實需要這樣做。 如果你不這樣做,你就會被灌輸。

  1. 將開發者控制台中谷歌給你的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/externallogincallbackexternalloginconfirmation ,因為它們都與/signin-google分開/signin-google和 OWIN/Google 流程中的必要步驟。

好的,我找到了為什么它為空。 您必須在 Google 控制台中啟用 Google + API。 還要確保在將密鑰粘貼到代碼后,密鑰沒有在末尾連接一個空格。 為什么他們不能返回一個正常的錯誤? 我不知道。

似乎 Nuget 包 Microsoft.Owin.Security.Facebook 版本 3.0.1 不再適用於 Facebook 登錄。

將此包更新到預發布 3.1.0 版本,您可以使用以下內容:

安裝包 Microsoft.Owin.Security.Facebook -Pre

正如其他人正確提到的那樣,大多數情況下這是因為您沒有使用 Google+ API 的權限,所以這里是如何在 Google API Manager 中為 Google+ API 獲取項目權限

步驟 1.從頂部組合框中選擇您的項目,然后轉到儀表板 > 啟用 API 在此處輸入圖片說明

第 2 步:搜索 Google plus 並選擇它在此處輸入圖片說明

第 3 步:啟用它! 在此處輸入圖片說明

如果您返回該項目的儀表板,您可以在底部看到該項目的已啟用 API 列表在此處輸入圖片說明

我通過簡單地更新應用程序中的所有 nugget 包來讓它工作,並且它工作正常。

我知道這很愚蠢,但經過長時間的斗爭,重新啟動 IIS 為我解決了這個問題。

這解決了我的問題:

啟用 Google+ API。 這是一個陷阱,是這里問題中問題的根本原因 - 如果你不這樣做,很容易錯過 Request to /account/ExternalLoginCallback包含&error=access_denied ,這是因為谷歌對 a 說不OWIN 為用戶的 Google+ 基本個人資料提出的權限請求。 我不知道這是誰的錯,谷歌的還是微軟的。

要在開發人員控制台中啟用 Google+ API,請單擊左側的 API,搜索 Google+,單擊它並點擊啟用。

我做了以下工作來讓它工作。

登錄開發人員門戶,找到您的應用程序並執行以下操作。

應用詳情 > 以應用為中心的上市平台 > 為網站選擇是

我今天遇到了這個問題,結果是我在分配提供程序后定義了遠程 cookie。

確保你放置...

app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

前...

app.UseFacebookAuthentication(
                   appId: "",
                   appSecret: "");

對於那些在 Web Api 上遇到此問題的人。 其他解決方案沒有幫助AuthenticationManager.GetExternalLoginInfoAsync(); 即使啟用了 google plus api,也始終返回 null。

使用此自定義函數獲取登錄信息。 顯然,當通過 Web api 請求時,Microsoft 有一個 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;
        }

盡管上面的答案都很好,但在我的例子中,這些都沒有奏效 - 我檢查並仔細檢查了 Google 設置,並同意 Chris Moschini 的觀點,即存在很多誤導性信息。

對我來說,當我意識到我的進程外狀態服務沒有啟動時,真是太棒了! 沒有錯誤(因為登錄是我在重新啟動后嘗試的第一件事,其中狀態服務設置為在機器上手動啟動)只是來自GetExternalLoginInfoAsync的 Null

希望這可以幫助其他人。

經過大量搜索和摸索,並在 Stackoverflow 上遵循了無數的紅鯡魚答案后,我最終在我的 Google 開發控制台上瀏覽了所有選項,並在 Google+API 概述頁面上發現了一個藍色的 [啟用] 按鈕。 我點擊了這個,嘿,它很快就起作用了。 忘記您閱讀的有關回調 url 和路由配置的所有廢話,OWIN 在任何情況下都會覆蓋谷歌默認的 /signin-google 重定向 uri,並將您發送回 ExternalLoginCallback。 只要堅持使用默認實現,只要您啟用 Google+API,一切都會好起來的。

我也想為此做出貢獻。 我最近才開始工作。 我遇到了 GetExternalLoginInfoAsync 返回 null 但僅在生產中存在的問題。

經過大量搜索,我終於找到了答案,這只是我的數據庫有問題。 在生產中,我設置了錯誤的連接字符串,因此無法正確連接,但它基本上對此保持沉默。 唯一發生的事情是 GetExternallLoginInfoAsync 返回 null。 因此,如果發生這種情況,請檢查數據庫連接字符串!

同樣在旁注中,要使這項工作正常進行,唯一需要的是:

  • 在 Google 控制台中設置項目
  • 啟用 Google+ API
  • 將您的客戶端 ID 和客戶端密碼復制到 Startup.Auth.cs 文件。

您不必啟用 HTTPS,也不必創建自定義路由。 但請確保您的數據庫工作正常!

確實,您將需要啟用 Google plus。 對我來說最重要的是項目 URL。 在 VS 中打開屬性窗口(查看 -> 屬性窗口),然后右鍵單擊項目並選擇屬性。 在小的屬性窗口中復制您的 SSL URL,然后在較大的屬性窗口中選擇 Web 選項卡並將該 URL 粘貼到項目 URL 中。

為我解決了這個問題。

更詳細地查看: https : //docs.microsoft.com/en-us/aspnet/mvc/overview/security/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and -openid 登錄

對我來說,我正在遷移和舊但工作 .NET 4.6.1 MVC 網站到核心 1.1。 工作在我開始工作之前就停止了,當我把它拿回來時,我正在遷移到 2.x。

我的問題是來自 Google 的回調遇到了來自我網站的404 我認為它應該命中AccountController.ExternalLoginCallback所以我添加了一個[Route(...)]到它,果然,谷歌的回調命中了這個動作。

這然后打null該行返回(什么樣的瘋子回報的null ?)

var externalLoginInfo = await this.SignInManager.GetExternalLoginInfoAsync();

我對其進行了逆向工程,以發現它最終獲得了ExternalScheme的處理程序,而我的則是 cookie 處理程序!

這一切似乎都錯了,我覺得中間件應該只是攔截回調 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 上的代碼)。 有趣的是, hCookieAuthenticationHandler類型,而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 標識位,我確實找到了一些仍在使用這些東西的示例,以及一些使用 Razor Pages 的示例。 我會繼續我所擁有的。

所以我接下來要研究將額外的 Google 用戶 JSON 有效負載項目映射到聲明中。 我想如果我的 Google 帳戶 ID(我猜是數字)被映射,那么一切都會正常。

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/additional-claims?view=aspnetcore-2.2

最終修復

我終於通過添加一個“聲明操作”來解決這個問題,將我的谷歌標識符從谷歌返回的 JSON 中提取出來!

serviceCollection.AddAuthentication(IdentityConstants.ExternalScheme)
    .AddGoogle(googleOptions =>
    {
        Configuration.Bind("OAuth2:Providers:Google", googleOptions);

        googleOptions.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub", "string");
    })
    .AddExternalCookie();

sub字段包含最終以nameidentifier聲明結束的nameidentifier ,然后包含在AccountController想要的ProviderKey中。

在我的情況下,解決方案是更新 Nuget 包 Microsoft.Owin.Security 和 Microsoft.Owin.Security.Google

所有其他答案都沒有為我解決這個問題,因此如果您在同一條船上,請確保您的注冊控制器操作具有 RequireHttps 屬性:

    // GET: /Account/LoginRegister
    [AllowAnonymous]
    [RequireHttps]
    public ActionResult LoginRegister()
    {
        return View(new RegisterLoginViewModel());
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM