Chase Florell
Chase Florell

Reputation: 47377

ServiceStack RequiredPermission is not validating my user

I cant seem to get our tests to pass the RequiredPermission attribute on our ServiceStack service. Can someone help me figure out where I'm going wrong here?

The assumption is that RequiredPermission uses the session.Permissions list.

Our UserViewModel is setup as follows

public class UserViewModel : ViewModelBase
{
    public UserViewModel()
    {
        Groups = new List<GroupModel>();
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string Password { get; set; } // This should never be populated on the way out.

    public IList<GroupModel> Groups { get; set; }
}

The GroupModel is similar with a list of SecuritySettings within it. Every call to the Service Layer returns a fully hydrated UserViewModel containing a list of Groups and each group contains a list of SecuritySettings.

When a user Authenticates, we run this

    public override void OnAuthenticated ( IServiceBase authService,
                                          IAuthSession session,
                                          IOAuthTokens tokens,
                                          Dictionary<string, string> authInfo )
    {
        session.Id = _userViewModel.Id.ToString();
        session.UserName = _userViewModel.Email;
        session.FirstName = _userViewModel.FirstName;
        session.DisplayName = string.Format( "{0} {1}", _userViewModel.FirstName, _userViewModel.LastName );

        session.Roles = new List<string>();
        session.Permissions = new List<string>();

        if ( _userViewModel.Groups != null )
        {
            foreach ( var group in _userViewModel.Groups )
            {
                // Add user Groups to "Roles"
                session.Roles.Add( group.Name );

                if ( @group.SecuritySettings == null ) continue;
                foreach ( var securitySetting in @group.SecuritySettings )
                {
                    // Add group SecuritySettings to "Permissions"
                    session.Permissions.Add( securitySetting.Name );
                }
            }
        }

        var mapper = new AutoMapper<UserModel>();
        _container.Register( mapper.BuildFrom( _userViewModel ) );

        //Important: You need to save the session!
        authService.SaveSession( session, SessionExpiry );
    }

The problem I'm having is that my tests are still returning "Unauthorized" on my UserServiceInterface method

    [RequiredPermission("Read User")]
    public object Get( UserRequest request )
    {
        return new UserResponse { User = _userService.GetById( request.Id ) };
    }

I can confirm that the UserViewModel.Groups[0].SecuritySettings[0].Name == "Read User".

Upvotes: 2

Views: 368

Answers (2)

Chase Florell
Chase Florell

Reputation: 47377

The resolution to this issue is to call the base.OnAuthenticated method at the end of the CustomCredentialsAuthProvider.OnAuthenticated method.

    public override void OnAuthenticated ( IServiceBase authService,
                                           IAuthSession session,
                                           IOAuthTokens tokens,
                                           Dictionary<string, string> authInfo )
    {

        // truncated for brevity

        //Important: You need to save the session!s
        authService.SaveSession( session, SessionExpiry );

        // THIS ENSURES THE SESSION IS ACCESSABLE BY THE APP 
        base.OnAuthenticated(authService, session, tokens, authInfo);
    }

Upvotes: 1

mythz
mythz

Reputation: 143319

Here is the implementation of the RequiredPermissionAttribute:

public bool HasAllPermissions(IAuthSession session)
{
    return this.RequiredPermissions
        .All(requiredPermission => session != null 
            && session.HasPermission(requiredPermission));
}

The default implementation of which just checks AuthUserSession.HasPermission(), i.e:

public virtual bool HasPermission(string permission)
{
    return this.Permissions != null && this.Permissions.Contains(permission);
}

Which is overridable if you're using a CustomAuthSession. I'd recommend overriding HasPermission() and putting a breakpoint so you can introspect your session instance - as the current behavior only fails when the session doesn't have the required permission.

Upvotes: 0

Related Questions