AuthenticationProperties.RedirectUri не передается в Google в Challenge()

В моем веб-приложении я зарегистрировал Google как поставщика единого входа:

app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions {
    ClientId = "8765.......apps.googleusercontent.com",
    ClientSecret = "Secret"
})

Мое приложение не позволяет пользователям регистрироваться/регистрироваться (вместо этого их учетные записи создаются администратором, но позже они могут связать свою учетную запись с Google).

В моем контроллере «Войти с помощью Google» я пытаюсь выполнить Challenge() для перенаправления в Google. Возможно, это неправильный подход:

string redirectUri = "http://localhost:55262/SSO/Google/ProcessToken"; // actually created in code, but shown as string for clarity
AuthenticationProperties properties = new AuthenticationProperties();
properties.RedirectUri = Server.UrlEncode(redirectUri);
Context.GetOwinContext().Authentication.Challenge(properties, "Google");

Это правильно отправляет пользователя в Google, но затем Google выдает Error: redirect_uri_mismatch, сообщая, что:

URI перенаправления в запросе: http://localhost:55262/signin-google не соответствует зарегистрированному URI перенаправления.

Я видел эту ошибку раньше, когда коллекция URI возврата в панели управления Google не содержала указанного redirect_uri.

Если я выполняю отладку в VS2015, я вижу, что свойство redirect_uri правильно установлено в AuthenticationProperties, но кажется, что OWIN/Katana не передает его в Google. Вместо этого, когда я нажимаю Google, return_uri используется по умолчанию для OWIN/Katana. Тот, который я установил, игнорируется.

Детали запроса Google, кажется, подтверждают это:

scope=openid profile email
response_type=code
redirect_uri=http://localhost:55262/signin-google

Что я делаю неправильно здесь, пожалуйста? Не следует ли использовать Challenge(), чтобы пользователи могли связать свои локальные учетные записи приложений с Google?


person EvilDr    schedule 13.11.2015    source источник
comment
Что такое GoogleOAuth2AuthenticationOptions? Жаль, что не полный образец OWIN-Katana с использованием Google.   -  person Kiquenet    schedule 04.05.2016
comment
Это объект класса OWIN, который содержит обязательные поля для аутентификации Google OAuth2. Естественно, он используется только для Google.   -  person EvilDr    schedule 04.05.2016


Ответы (2)


Обратите внимание, что открытая аутентификация OWIN имеет предопределенные методы. Другими словами, в localhost:port/signin-google OWIN ожидает вызова signin-google внешней службой аутентификации (хотя вы не можете найти ее реализацию внутри проекта). signin-google – это допустимый и рабочий путь, и я настоятельно рекомендую вам не менять его (во избежание написания новой реализации в качестве действия контроллера).

У меня была аналогичная проблема. Проведя много утомительных дней, наконец, я обнаружил, что проблема исходит из исходного URL-адреса пользователя, который действителен для отправленного redirect_uri OWIN. Четко:

  • Если вы введете www.site.com, redirect_uri будет равно www.site.com/signin-google.
  • Если вы введете site.com, redirect_uri будет равно site.com/signin-google.

И Google вернет redirect_uri_mismatch Ошибку для одного из вышеперечисленных случаев на основе введенных URL-адресов перенаправления в консоли. Я думаю, что ваша проблема также связана с этой реальностью, и решение заключается в установке любых возможных URL-адресов в консоли.

person Amirhossein Mehrvarzi    schedule 16.11.2015

Чтобы предоставить дополнительную информацию о принятом ответе...

Можно игнорировать /signin-google

Выясняется, что /signin-google URI находится под внутренним управлением OWIN/Katana. Вам, как разработчику, не нужно беспокоиться об этом, но вам нужно добавить его в консоль разработчика Google в качестве URI авторизованного перенаправления.

В запросе Google обратите внимание, что OWIN всегда передает URI перенаправления в Google как /signin-google, независимо от того, какой пользовательский URI вы установили в свойстве AuthenticationProperties.RedirectUri. Хотя на первый взгляд это может показаться ошибкой/проблемой, у него есть большое преимущество в том, что OWIN может управлять всеми обратными вызовами с помощью одного URI обратного вызова. Ваш обратный URI тоже не забыт (см. ниже)!.

А как насчет вашего собственного URL-адреса перенаправления?

Ну, вот где AuthenticationProperties() вступают в игру. Указав свой собственный URL-адрес обратного вызова, например...

AuthenticationProperties properties = new AuthenticationProperties { RedirectUri = "https://my.app.com/custom/callback/uri" };

... после того, как OWIN проверит токен Google и извлечет необходимые данные, пользователь будет перенаправлен на указанный вами URL-адрес.

Тут я и запутался, так как не понимал, что делать с /signin-google, когда по факту никаких действий не предпринималось. Это относится как к MVC, так и к веб-формам — вам не нужно беспокоиться о том, что передается в Google. Однако, если вы используете веб-формы или указываете правила авторизации в web.config, вам понадобится это, чтобы вернувшиеся пользователи снова не попали на страницу ведения журнала:

<location path="signin-google">
    <system.web>
        <authorization>
            <allow users="*"/>
        </authorization>
    </system.web>
</location>

Вот весь код, который вам нужен, чтобы отправить пользователя в Google и вернуть токен, содержащий его данные:

Исходящий

Отправьте пользователя в Google с контроллера, события нажатия кнопки, загрузки страницы, чего угодно (независимо от вашего стека ASP/хостинга):

// set the callback, for after OWIN finishes examining what comes back from Google
AuthenticationProperties properties = new AuthenticationProperties { RedirectUri = "https://www.myapp.com/some/callback/uri" };
// send the user to Google
Context.GetOwinContext().Authentication.Challenge(properties, "Google");
// Stop execution of the current page/method - the 401 forces OWIN to kick-in and do its thing
Response.StatusCode = 401;
Response.End();

Входящий

Пользователь возвращается из Google после проверки его личности

Microsoft.AspNet.Identity.Owin.ExternalLoginInfo loginInfo = Context.GetOwinContext().Authentication.GetExternalLoginInfo();
person EvilDr    schedule 16.11.2015
comment
Response.StatusCode = 401; Ответ.Конец(); была ключевой модификацией. Спасибо, это заняло некоторое время, чтобы отследить. Ссылка: stackoverflow.com/questions/47458095/ - person gb2d; 24.11.2017
comment
Полное минное поле, не так ли :-/ - person EvilDr; 24.11.2017