Настройка redirect_uri в Identity Asp.Net
Я пытаюсь установить redirect_uri для входа в facebook с идентификатором Asp.Net. Однако метод GetExternalLogin REST в AccountController запускается только в том случае, если redirect_uri является "/". Если я добавлю что-нибудь еще, это не вызывает GetExternalLogin, браузер показывает только * error: invalid_request *.
Однако URL-адрес содержит перенаправленный параметр, как это должно быть, например. если я добавлю redirect_uri как http://localhost:25432/testing
URL-адрес ответа выглядит следующим образом:
http://localhost:25432/api/Account/ExternalLogin?provider=Facebook&response_type=token&client_id=self&redirect_uri=http%3A%2F%2Flocalhost%3A25432%2Ftesting&state=0NctHHGq_aiazEurHYbvJT8hDgl0GJ_GGSdFfq2z5SA1
и окно браузера показывает:
error: invalid_request
Любая идея, почему это работает только при перенаправлении на '/', но не на другие URL-адреса?
Спасибо!
Ответы
Ответ 1
Проблема заключается в том, что GetExternalLogin
зарегистрирован как OAuthOptions.AuthorizeEndpointPath
, который использовался для app.UseOAuthBearerTokens(OAuthOptions)
. Эта конфигурация ставит проверку на аргументы конечной точки.
if (!Uri.TryCreate(authorizeRequest.RedirectUri, UriKind.Absolute, out validatingUri))
{
// The redirection endpoint URI MUST be an absolute URI
}
else if (!String.IsNullOrEmpty(validatingUri.Fragment))
{
// The endpoint URI MUST NOT include a fragment component.
}
else if (!Options.AllowInsecureHttp &&
String.Equals(validatingUri.Scheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase))
{
// The redirection endpoint SHOULD require the use of TLS
}
И вы должны передать "Авторизовать запрос конечной точки, отсутствующий требуемый параметр response_type" и
"Авторизованный запрос конечной точки содержит неподдерживаемый параметр response_type"
Ответ 2
Для всех, кто может столкнуться с этой проблемой: проблема в том, что вы берете (копируете) ApplicationOAuthProvider.cs
из шаблона SPA в Visual Studio и там, где этот код:
public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
if (context.ClientId == _publicClientId)
{
var expectedRootUri = new Uri(context.Request.Uri, "/");
if (expectedRootUri.AbsoluteUri == context.RedirectUri)
{
context.Validated();
}
}
return Task.FromResult<object>(null);
}
Это, очевидно, блокирует любой redirect_uri
, который не похож на http://localhost/
или http://domain.com/
, поэтому, например, http://domain.com/home
не будет работать.
Теперь это ниже источник InvokeAuthorizeEndpointAsync
в Катане, который выполняет всю работу, и вы можете видеть, что он вызывает любой пользовательский OAuthProvider
, который может быть зарегистрирован для этого приложения MVC/Web API (эта регистрация обычно происходит в Startup.Auth.cs
):
private async Task<bool> InvokeAuthorizeEndpointAsync()
{
var authorizeRequest = new AuthorizeEndpointRequest(Request.Query);
var clientContext = new OAuthValidateClientRedirectUriContext(
Context,
Options,
authorizeRequest.ClientId,
authorizeRequest.RedirectUri);
if (!String.IsNullOrEmpty(authorizeRequest.RedirectUri))
{
bool acceptableUri = true;
Uri validatingUri;
if (!Uri.TryCreate(authorizeRequest.RedirectUri, UriKind.Absolute, out validatingUri))
{
// The redirection endpoint URI MUST be an absolute URI
// http://tools.ietf.org/html/rfc6749#section-3.1.2
acceptableUri = false;
}
else if (!String.IsNullOrEmpty(validatingUri.Fragment))
{
// The endpoint URI MUST NOT include a fragment component.
// http://tools.ietf.org/html/rfc6749#section-3.1.2
acceptableUri = false;
}
else if (!Options.AllowInsecureHttp &&
String.Equals(validatingUri.Scheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase))
{
// The redirection endpoint SHOULD require the use of TLS
// http://tools.ietf.org/html/rfc6749#section-3.1.2.1
acceptableUri = false;
}
if (!acceptableUri)
{
clientContext.SetError(Constants.Errors.InvalidRequest);
return await SendErrorRedirectAsync(clientContext, clientContext);
}
}
await Options.Provider.ValidateClientRedirectUri(clientContext);
if (!clientContext.IsValidated)
{
_logger.WriteVerbose("Unable to validate client information");
return await SendErrorRedirectAsync(clientContext, clientContext);
}
var validatingContext = new OAuthValidateAuthorizeRequestContext(
Context,
Options,
authorizeRequest,
clientContext);
if (string.IsNullOrEmpty(authorizeRequest.ResponseType))
{
_logger.WriteVerbose("Authorize endpoint request missing required response_type parameter");
validatingContext.SetError(Constants.Errors.InvalidRequest);
}
else if (!authorizeRequest.IsAuthorizationCodeGrantType &&
!authorizeRequest.IsImplicitGrantType)
{
_logger.WriteVerbose("Authorize endpoint request contains unsupported response_type parameter");
validatingContext.SetError(Constants.Errors.UnsupportedResponseType);
}
else
{
await Options.Provider.ValidateAuthorizeRequest(validatingContext);
}
if (!validatingContext.IsValidated)
{
// an invalid request is not processed further
return await SendErrorRedirectAsync(clientContext, validatingContext);
}
_clientContext = clientContext;
_authorizeEndpointRequest = authorizeRequest;
var authorizeEndpointContext = new OAuthAuthorizeEndpointContext(Context, Options);
await Options.Provider.AuthorizeEndpoint(authorizeEndpointContext);
return authorizeEndpointContext.IsRequestCompleted;
}
Это ключ:
await Options.Provider.ValidateClientRedirectUri(clientContext);
Итак, ваше решение состоит в том, чтобы изменить способ выполнения ValidateClientRedirectUri
валидации - реализация SPA по умолчанию, как вы можете видеть, очень наивна.
Там много ppl имеет проблемы с SPA главным образом потому, что ему не хватает какой-либо полезной информации, и я имею в виду как для ASP.NET Identity, так и для OWIN и в отношении того, что происходит в реализации KnockoutJS.
Я хочу, чтобы Microsoft предоставила более подробные документы для этих шаблонов, потому что любой, кто попытается сделать что-то более сложное, столкнется с проблемами.
Я потратил несколько часов на это, копаясь в исходном коде OWIN (Katana), думая, что это вышеперечисленная реализация блокирует мои URI перенаправления, но это не так, надеюсь, поможет и кому-то еще.
НТН
Ответ 3
Основываясь на других ответах, я изменил код проверки в ApplicationOAuthProvider.cs, чтобы убедиться, что перенаправление uri находится в одном домене, например:
public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
if (context.ClientId == _publicClientId)
{
Uri expectedRootUri = new Uri(context.Request.Uri, "/");
if (context.RedirectUri.StartsWith(expectedRootUri.AbsoluteUri))
{
context.Validated();
}
}
return Task.FromResult<object>(null);
}