Ответ 1
Я забыл включить "Google + API" в консоли разработчика Google. Вход в Google выглядит нормально, но GetExternalLoginInfoAsync возвращает null.
Вы можете перейти по этой ссылке fooobar.com/questions/239028/...
Я пытаюсь устранить прерывистую проблему при использовании Google в качестве внешнего поставщика входа.
При попытке входа в систему пользователь перенаправляется обратно на страницу входа, а не на проверку подлинности.
Проблема возникает в этой строке (строка 55 ссылки ниже), GetExternalIdentityAsync возвращает null.
var externalIdentity = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
Полный код:
[Authorize]
public abstract class GoogleAccountController<TUser> : Controller where TUser : Microsoft.AspNet.Identity.IUser
{
public IAuthenticationManager AuthenticationManager
{
get
{
return HttpContext.GetOwinContext().Authentication;
}
}
public abstract UserManager<TUser> UserManager { get; set; }
[AllowAnonymous]
[HttpGet]
[Route("login")]
public ActionResult Login(string returnUrl)
{
ViewData.Model = new LoginModel()
{
Message = TempData["message"] as string,
Providers = HttpContext.GetOwinContext().Authentication.GetExternalAuthenticationTypes(),
ReturnUrl = returnUrl
};
return View();
}
[AllowAnonymous]
[HttpPost]
[ValidateAntiForgeryToken]
[Route("login")]
public ActionResult Login(string provider, string returnUrl)
{
return new ChallengeResult(provider, Url.Action("Callback", "Account", new { ReturnUrl = returnUrl }));
}
[AllowAnonymous]
[Route("authenticate")]
public async Task<ActionResult> Callback(string returnUrl)
{
var externalIdentity = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
if (externalIdentity == null)
{
return RedirectToAction("Login", new { ReturnUrl = returnUrl });
}
var emailAddress = externalIdentity.FindFirstValue(ClaimTypes.Email);
var user = await UserManager.FindByNameAsync(emailAddress);
if (user != null)
{
await SignInAsync(user, false);
return RedirectToLocal(returnUrl);
}
else
{
TempData.Add("message", string.Format("The account {0} is not approved.", emailAddress));
return RedirectToAction("Login", new { ReturnUrl = returnUrl });
}
}
[HttpPost]
[ValidateAntiForgeryToken]
[Route("logout")]
public ActionResult Logout(string returnUrl)
{
AuthenticationManager.SignOut();
return RedirectToLocal(returnUrl);
}
private async Task SignInAsync(TUser user, bool isPersistent)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
var authenticationProperties = new AuthenticationProperties()
{
IsPersistent = isPersistent
};
AuthenticationManager.SignIn(authenticationProperties, identity);
}
private ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
protected override void Dispose(bool disposing)
{
if (disposing && UserManager != null)
{
UserManager.Dispose();
UserManager = null;
}
base.Dispose(disposing);
}
}
Что также здесь.
Это очень непростая проблема, и повторное развертывание приложения часто заставит его работать временно.
Глядя в Fiddler, я вижу, что вызов выполняется для подписывания google перед предыдущим методом проверки подлинности, в котором он не может найти файл cookie.
Приложение использует следующий код для инициализации входа в google
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/login")
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseGoogleAuthentication();
Я установил режим проверки подлинности не в файл web.config и удалил модуль проверки форм.
<system.web>
<authentication mode="None" />
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<remove name="FormsAuthenticationModule" />
</modules>
</system.webServer>
Сайты размещены на Azure, некоторые из них работают на одном экземпляре, а некоторые - на 2. У них есть пользовательские домены, хотя они по-прежнему терпят неудачу как в домене пользовательского домена, так и в домене azurewebsites и http/https.
Может ли кто-нибудь помочь, почему это может произойти?
Обновление
Версия 3.0 Microsoft.Owin.Security.Google была выпущена прошлой ночью. Переходим к переходу и видим, устраняет ли это проблему.
https://www.nuget.org/packages/Microsoft.Owin.Security.Google
Я забыл включить "Google + API" в консоли разработчика Google. Вход в Google выглядит нормально, но GetExternalLoginInfoAsync возвращает null.
Вы можете перейти по этой ссылке fooobar.com/questions/239028/...
Том. Я использую google-oauth в моем приложении asp.net с помощью REST API. он работает нормально, и я не сталкиваюсь с проблемами связи.
Следующие шаги, которые я выполняю:
1. Я создал один проект в консоли разработчика Google, в котором я создал настройки "Идентификатор клиента для веб-приложения", который будет содержать следующие параметры.
a) Идентификатор клиента = > Он будет автоматически сгенерирован Google b) Адрес электронной почты = > Он будет автоматически сгенерирован Google c) Клиентский секрет = > Он будет автоматически сгенерирован Google d) Перенаправить URIs = > Необходимо указать URL-адрес веб-страницы, который будет использоваться для обработки процесса аутентификации. На этой странице мы можем аутентифицироваться, и мы можем получить основную информацию пользователя.
my url: "http://localhost:1822/WebForm1.aspx/code"
Я установил стартовую страницу "Webpage2.aspx" , и я формирую открытый auth url в "Webpage2.aspx" и перенаправляю на страницу входа в google.
После входа в систему он будет перенаправлен на "Webpage1.aspx" вместе с кодом доступа. Пропустив этот код доступа на " https://accounts.google.com/o/oauth2/token" url, я получаю токен доступа вместе с типом токена и временем истечения маркера. После этого, передав этот доступ к URL-адресу https://www.googleapis.com/oauth2/v2/userinfo, я получаю базовую информацию пользователя, такую как "электронная почта, имя, пол, фотография", и т.д.)
public class GoogleAuthorizationData
{
public string access_token { get; set; }
public int expires_in { get; set; }
public string token_type { get; set; }
}
public class GoogleUserInfo
{
public string name { get; set; }
public string family_name { get; set; }
public string gender { get; set; }
public string email { get; set; }
public string given_name { get; set; }
public string picture { get; set; }
public string link { get; set; }
public string id { get; set; }
}
Webpage1.aspx
============
protected void Page_Load(object sender, EventArgs e)
{
string code = Request.QueryString["code"].ToString();
string scope = Request.QueryString["scope"].ToString();
string url = "https://accounts.google.com/o/oauth2/token";
string postString = "code=" + code + "&client_id=" + ConfigurationManager.AppSettings["GoogleClientID"].ToString() + "&client_secret=" + ConfigurationManager.AppSettings["GoogleSecretKey"].ToString() + "&redirect_uri=" + ConfigurationManager.AppSettings["ResponseUrl"].ToString() + "&grant_type=authorization_code";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url.ToString());
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
UTF8Encoding utfenc = new UTF8Encoding();
byte[] bytes = utfenc.GetBytes(postString);
Stream os = null;
try
{
request.ContentLength = bytes.Length;
os = request.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
}
catch
{ }
try
{
HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse();
Stream responseStream = webResponse.GetResponseStream();
StreamReader responseStreamReader = new StreamReader(responseStream);
var result = responseStreamReader.ReadToEnd();//
var json = new JavaScriptSerializer();
GoogleAuthorizationData authData = json.Deserialize<GoogleAuthorizationData>(result);
HttpWebRequest request1 = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/oauth2/v2/userinfo");
request1.Method = "GET";
request1.ContentLength = 0;
request1.Headers.Add("Authorization", string.Format("{0} {1}", authData.token_type, authData.access_token));
HttpWebResponse webResponse1 = (HttpWebResponse)request1.GetResponse();
Stream responseStream1 = webResponse1.GetResponseStream();
StreamReader responseStreamReader1 = new StreamReader(responseStream1);
GoogleUserInfo userinfo = json.Deserialize<GoogleUserInfo>(responseStreamReader1.ReadToEnd());
Response.Write(userinfo.email);
}
catch (Exception eX)
{
throw eX;
}
}
Я считаю, что вы не должны использовать app.UseGoogleAuthentication();
как вызов, который попытается использовать OpenID 2.0, который устарел.
Вместо этого вы должны использовать OAuth 2.0 для входа (OpenID Connect).
Итак:
app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions() { ClientId = "YOUR_CLIENT_ID", ClientSecret = "YOUR_CLIENT_SECRET", });
У меня та же проблема. Я использую Visual Studio 2013, а веб-сайт находится на Azure. Социальный журнал, который работал без проблем, прекратил работу, и LinkLoginCallback получал null в loginInfo. Я переиздал проект без изменения кода или перестройки, а затем loginInfo получил правильные данные, и все работает нормально. Не имеет смысла, но вы идете.
У меня появилась эта проблема вчера, и я ПОЛНОСТЬЮ СТУК! И, как вы описали, я получил это просто так без причины.
Мне удалось это исправить (после нескольких часов сравнения двух проектов - 1 тестовый проект, который каждый раз работал без проблем, а другой был более серьезным проектом - и у них был тот же самый код, но разные версии dll)
Проблема связана с DLL - ссылочными пакетами от Nuget. Убедитесь, что у вас есть последние пакеты, а также проверьте время выполнения в web.config.
После того, как я обновил все связанные с Owin пакеты и Microsoft.Owin и добавил:
<assemblyBinding>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
</assemblyBinding>
... он снова работает! Они могут варьироваться в зависимости от ваших используемых пакетов, но так, как это сработало для меня.
В Microsoft Owin есть ошибка в System.Web. Тот, который используется при запуске приложений Owin в IIS. Это, вероятно, 99% из нас, если мы используем новую проверку подлинности на основе Owin с помощью ASP.NET MVC5.
Ошибка в том, что cookie, установленный Owin, загадочно исчезает в некоторых случаях.
Поместите этот nuget перед https://github.com/KentorIT/owin-cookie-saver перед
app.UseGoogleAuthentication(...)
Убедитесь, что сторонние файлы cookie включены. Я узнал, что если вы не вошли в Google, когда пытаетесь "Зарегистрировать" пользователя с вашим приложением, он перенаправляется на страницу входа в систему, поскольку ищет этот файл cookie, которого нет, но все же удается делать то, что это необходимо для внешнего провайдера. В следующий раз, когда вы попытаетесь "Зарегистрировать", поскольку он выполнил часть процесса, ему больше не нужно искать внешний файл cookie, и он снова выполняет второй раз.