Workaround for sharing Canvas Apps

Don’t you find it absolutely frustrating when there’s a canvas app that you want to get access to, or give other users access to, but can’t see it? It’s REALLY annoying, but it’s sort of the way that Microsoft has designed the platform (at least at this point in time).

See, when a user creates a canvas app, only the creator is able to see & launch it. If other users want to get access to it, the creator needs to share it. This can be done by sharing the app directly with another user, or by sharing it with an AAD Security Group (which is sort of best practise).

Now, of course there’s the Microsoft Power Platform Centre of Excellence solution, which includes a very handy app to assign permissions for canvas apps. After all, if a user is on holiday, sick leave, or has left the company, there needs to be some way of assigning permissions for other users to gain access to it. It’s really helpful, but of course needs the CoE solution installed.

Let’s think of another scenario. What about if we have some canvas apps as part of a solution, that’s deployed through (proper) ALM – such as using Azure DevOps with automated pipelines. Best practise for this is to use service principals (ie non-interactive user logins). This is great, but then the canvas app/s will be owned by this user. So without the use of the CoE ‘Set App Permissions’ canvas app, we’re sort of stuck, as we can’t gain access to the app.

Or can we…..?

So this is a scenario that I’ve been dealing with recently, and I’ve found a really cool workaround that doesn’t need the CoE ‘Set App Permissions’ canvas app to be able to handle the situation.

The example below (amusingly, in my opinion) is actually using the Microsoft CoE solution as an example, but this works with any canvas apps that are held within a solution (against, this heavily supports using solutions for ALL development items!).

So, this is what the actual installed apps look like in this environment:

As we can see, there are a lot of them! But what happens if I’m logged in as my regular user? What do I see if I go to the list of apps? Well, I’ll see the following:

Now, as we can see, I’m able to see the model-driven app (as these aren’t hidden at all). But I’m not able to see ANY of the canvas app! So how can I get access to it, or share it with other users?

Well, if I take a look at the solution itself, I can see the following when browsing to the list of apps (I’m really loving the new Solution Explorer layout, I’ll freely admit!):

I can try to play the canvas app (in this case, the ‘Set App Permissions’ app) directly from the solution. But when I try to do this, I’ll get the following error message:

Now, this is of course happening because I’m not the owner of the app, & the app hasn’t been shared with me at all. So really I was expecting this error to happen.

However, if I take a look at the menu options displayed for me, I can see that the ‘Share’ option isn’t greyed out. I wonder what happens if I click it…

Now this is EXCITING! When clicking the ‘Share’ option on the menu, I’m given the regular sharing screen, where I’m able to set app permissions. So it looks like I’m able to do something here. OK – let’s go ahead & try to share the app with my own user:

So I’ve looked up my own user, and then clicked ‘Share’. This is what happens next…

Exciting moment – will this work?

Waiting with bated breath, and then…

It’s worked! The app sharing has been successful with my user.

Note: The example that I’m using here is with my own user account. However it doesn’t need to be – I can select any user account or AAD Security Group, and share accordingly.

Going to my list of apps, I can now see that the app is showing up for me:

Clicking the app to launch it presents me with the permissions dialogue, and having confirmed permissions, then launches it properly:

So this is indeed a way in which it’s possible to share canvas apps with users and/or AAD security groups, even when a user isn’t the owner of the canvas app.

It is important to note that the user carrying this out does need to have one of the following permissions in the environment:

  • System Customiser
  • System Administrator

Without having one of these roles, it’s not going to be possible to carry out the above (mostly because it’s not possible to see solutions & dig down into them).

This is a handy little trick that hopefully will help clear up one of the headaches when trying to share canvas apps! Of course it’s possible to use the Microsoft CoE tool to set app permissions, but if a customer doesn’t have it installed, then this would be another way to approach things.

Have you ever had this issue? How did you go about solving it? I’d love to hear – please drop a comment below…

Record security with Power Automate

Today’s post is around record security, and how Power Automate can really be quite useful with this!

Let’s take a quick recap of how security works (which is applicable to both Dynamics 365, as well as Power Platform apps). We have the following:

  • Security roles, which are set up with specific privileges (Create/Read/Update/Delete etc) across each entity table, as well as for other system permissions
  • Users, who can have one (or more) security roles applied to them (security roles being additive in nature)
  • Teams, who can have one (or more) security roles applied to them. Users are added into the team, and inherit all permissions that the team has (much easier than applying multiple roles on a ‘per user’ basis)

That’s great for general security setup, but it does take a system admin to get it handled. Alternatively, of course, it’s possible to use AAD Security Groups which are connected to security teams within Power Platform, and users added to them will inherit the necessary permissions.

But what if we want to allow users who aren’t system administrators to allow other users access to the records? Well, it’s also possible to share a specific record with another user – doing this allows the second user to see/access the record, even if they usually wouldn’t be able to do so. This is really great, but does require a manual approach (in that each record would need to be opened, shared with the other user/s, and then closed).

I’ve been working on a project recently where we have the need to share/un-share a larger number of records, but with a different user for each record. We’ve been looking into different ways of doing this, and obviously Power Automate came into mind! We didn’t want to use code for this, for a variety of reasons.

Security and Compliance in PowerApps and Flow - Michał Guzowski Consulting

The scenario we had in mind was to have a lookup to the User record, and with populating this with a user, it would then share the record with them. This would be great, as we could bulk-update records as needed (even from an integration perspective), and hopefully all would work well.

So with that, I started to investigate what options could be available. Unfortunately, there didn’t seem to be any out of the box connectors/actions that could be used for this, which was quite disheartening.

My next move was to look at the user forums, & see if anyone had done anything similar. I was absolutely excited to come across a series of responses from Chad Althaus around this exact subject! It turns out that there’s something called ‘Unbound Actions’, which is perfect for the scenario that we’re trying to achieve.

There are two types of actions available within Power Automate:

  • Bound actions. This are actions that target a single entity table or a set of records for a single entity table
  • Unbound actions. These aren’t bound to an entity type and are called as static operations. They can be used in different ways

There are quite a lot of unbound actions available to use:

The one I’m interested in for this scenario is the GrantAccess action. More information around this can be found at https://docs.microsoft.com/en-us/dynamics365/customer-engagement/web-api/grantaccess?view=dynamics-ce-odata-9

It does require some JSON input, but when formatted correctly, it shows along the following lines:

The different parts of this works as follows:

  • Target is the actual record we’re wanting to apply the action to
  • SystemUserID is the actual system user, and we also need to specify the odatatype
  • AccessMask is what we’re wanting to do when sharing the record (as there are different options available for sharing, ie ReadOnly, Edit, ShareOnwards, etc)

Using this, we’ve therefore built out the following scenario:

  1. Field added to the record, looking up to Users
  2. Relevant users who are able to access the record can set this lookup field to be a specific user record (who doesn’t have access to this record)
  3. Power Automate flow fires on the update of the record when it’s saved (filtering on just this attribute), sharing the record with the selected user
  4. The user then gets an email to notify them that the record has been shared with them, with a URL link to it (it’s somewhat annoying that there’s no inbuild system notification when a record has been shared with you, but I guess that’s something we’re having to live with!)
  5. They can then go in & access the record as they need to

We’ve also given some thought to general record security, and have additionally implemented the following as well:

  1. If the user lookup value is changed, we obviously share the record with the new user that’s been saved to it
  2. Using a different Unbound Action (RevokeAccess), we remove the sharing of the record with the previous user (we have another field that’s being updated with the value of it, which we’re using to pass the action in, as otherwise we don’t actually know who the previous user was!)

All in all, we’re quite happy that we’ve managed to come up with this solution, which is working splendidly for us. Also, major thanks to Chad for his assistance in getting the syntax correct!

Have you ever needed to do something like this? Did you manage to implement it in some way? Drop a comment below – I’d love to hear how your experience was!