J'ai suivi un didacticiel pour protéger une API Web avec OAuth en C #.
Je fais des tests et jusqu'à présent, j'ai réussi à obtenir le jeton d'accès avec succès depuis /token
. J'utilise une extension Chrome appelée "Client avancé REST" pour le tester.
{"access_token":"...","token_type":"bearer","expires_in":86399}
C'est ce que je reçois de /token
. Tout a l'air bien.
Ma prochaine requête est adressée à mon contrôleur API de test:
namespace API.Controllers
{
[Authorize]
[RoutePrefix("api/Social")]
public class SocialController : ApiController
{
....
[HttpPost]
public IHttpActionResult Schedule(SocialPost post)
{
var test = HttpContext.Current.GetOwinContext().Authentication.User;
....
return Ok();
}
}
}
La demande est une POST
et a l'en-tête:
Authorization: Bearer XXXXXXXTOKEHEREXXXXXXX
Je reçois: Authorization has been denied for this request.
retourné en JSON.
J'ai aussi essayé de faire un test GET et j'ai obtenu ce à quoi je m'attendais, à savoir que la méthode n'est pas prise en charge car je ne l'ai pas implémentée.
Voici mon fournisseur d'autorisation:
public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
using (var repo = new AuthRepository())
{
IdentityUser user = await repo.FindUser(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
}
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
identity.AddClaim(new Claim(ClaimTypes.Role, "User"));
context.Validated(identity);
}
}
Toute aide est la bienvenue. Je ne sais pas si c'est la demande ou le code qui est erroné.
edit: Voici mon Startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
ConfigureOAuth(app);
}
public void ConfigureOAuth(IAppBuilder app)
{
var oAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider()
};
// Token Generation
app.UseOAuthAuthorizationServer(oAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
La question est assez simple: Modifier l’ordre de votre pipeline OWIN .
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
}
Pour OWIN, l’ordre du pipeline de votre configuration est assez important. Dans votre cas, vous essayez d'utiliser votre gestionnaire API Web avant le gestionnaire OAuth. À l’intérieur de celui-ci, vous validez votre demande, trouvez votre action sécurisée et essayez de la valider par rapport au Owin.Context.User
actuel. À ce stade, cet utilisateur n'existe pas car il est défini à partir du jeton avec OAuth Handler qui a appelé ultérieurement.
Vous devez ajouter une revendication avec ce schéma:
http://schemas.Microsoft.com/ws/2008/06/identity/claims/role
la meilleure chose à faire est d’utiliser l’ensemble prédéfini de revendications:
identity.AddClaim(new Claim(ClaimTypes.Role, "User"));
Vous pouvez trouver ClaimTypes
dans System.Security.Claims
.
Vous devez également prendre en compte les rôles de filtrage dans votre contrôleur/action:
[Authorize(Roles="User")]
Vous pouvez trouver un exemple d'application simple, owin auto-hébergé avec un client jquery ici .
On dirait que la version de " System.IdentityModel.Tokens.Jwt" qui coexiste avec les autres assemblys Owin n'est pas correcte.
Si vous utilisez la version 2.1.0 de "Microsoft.Owin.Security.Jwt", vous devez utiliser l'assembly "System.IdentityModel.Tokens.Jwt" de la version 3.0.2.
A partir de la console du gestionnaire de paquets, essayez:
Update-Package System.IdentityModel.Tokens.Jwt -Version 3.0.2