Why AssignRoles return me Invalid Role

Probably an easy one. Just buy my SS licence :slight_smile:

This is my TestCase:

    [Test]
    public void A_Register_A_User()
    {
        using (var client = CreateClient())
        {
            var reg = new Register();
            reg.Email = "a.leblanc@live.com";
            reg.FirstName = "André";
            reg.LastName = "Leblanc";
            reg.DisplayName = string.Format("{0} {1}", reg.FirstName, reg.LastName);
            reg.Password = "1234";
            var response = client.Post(reg);

            Assert.That(response.UserId, Is.Not.Empty);
        }
    }

    [Test]
    public void A_Register_Role_To_User()
    {
        using (var client = CreateClient())
        {
            var ar = new AssignRoles();
            ar.UserName = "a.leblanc@live.com";
            ar.Roles.AddIfNotExists("VerifiedUser");
            ar.Permissions.AddIfNotExists("CanRead"); 
            var response = client.Post(ar);
            Assert.That(response.AllRoles.Count, Is.GreaterThan(0));
            Assert.That(response.AllPermissions.Count, Is.GreaterThan(0));
        }
    }

And the error message:ServiceStack.WebServiceException : Invalid Role

The AssignRoles Service requires being invoked with an Authenticated Client with a User that has the RoleNames.Admin (i.e. “Admin”) role.

Either that or someone with Super User Access by configuring your AppHost with an AuthSecret which you can include in your requests with something like:

var authSecretHeader = HttpHeaders.XParamOverridePrefix + "authsecret";
client.RequestFilter = req => req.Headers[authSecretHeader] = myAuthSecret;
client.Post(ar);

OK this work great but now when I authenticate again with my user with Admin Role. The role assignment to another user give me same error…

        [Test]
    public void A_Register_An_Admin_User()
    {
        using (var client = CreateClient())
        {
            var reg = new Register();
            reg.Email = "aleblanc@lallemand.com";
            reg.FirstName = "André";
            reg.LastName = "Leblanc";
            reg.DisplayName = string.Format("{0} {1}", reg.FirstName, reg.LastName);
            reg.Password = "1234";
            var response = client.Post(reg);
            Assert.That(response.UserId, Is.Not.Empty);

            var authSecretHeader = HttpHeaders.XParamOverridePrefix + "authsecret";
            client.RequestFilter = req => req.Headers[authSecretHeader] = "secretz";

            var ar = new AssignRoles();
            ar.UserName = reg.Email;
            ar.Roles.AddIfNotExists(RoleNames.Admin);
            var rolesResponse = client.Post(ar);

            Assert.That(rolesResponse.AllRoles[0], Is.EqualTo(RoleNames.Admin));
            client.Post(new Authenticate { provider = "logout" });
        }
    }
    [Test]
    public void B_Register_Role_To_User()
    {
        using (var client = CreateClient())
        {
            var auth = new Authenticate();
            auth.UserName = "aleblanc@lallemand.com";
            auth.Password = "1234";
            auth.RememberMe = true;
            var authresponse = client.Post(auth);

            var ar = new AssignRoles();
            ar.UserName = "a.leblanc@live.com";
            ar.Roles.AddIfNotExists("VerifiedUser");
            ar.Permissions.AddIfNotExists("CanRead"); 
            var response = client.Post(ar);
            Assert.That(response.AllRoles.Count, Is.GreaterThan(0));
            Assert.That(response.AllPermissions.Count, Is.GreaterThan(0));
            client.Post(new Authenticate { provider = "logout" });
        }
    }

In my CustomCredentialsAuthProvider

		public override IHttpResult OnAuthenticated(IServiceBase authService, IAuthSession session, IAuthTokens tokens, Dictionary<string, string> authInfo)
	{
        var userAuthRep = authService.TryResolve<IUserAuthRepository>();
        var userAuth = userAuthRep.GetUserAuthByUserName(session.UserAuthName);
        session.Roles = (List<string>)userAuthRep.GetRoles(userAuth);
        session.Permissions = (List<string>)userAuthRep.GetPermissions(userAuth);

        return base.OnAuthenticated(authService, session, tokens, authInfo);
	}

Calling base.OnAuthenticated() should populate the session with their Roles/Permissions if it was persisted with the UserAuth or when it isn’t (e.g. when using OrmLiteAuthRepository with UseDistinctRoleTables=true) then session.HasRole() and session.HasPermission() will check the AuthProvider to see if the User has the specific role.

So you shouldn’t need to set session.Roles/Permissions explicitly. After calling base.OnAuthenticated() you can check to see if the User has the Admin role with:

var response = base.OnAuthenticated(authService, session, tokens, authInfo);
if (session.HasRole(RoleNames.Admin, userAuthRepo))
    Console.WriteLine(session.FirstName + " has Admin role");
return response;

Since you’re using a Custom AuthProvider I wont be able to tell what the issue is, so I’d need to a minimal stand-alone repro I can run locally to see the issue to be able to investigate further.

I think I know why now…

session.HasRole return me nothing.
I comment my TryAuthenticate and now it work. Strange thing I see in base.TryAuthenticate a method base.PopulateSession. But in my CustomAuthProvider I can’t call it.
Anyway I don’t really need to override TryAuthenticate In this project…

Thanks!

1 Like

FYI I’ve made PopulateSession() public should you need it in future.

This change is available from v5.0.3 that’s now available on MyGet.

1 Like