web-dev-qa-db-fra.com

Le jeton Owin Bearer ne fonctionne pas pour WebApi

J'ai parcouru des tonnes de documentation à ce sujet. Ma recherche google montre que j'ai visité tous les liens de la première page.

Problème La génération de jetons fonctionne bien. Je l'ai configuré avec un fournisseur personnalisé en tant que tel:

    public void ConfigureOAuth(IAppBuilder app)
    {
        var usermanager = NinjectContainer.Resolve<UserManager>(); 
        app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = new AppOAuthProvider(usermanager)
        });
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
    }

Cependant, lorsque j'appelle une URL protégée et passe le jeton porteur, je reçois toujours: Token Request

Comment diagnostiquer ou résoudre le problème? Si possible, comment puis-je effectuer moi-même la validation du jeton?

UPDATE Voici mon fournisseur AppOAuthProvider. Les deux méthodes sont appelées lorsque j'essaie de frapper un jeton, mais pas lorsque j'essaie d'accéder à une ressource protégée

public class AppOAuthProvider : OAuthAuthorizationServerProvider
{
    private UserManager _user;
    public AppOAuthProvider(UserManager user)
    {
        _user = user;
    }
    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
    }

    public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

        //Get User Information
        var getUser = _user.FindUser(context.UserName);
        if (getUser.Status == StatusCode.Failed)
        {
            context.SetError("invalid_grant", "The user name or password is incorrect.");
            return Task.FromResult<object>(null);
        }

        var user = getUser.Result;

        //Get Roles for User
        var getRoles = _user.GetRoles(user.UserID);
        if (getRoles.Status == StatusCode.Failed)
        {
            context.SetError("invalid_grant", "Could not determine Roles for the Specified User");
        }

        var roles = getRoles.Result;

        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaim(new Claim("UserID", user.UserID.ToString()));
        identity.AddClaim(new Claim("UserName", user.UserName));

        foreach (var role in roles)
        {
            identity.AddClaim(new Claim(ClaimTypes.Role, role));
        }

        context.Validated(identity);

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

UPDATE 2: Voici mon contrôleur de compte

[RoutePrefix("api/auth/account")]
public class AccountController : ApiController
{
    private UserManager _user;
    public AccountController(UserManager user)
    {
        _user = user;
    }

    [Authorize]
    [HttpGet]
    [Route("secret")]
    public IHttpActionResult Secret()
    {
        return Ok("Yay! Achievement Unlocked");
    }
}

UPDATE 3: Voici mon Startup.cs

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseNinjectMiddleware(NinjectContainer.CreateKernel);
        app.UseNinjectWebApi(GlobalConfiguration.Configuration);
        GlobalConfiguration.Configure(WebApiConfig.Register);
        ConfigureOAuth(app);
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        app.UseWebApi(GlobalConfiguration.Configuration);
        app.UseWelcomePage();
    }
}
9
Ody

Vous devez configurer l'authentification du serveur d'autorisation OAuth et du porteur OAuth avant d'appeler UseWebApi sur IAppBuilder. Ce qui suit est de mon programme. 

    public void Configuration(IAppBuilder app)
    {
        app.UseFileServer(new FileServerOptions()
        {
            RequestPath = PathString.Empty,
            FileSystem = new PhysicalFileSystem(@".\files")
        });

        // set the default page
        app.UseWelcomePage(@"/index.html");

        ConfigureAuth(app);

        HttpConfiguration config = new HttpConfiguration();

        config.Routes.MapHttpRoute
        (
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional } 
        );

        config.Formatters.Clear();
        config.Formatters.Add(new JsonMediaTypeFormatter());
        config.Formatters.JsonFormatter.SerializerSettings =
        new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };

        app.UseCors(CorsOptions.AllowAll);
        app.UseWebApi(config);


    }

    public void ConfigureAuth(IAppBuilder app)
    {
        OAuthAuthorizationServerOptions oAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = new YourApplicationOAuthProvider()
        };

        app.UseOAuthAuthorizationServer(oAuthServerOptions);
        app.UseOAuthBearerAuthentication
        (
            new OAuthBearerAuthenticationOptions 
            {
                Provider = new OAuthBearerAuthenticationProvider()
            }
        );
    }
16
Yang Zhang
    HttpConfiguration config = new HttpConfiguration();
app.UseNinjectMiddleware(NinjectContainer.CreateKernel);
app.UseNinjectWebApi(GlobalConfiguration.Configuration);
ConfigureOAuth(app);
WebApiConfig.Register(config);
//GlobalConfiguration.Configure(WebApiConfig.Register);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
// app.UseWebApi(GlobalConfiguration.Configuration);
app.UseWebApi(config);
app.UseWelcomePage();

J'ai essayé cela avec l'application de votre échantillon sur github et cela a fonctionné

3
ojorma

Dans votre fournisseur, vous devez:

public override ValidateClientAuthentication(OAuthClientAuthenticationContext context)
{
    //test context.ClientId
    //if you don't care about client id just validate the context
    context.Validated();
}

La raison en est que si vous ne substituez pas ValidateClientAuthentication et ne validez pas le contexte, il est considéré comme rejeté et vous obtiendrez toujours cette erreur.

2
Rui