Web API 2 身份。 /Token 总是 return 404 错误

Web API 2 identity. /Token Always return 404 error

我在采用 Web API 2 身份时遇到了一些问题。在项目中。

我加StartUp.cs

像这样:

using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(MyNamespace.Startup))]
namespace MyNamespace
{
    public partial class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                ConfigureAuth(app);
            }
        }
}

之后我添加部分class以启用令牌授权:

namespace MyNamespace
{
    public partial class Startup
    {
        public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
        public static string PublicClientId { get; private set; }
        public void ConfigureAuth(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions());
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

            PublicClientId = "self";
            OAuthOptions = new OAuthAuthorizationServerOptions
            {
                TokenEndpointPath = new PathString("/Token"),
                Provider = new ApplicationOAuthProvider(PublicClientId),
                AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(14)
            };

            app.UseOAuthBearerTokens(OAuthOptions);
        }
    }
}

同样,我实现了用户功能(如 UserStore、UserManager)。

我从示例中采用 "ExternalLogin" 方法并进行了更改。

    // GET api/Account/ExternalLogin
    [OverrideAuthentication]
    [HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
    [AllowAnonymous]
    [Route("ExternalLogin", Name = "ExternalLogin")]
    public async Task<IHttpActionResult> GetExternalLogin(string provider, string error = null)
    {
        if (error != null)
        {
            return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error));
        }

        if (!User.Identity.IsAuthenticated)
        {
            return new ChallengeResult(provider, this);
        }

        ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);

        if (externalLogin == null)
        {
            return InternalServerError();
        }

        if (externalLogin.LoginProvider != provider)
        {
            Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
            return new ChallengeResult(provider, this);
        }

        User user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider,
            externalLogin.ProviderKey));

        bool hasRegistered = user != null;

        if (hasRegistered)
        {
            Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);



            ClaimsIdentity oAuthIdentity = await UserManager.CreateIdentityAsync(user, 
                                OAuthDefaults.AuthenticationType);

            ClaimsIdentity cookieIdentity = await UserManager.CreateIdentityAsync(user, 
                                CookieAuthenticationDefaults.AuthenticationType);

            AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName);
            Authentication.SignIn(properties, oAuthIdentity, cookieIdentity);
        }
        else
        {
            IEnumerable<Claim> claims = externalLogin.GetClaims();
            ClaimsIdentity identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
            Authentication.SignIn(identity);
        }

        return Ok();
    }

之后我 运行 我的应用程序并尝试像这样登录应用程序:

 var loginData = {
            grant_type: 'password',
            username: "test",
            password: "test"
        }; 

 $.ajax({
         type: 'POST',
         url: '/Token',
         data: loginData
        }).done(function (data) {
            alert(data.username);
            sessionStorage.setItem(tokenKey, data.access_token);
        }).fail(function (data) {
            alert(data);
        });

我遇到了 404 错误。我尝试通过 fiddler 向 /Token 发送自定义请求,结果相同。然后我检查我的 api/Account/ExternalLogin 操作是否可用,此响应 401 状态代码。我检查了引用 Owin,Microsoft.Owin 全部正确。有什么问题?我哪里有问题?

更新:

public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
 {
    private readonly string _publicClientId;

    [Dependency]
    public ICustomUserManager UserManager
    {
        get;set;
    }

    public ApplicationOAuthProvider(string publicClientId)
    {
        if (publicClientId == null)
        {
            throw new ArgumentNullException("publicClientId");
        }

        _publicClientId = publicClientId;
    }

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        var userManager = context.OwinContext.GetUserManager<ICustomUserManager>();

        User user = await userManager.FindAsync(context.UserName, context.Password);

        if (user == null)
        {
            context.SetError("invalid_grant", "The user name or password is incorrect.");
            return;
        }

        ClaimsIdentity oAuthIdentity = await UserManager.CreateIdentityAsync(user, 
                                OAuthDefaults.AuthenticationType);

        ClaimsIdentity cookieIdentity = await UserManager.CreateIdentityAsync(user, 
                                CookieAuthenticationDefaults.AuthenticationType);

        AuthenticationProperties properties = CreateProperties(user.UserName);
        AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);

        var val = context.Validated(ticket);
        context.Request.Context.Authentication.SignIn(cookieIdentity);
    }

    public override Task TokenEndpoint(OAuthTokenEndpointContext context)
    {
        foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
        {
            context.AdditionalResponseParameters.Add(property.Key, property.Value);
        }

        return Task.FromResult<object>(null);
    }

    public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        // Resource owner password credentials does not provide a client ID.
        if (context.ClientId == null)
        {
            context.Validated();
        }

        return Task.FromResult<object>(null);
    }

    public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
    {
        if (context.ClientId == _publicClientId)
        {
            Uri expectedRootUri = new Uri(context.Request.Uri, "/");

            if (expectedRootUri.AbsoluteUri == context.RedirectUri)
            {
                context.Validated();
            }
        }

        return Task.FromResult<object>(null);
    }

    public static AuthenticationProperties CreateProperties(string userName)
    {
        IDictionary<string, string> data = new Dictionary<string, string>
        {
            { "userName", userName }
        };
        return new AuthenticationProperties(data);
    }
}

这个问题我想通了。 OAuthAuthorizationServerOptions 有一个 AllowInsecureHttp 属性。我使用了不安全的 http 协议。在这种情况下,您可以设置 AllowInsecureHttp = true,或者您可以将 Https 过滤器添加到过滤器管道。

我在我的生产环境中遇到了同样的问题,但不是在本地 (IIS Express)。 web.config 没有任何帮助。 解决方案是添加显式 NuGet 包引用:Microsoft.Owin.Host.SystemWeb