在 Asp.Net Identity 中設置 redirect_uri
我正在嘗試使用 Asp.Net Identity 為 facebook 登錄設置 redirect_uri。但是,僅當 redirect_uri 為“/”時才會觸發
GetExternalLoginREST 方法。AccountController如果我添加任何其他它不會觸發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知道為什麼這僅在重定向到“/”而不是任何其他網址時有效嗎?
問題是
GetExternalLogin註冊為OAuthOptions.AuthorizeEndpointPathwhich used forapp.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 參數”
對於可能遇到此問題的其他任何人:問題是當您
ApplicationOAuthProvider.cs從 Visual Studio SPA 模板中獲取(複製)時,它就在此程式碼所在的位置: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://example.com/例如http://example.com/home不起作用。現在下面是
InvokeAuthorizeEndpointAsyncKatana 的原始碼,它完成了所有工作,您可以看到它呼叫了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 實現非常幼稚。SPA 存在很多問題,主要是因為它缺乏任何有用的資訊,我的意思是對於 ASP.NET 身份和 OWIN 的東西,以及關於 KnockoutJS 實現中發生的事情。
我希望微軟能為這些模板提供更全面的文件,因為任何嘗試做任何更複雜的事情的人都會遇到問題。
我花了幾個小時研究 OWIN (Katana) 原始碼,認為上面的實現阻止了我的重定向 URI,但事實並非如此,希望也能幫助其他人。
高溫高壓