web-dev-qa-db-ja.com

Web API2ID。 / Token常に404エラーを返す

Web API 2Identityの採用に問題があります。プロジェクト内。

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エラーが発生しました。フィドラーを介して/ 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);
    }
}
12
CMaker

私はこの問題を理解しています。 OAuthAuthorizationServerOptionsにはAllowInsecureHttpプロパティがあります。安全でないhttpプロトコルを使用しました。この場合、AllowInsecureHttp = trueを設定するか、フィルターパイプラインにHttpsフィルターを追加できます。

32
CMaker

実稼働環境でも同じ問題が発生しましたが、ローカルでは発生しませんでした(IISExpress)。 web.configには何の助けもありません。解決策は、明示的なNuGetパッケージ参照をMicrosoft.Owin.Host.SystemWebに追加することでした。

3