Web API 2标识。 / Token始终返回404错误

时间:2015-05-26 16:00:48

标签: asp.net asp.net-web-api2 asp.net-identity-2

我在采用Web API 2 Identity方面遇到了一些问题。在项目中。

我添加了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);
            }
        }
}

之后我添加了启用令牌授权的部分类:

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都是正确的。问题是什么?哪里有问题?

UPD:

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);
    }
}

2 个答案:

答案 0 :(得分:30)

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

答案 1 :(得分:1)

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