Как получить параметры, заданные в свойствах AuthenticationProperties в вызове OIDC IdentityServer4? - PullRequest
0 голосов
/ 15 мая 2019

IdentityServer4 работает как система аутентификации, подключенная к Google и Amazon вместе с локальными учетными записями.У меня есть отдельное веб-приложение, использующее систему IdentityServer4 в качестве поставщика oidc auth, и кажется, что все работает с аутентификацией и выдачей токенов.Проблема в том, что он не поддерживает returnUrl после аутентификации.Я использую OIDC StateDataFormatterCache, который встроен в Id4 через распределенный кеш Redis и в Redis проверил, что он записывает перенаправление и даже тестовый параметр, который я добавил во время вызова.

После аутентификации он выполняетне перенаправлять меня обратно на исходный URL-адрес, и когда я пытаюсь получить доступ к параметрам и параметрам AuthenticationProperties, установленным в запросе, они не появляются после аутентификации.

Я прошел по коду на стороне IdentityServer4где логин для локального и внешнего обратного вызова и returnUrl никогда не появляется там.Я предполагаю, что OIDC StateDataFormatterCache перехватывает это, чтобы предотвратить потенциальные проблемы с длинными URL-адресами, и должен перехватить ответ и ввести возвращаемый URL-адрес.Эта часть, похоже, не работает, поэтому я пытался посмотреть, смогу ли я вставить свой собственный пользовательский параметр в реквизиты аутентификации и вытащить его обратно после аутентификации, но он окажется пустым.У AuthenticationProperties, похоже, просто есть access_token, refresh_token, id_token и т. Д., Но отсутствует URL-адрес перенаправления и мой пользовательский параметр.

services.AddOidcStateDataFormatterCache("oidc");
...
var authProps = new AuthenticationProperties { RedirectUri = originalPath + context.Request.QueryString };

Microsoft.Extensions.Primitives.StringValues stateValue;

if (context.Request.Query.TryGetValue("state", out stateValue))
{
   authProps.SetParameter("itk", stateValue);
}

await Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.ChallengeAsync(context,"oidc", authProps); //authProps has custom parameter 'itk' and a redirect
...
var authContext = await context.AuthenticateAsync("oidc");
//authContext.Properties has data but not the RedirectUri or the custom parameter I set and verified to exist in the redis store

Вот что отображается в Redis:

{
  "Items": {
    ".redirect": "/?state=foo",
    ".xsrf": "DkRjG29eE4qDFaNLSktyTDKfhdzXH8FfVpAwBbje6tc",
    "OpenIdConnect.Code.RedirectUri": "https://localhost/signin-oidc"
  },
  "Parameters": {
    "itk": [
      "foo"
    ]
  },
  "RedirectUri": "/?state=foo"
}

Anyидеи о том, почему я не могу получить информацию, помещенную в Redis с помощью средства форматирования данных состояния?

Мне нужно иметь возможность получить значение «itk» в параметрах.

Я нашелмоя проблема с перенаправлением не проходит, но мне все еще нужно иметь возможность получить этот параметр.

1 Ответ

0 голосов
/ 22 мая 2019

Поведение является заданным, за исключением сохранения в Redis. Комментарий к Parameters гласит:

Коллекция параметров, которые передаются в обработчик аутентификации. Они не предназначены для сериализация или постоянство, только для передачи данных между сайтами вызовов.

Мы должны использовать коллекцию Items для сериализации или сохранения.
Как это работает для меня:

//configuration
services.AddOidcStateDataFormatterCache(Constants.MyExternalIdIdpName);
//AccountController
[HttpGet]
public IActionResult Login(string returnUrl)
{
  string provider = Constants.MyExternalIdIdpName;
  string returnUrl2 = Url.Action("ExternalLoginCallback", new { returnUrl = returnUrl });

  // start challenge and roundtrip the return URL
  var props = new AuthenticationProperties
  {
    RedirectUri = returnUrl2,
    Items = { { "scheme", provider } }
  };

  return new ChallengeResult(provider, props);
}

, а затем

[HttpGet]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl)
{
  // read external identity from the temporary cookie
  var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);

  // retrieve claims of the external user
  var claims = result.Principal.Claims.ToList();

  var userIdClaim = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject);
  var user = <users>.FindByExternalProvider(provider, userIdClaim.Value);

  await _events.RaiseAsync(new UserLoginSuccessEvent(provider, userId, user.SubjectId, user.Username));
  await HttpContext.SignInAsync(user.SubjectId, user.Username, provider, props, additionalClaims.ToArray());

  // delete temporary cookie used during external authentication
  await HttpContext.SignOutAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);

  // validate return URL and redirect back to authorization endpoint or a local page
  if (_interaction.IsValidReturnUrl(returnUrl) || Url.IsLocalUrl(returnUrl))
  {
    return Redirect(returnUrl);
  }

  return Redirect("~/");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...