Testing Power Apps with Role-Based Security
When we build apps (or applications before them), we often build different behaviors or capabilities based on the role of the current user. For example, when I ask for some time off, my manager can approve it, but I can’t.
In a Power App, there are many different ways to implement role-based permissions. I’ve put a few articles into the Resources below showing some approaches.
Testing the Power App by playing the different roles can be very hard. Each user who loads the Power App is themselves, right?
Well, here’s a trick I’ve been using to make things much easier for testing.
Here are the high level steps:
- Set up the roles using whatever mechanisms you choose. As a SharePoint guy, I like to use lists wherever possible so it’s easy to maintain the roles over time.
- In your Power App’s initial screen, set up logic to determine the current user and set variables to reflect that user’s role(s) at an app level. (You’re likely to have additional roles when you get deeper into the app, perhaps working with specific items. This approach works there, too!)
- Add a
Combo box
to the screen which allows you to select any user. - Switch the current user to the “assumed user” when you want to test with that user and their role(s).
Determining the current user is easy: we just use the User() function. But the User()
function isn’t really complete enough. I always then define a second variable for currentUser
by getting their Office365Users.UserProfile
. This requires the Office365Users
connector.
When I create a new Power App, one of the first things I do is add these lines to the OnVisible
property of the initial landing screen:
// User
Set(thisUser, User());
Set(currentUser, Office365Users.UserProfile(thisUser.Email));
Between User()
and Office365Users.UserProfile
, this tells me most of the base information Microsoft 365 knows about the user. Yes, I could use Office365Users.MyProfile()
to get the user’s profile information, but then this testing trick wouldn’t work. By using Office365Users.UserProfile
and passing in an email address, I can get anyone’s user profile.
Add a Combo box to the screen and rename it to ComboBox_AssumePerson
.
Set the Items
for ComboBox_AssumePerson
to:
Office365Users.SearchUser({searchTerm:ComboBox_AssumePerson.SearchText,top:10})
For the OnChange
property, add code similar to the following. Here, I’m setting two variables to the selected user from ComboBox_AssumePerson
: assumeUser
and the currentUser
we’ve already defined.
Set(assumeUser, ComboBox_AssumePerson.Selected);
Set(currentUser, ComboBox_AssumePerson.Selected);
Set(returnToLanding, true);
Navigate(PermissionCheck, ScreenTransition.Cover);
Because of the way we’ve set up the Items
for ComboBox_AssumePerson
, on selection, we get an object which is equivalent to our call to Office365Users.UserProfile
: same type of object, with the same properties.
Now change the last line in the // User
code above to assume the selected user if there is one.
Set(currentUser, If(IsBlank(assumeUser), Office365Users.UserProfile(thisUser.Email), assumeUser));
Because I’m setting all the role information in the OnVisible
property for the landing screen, just changing the currentUser
isn’t enough. To make the change “stick”, I’m navigating to another screen called PermissionCheck
which looks at the returnToLanding
value in its OnVisible
property, and if it it set to true
, it navigates right back. That means the role-based calculations all happen again, but this time in the context of assumeUser
.
If(returnToLanding, Set(returnToLanding, false); Back());
By the way, that PermissionCheck
screen can be really handy, too. The only thing going on in that screen is to show the current user’s roles. I tend to set variables like isAdmin
, isManager
, isExecutive
, or isContactTracer
on the landing screen. The PermissionCheck
screen shows me those values for the current or assumed user whenever I need to be sure what they are. It doesn’t need to be pretty, but by displaying your role-based variables, you have an easy way to check your logic.
Now you can wander around your Power App as the user you have selected and the permissions you have determined for that user.
How do we undo that user assumption? We simply clear the ComboBox_AssumePerson
, which fires its OnChange
property. Then this line from above sets things back to the real user who is using the Power App because assumeUser
no longer has a value.
Set(currentUser, If(IsBlank(assumeUser), Office365Users.UserProfile(thisUser.Email), assumeUser));
Caveats
As with most things, there are some very clear caveats to this approach.
- When you assume another user’s identity in the app, you’re still you beneath the covers. That means any items created in lists will still be created by you. You’re only able to assume the other user’s identity in the Power App itself.
- Everywhere you figure out the user’s roles, be sure to use
currentUser.Mail
– NOTthisUser.Email
– to match users from your permission structures. There’s an example of this in my previous post Power Apps: Filtering by Multi-select SharePoint Columns, where I check the user in Section 3. - Be sure you have some indication on your screens showing who you are while you’re running the Power App. I think this is a good practice, anyway, but it’s especially important when you have this capability set up. (Who am I again?) I usually have something like this in the upper right of every screen.
- Some logic may not work with this approach. For example, I can display the
User()
‘s photo, but not thecurrentUser
‘s. - For debugging – even after you launch the Power App for production use – you may want to leave this “back door” in place. But be sure to set the
Visible
property forComboBox_AssumePerson
so only someone in a role you consider an admin can use it. And make sure they understand it!