J'ai implémenté un système d'autorisation de jeton sur l'API Web ASP.NET avec le middleware OWIN. Je peux m'authentifier avec un client REST et obtenir un jeton d'autorisation pour appeler l'API. Si je mets l'attribut [Authorize]
Sur une action GET dans mon contrôleur, cela fonctionne également correctement. Si je n'ai pas de jeton valide, il refuse la ressource avec un message 401, mais si j'utilise [Authorize(Roles="admins")]
avec le paramètre roles
, il ne reconnaît pas les rôles de l'utilisateur. J'ai vérifié choses dans la base de données et vérifié que usersinroles
est correctement rempli.
Ceci est un extrait de code:
[Authorize(Roles = "admins")]
public IEnumerable<CompanyModel> Get()
{
ClaimsPrincipal principal = Request.GetRequestContext().Principal as ClaimsPrincipal;
bool isrole = principal.IsInRole("admins");
J'ai également vérifié l'action sans le paramètre roles
et le booléen isrole
est toujours false
. Dois-je activer quelque chose?
Vous devez ajouter dans la méthode GrantResourceOwnerCredentials:
identity.AddClaim(new Claim(ClaimTypes.Role, "admins"));
étape par étape
Dans la classe StartUp.cs, vous devez avoir un fournisseur personnalisé, comme la ligne
Provider = new CustomAuthorizationServerProvider()
par exemple:
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions oAuthServerOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = new CustomAuthorizationServerProvider()
};
// Token Generation
app.UseOAuthAuthorizationServer(oAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
Ensuite, votre classe CustomAuthorizationServerProvider qui hérite de la classe OAuthAuthorizationServerProvider remplacera GrantResourceOwnerCredentials (contexte OAuthGrantResourceOwnerCredentialsContext).
Ensuite, après avoir vérifié que l'utilisateur a le nom d'utilisateur et le mot de passe corrects, vous devez ajouter
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
...
// other claims
...
identity.AddClaim(new Claim(ClaimTypes.Role, "admins"));
...
var ticket = new AuthenticationTicket(identity, properties);
context.Validated(ticket);
Modifié
Vous pouvez obtenir des rôles d'utilisateur à partir de DB au lieu d'utiliser la chaîne codée "admins" en faisant:
var roles = await userManager.GetRolesAsync(userId);
Vous pouvez donc ajouter la méthode suivante dans votre référentiel:
public async Task<IList<string>> UserRoles(string userId)
{
IList<string> roles = await userManager.GetRolesAsync(userId);
return roles;
}
Et puis appelez-le depuis votre remplacement GrantResourceOwnerCredentials en ajoutant:
using (AuthRepository repository = new AuthRepository())
{
IdentityUser user = await repository.FindUser(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect");
return;
}
var roles = repository.UserRoles(user.Id);
}