Il y a environ un mois, un projet fonctionnait parfaitement avec ASP Identity OAuth. J'envoyais une demande POST au noeud final/Token avec grant_type, nom d'utilisateur et mot de passe, et tout était dandy.
J'ai récemment lancé un nouveau projet basé sur le modèle SPA de Visual Studio 2013 RC2. C'est un peu différent de l'ancien modèle. L’authentification est configurée avec des valeurs par défaut assez basiques,
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
//AuthorizeEndpointPath = new PathString("/Account/Authorize"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
};
Rien de significatif n'a changé par rapport au modèle par défaut. Je peux enregistrer des comptes avec succès via une méthode de contrôleur API Web que j'ai implémentée;
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{
if (ModelState.IsValid)
{
var user = new TunrUser() { UserName = model.Email, Email = model.Email, DisplayName = model.DisplayName };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
return Created(new Uri("/api/Users/" + user.Id,UriKind.Relative), user.toViewModel());
}
else
{
return BadRequest(result.Errors.First());
}
}
return BadRequest(ModelState);
}
Cependant, peu importe ce que je POST sur le noeud final/Token, je toujours reçois la même réponse.
{"error":"invalid_client"}
Normalement, je passe le corps de requête suivant
grant_type=password&username=user%40domain.com&password=userpassword
Mais cela entraîne la même erreur. Cela fonctionnait dans le précédent modèle/identité VS2013 SPA. Qu'est-ce qui a changé?
Je vous remercie!
Il s'avère donc que les nouveaux modèles n'incluent pas une implémentation fonctionnelle d'ApplicationOAuthProvider qui était présente dans les modèles plus anciens.
Après avoir regardé cette conversation de construction , j’ai enquêté plus avant et découvert qu’une implémentation fonctionnelle d’ApplicationOAuthProvider est disponible pour vérification dans ce paquet NuGet ! C'est très similaire à l'ancienne implémentation.
En outre, vous pouvez utiliser la classe ApplicationOAuthProvider fournie avec le modèle WebApi lorsque l'option Comptes d'utilisateurs individuels est choisie comme option de sécurité. Cependant, vous devrez changer quelques autres choses, que j'ai énumérées ci-dessous. J'espère que ça aide.
La classe ApplicationOAuthProvider fournie avec le modèle WebApi/Individual User Accounts contient la méthode suivante:
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser 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 user.GenerateUserIdentityAsync(userManager,
OAuthDefaults.AuthenticationType);
ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = CreateProperties(user.UserName);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
Copiez-le dans la classe ApplicationOAuthProvider de votre projet de modèle SPA, en remplaçant la méthode d'origine. La méthode code user.GenerateUserIdentityAsync
n'est pas valide lorsqu'elle est copiée dans le projet de modèle SPA car la classe ApplicationUser n'autorise pas le type d'authentification "porteur".
Ajoutez une surcharge semblable à la suivante à la classe ApplicationUser (recherchez-la dans le fichier Models\IdentityModels.cs
):
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager , string authenticationType)
{
var userIdentity = await manager.CreateIdentityAsync(this , authenticationType);
// Add custom user claims here
return userIdentity;
}
Vous devriez maintenant pouvoir utiliser /Token
endpoint correctement.