web-dev-qa-db-fra.com

Rôles d'autorisation API Web oauth owin

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?

22
CaTourist

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);
}
45
Xavier Egea