Self-service Microsoft Form for external guests to use Power App

This is a walk through of the steps to create a self-service guest user sign up using Microsoft Forms and redirects to the Power App.

Steps

  • Create a Microsoft Form to capture external user’s email address

  • Create the app registration to be able to make a Microsoft Graph invitation call

  • Use Power Automate via Microsoft Graph invitation API to add this email as external user to tenant

  • Add user to a group that the app is shared with

  • Redirect back to the Power App (or SharePoint extranet site, or Teams)

Create Microsoft Form

  • Change setting to allow anonymous - anyone can access this if they go to the form’s public shared URL

Create App Registration in Azure AD Portal

  • Go to Azure AD portal > App registration

  • You should name this app similar to your Power App name - it doesn’t need to be the same, but it’s less confusing to your tenant admins when reviewing the registered apps in Azure Portal.

  • As this app registration is only used for your tenant - it can be Single Tenant

  • Add Application Permission for User.Invite.All

  • This is a tenant admin consent required permission, so grant it here, or ask a tenant admin to grant it.

  • You will need to generate a Client Secret (no screen shot included), save that client secret.

  • You will also need to copy the Client ID

  • You will also need to copy the Directory ID (tenant ID)

Oh we need a Power App

  • Made a quick Power App here - the text label shows the current user’s email. For external user this would show external email (to proof this works).

  • For Sharing - I’ve made this Power App shared with Everyone.

  • We need to copy the Web link with the tenant-id

Now we need a Power Automate (Flow)

  • Run on Microsoft Form submission

  • We’ll need this redirect URL - when external guest invite is complete, redirect to our Power App

  • Because we registered an “Application Permission”, we can use the HTTP action to call Microsoft Graph without using delegate permission.

  • See also https://docs.microsoft.com/en-us/graph/api/invitation-post?view=graph-rest-1.0&tabs=http

  • Enter: Tenant, Audience, Client ID, Client Secret (not included in picture)

  • You should have all these values by this point.

  • The JSON message to send to Microsoft Graph should have the redirect URL back to the Power App

  • If successful we will get a user Object ID - we should add this to a Group as you need.

  • In my simplified example since my Power App is shared with Everyone - the external guest user will get access to it without being a member to a group.

Result

  • Switch to an external tenant (special thank you for Blackmores for example here)

  • Fill in the form

  • See the flow trigger and create an invitation from my tenant (Flow Studio Solutions) to guest tenant (Blackmores)

  • The guest email is added as a guest user type in my tenant

  • In the email of the guest email - Microsoft Azure AD sends a B2B invitation email

  • Note the redirect URL is the Power App we will be redirected to at the end of the guest invitation process

  • First time accepting will create this permission dialog reviewing that you (as guest) indeed want to be added to the external tenant. They will see your email, name and photo.

  • After successful redirect - the Power App loads, and look I’m using the Power App as an external user with external email address.

  • If the external user clicks the accept in the email again - they will skip the permission review process and be redirected by Azure AD into the Power App directly.

Variations and extra homework

  • The triggering mechanism doesn’t need to be Microsoft Forms. It can be a HTTP Request trigger that accepts an email address. In a scenario where I’ve build a child tenant to a parent tenant - some javascript on the child tenant send a POST request to the flow to initiate the invitation.

  • The email doesn’t need to be sent directly. The invitation API returns a redemption URL - which can be returned by the Flow in a HTTP Response to a calling javascript, and the user can be redirected to that redemption URL directly without needing to go through an email.

  • You can also capture the redemption URL and create your own email template.

  • You don’t need to redirect to Power App - you can be redirected to a SharePoint extranet that now includes the new guest user. Or to the Teams (by adding the guest user to the team’s group membership).

How to provision SharePoint list and resources with only standard Microsoft Flow using ExecuteSiteScriptAction

I wanted to blog about an interesting technique I was testing - how to call ExecuteSiteScriptAction from Microsoft Flow - and using that to provision SharePoint site.

We’ll do this all with Microsoft Flow and it is all part of the Flow / Office-Seeded license so there’s no extra cost.

Steps

  • YouTube: How to create custom SharePoint list in one action using ExecuteSiteScriptAction and Flow

  • Documentation links for Site Design and Scripting

  • ExecuteSiteScriptAction seems to be something new allowing us to directly execute site script without saving it as a site script first

  • Future ideas

I did a recording of this on YouTube last week, this blog post will cover the steps and goes a bit deeper into the technical details.

Documentation links for Site Design and Scripting

  • https://docs.microsoft.com/en-us/sharepoint/dev/declarative-customization/site-design-json-schema

  • https://docs.microsoft.com/en-us/sharepoint/dev/declarative-customization/get-started-create-site-design

ExecuteSiteScriptAction

ExecuteSiteScriptAction is a REST command available on the API, although doesn’t seem to be mentioned in the REST documentation (yet)

  • https://docs.microsoft.com/en-us/sharepoint/dev/declarative-customization/site-design-rest-api#rest-commands

I actually found out about this from reverse engineering the new SharePoint “Create List from Excel Spreadsheet” feature. I was reading how it was done in JavaScript, and came across this end point.

I did a search for ExecuteSiteScriptAction and finds a reference in PnPJS.

  • https://pnp.github.io/pnpjs/sp/site-scripts/#execute-site-script-action

  • https://github.com/pnp/pnpjs/issues/1096


What does this all mean?

ExecuteSiteScriptAction allows us to execute site script directly, without first saving it as a site script and then execute the site script.

So it’s ideal to provision a complex SharePoint resource.

Previously, I do this either via a series of REST calls, or use REST with $batch or call Azure Functions, but all those methods are more complex. Using Site Script is a much easier way to quickly ask SharePoint to provision the resource on the server side, without multiple trips of communicating with the server.

To do this in Flow (watch the video):

Use this in the first compose - create a JSON of the site script to createSPList with several subactions.

{
  "verb": "createSPList",
  "listName": "Customer_Tracking",
  "templateType": 100,
  "subactions": [
    {
      "verb": "setTitle",
      "title": "Customer Tracking"
    },
    {
      "verb": "setDescription",
      "description": "List of Customers and Orders"
    },
    {
      "verb": "addSPField",
      "fieldType": "Text",
      "displayName": "Customer Name",
      "isRequired": false,
      "id": "c532fcb9-cdb3-45c6-8247-c784dcd58e1a",
      "internalName": "customer_name",
      "addToDefaultView": true
    },
    {
      "verb": "addSPField",
      "fieldType": "Text",
      "displayName": "Customer Name 2",
      "isRequired": false,
      "id": "c532fcb9-cdb3-45c6-8247-c784dcd58e1b",
      "internalName": "customer_two",
      "addToDefaultView": true
    },
    {
      "verb": "addSPFieldXml",
      "schemaXml": "<Field ID=\"{c532fcb9-cdb3-45c6-8247-c784dcd58e1c}\" Type=\"Choice\" DisplayName=\"Customer Category\" Required=\"FALSE\" Format=\"Dropdown\" StaticName=\"customer_category\" Name=\"customer_category\"><Default>Operations</Default><CHOICES><CHOICE>Operations</CHOICE><CHOICE>IT</CHOICE><CHOICE>Legal</CHOICE><CHOICE>Engineering</CHOICE></CHOICES></Field>"
    },
    {
      "verb": "addSPField",
      "fieldType": "Text",
      "displayName": "Text Field",
      "isRequired": false,
      "addToDefaultView": true
    },
    {
      "verb": "addSPField",
      "fieldType": "Number",
      "displayName": "Number Field",
      "internalName": "ElectricSlide",
      "addToDefaultView": true,
      "isRequired": true
    }
  ]
}


Then create a second JSON

{
  "actionDefinition": "@{string(outputs('createSPList-definition'))}"
}

Finally, send that to SharePoint via REST

// _api/Microsoft.Sharepoint.Utilities.WebTemplateExtensions.SiteScriptUtility.ExecuteSiteScriptAction()


{
  "accept": "application/json; odata.metadata=minimal",
  "content-type": "application/json;charset=utf-8"
}

That’s it - all the actions are standard, and doesn’t require calling out to a webservice.


Future ideas / Homework

  1. Imagine Flows now can easily call this to create needed SharePoint list if it doesn’t exist.

  2. Or to upgrade SharePoint lists across many sites (use variable for site url).

  3. A new PowerApps can call an accompanied Flow to create the list that it needs.

  4. We can also use many of the other features within Site Script to modify permissions, set theme and colours etc.

  5. We can even use AddSPFieldXML to add complex fields via XML definition.

  6. As a final thought - I think the Site Script definition is a much easier way to define provisioning steps, since it’s really designed to be low code.

  7. Being able to use one technique (Site Script) to provision assets during:

    • Create Sites using out of box experience

    • Invoke with Power Automate (Flow)

    • And we can also invoke Site Script from SPFx in JavaScript through PnPJS

    • This kind of shared skill re-use, and with Microsoft extending site script makes this a great technique to learn and be familiar with.

  8. Daniel Laskewitz reached out and told me that we can add the new SharePoint REST API for creating new sites to completely automate creating new sites as well as provisioning the scripts all using Power Automate. Here’s the doc link he sent me. Thank you Daniel!

    https://docs.microsoft.com/en-us/sharepoint/dev/apis/site-creation-rest





Where to find John presenting in May 2020

We are living right now in a strange time. At home, and virtual events are replacing the traditional physical events.

I’ve agreed to several events and will be presenting all new (or freshly updated) topics for 2020. So while we remain physically distant, if you wanted to see one of my presentations - I’m actually a lot more visible.

May 01 - DC Power Apps & Power Automate usergroup - Why and How to implement Governance of the Power Platform

May 06 - Sydney Serverless meetup - Power Automate - Microsoft’s insane low-code serverless platform

May 11 - M365 May - Deep dive into Approvals in SharePoint and Teams with Power Automate

May 11 - USYD Cloud Society Azure/Power Up! - Intro Power Apps and Power Automate

May 15 - Sydney Power Apps and Flow usergroup - What’s new in Power Virtual Agents with Charles Sterling

May 16 - D365 Automation Saturday - Flow JAM Stack - how to build a complete low-code public website in 40 minutes

May 25 - UNSW Cloud Society - Azure/Power Up! - Intro Power Apps and Power Automate

May 26 - M365 May - Why and How to implement Governance of the Power Platform

May 27-28 - M365 Virtual Marathon - 5 Design Keys to make Flows run insanely fast

May 27-28 - M365 Virtual Marathon - Flow JAM Stack - how to build a complete low-code public website backed by M365

I’m still working on my YouTube series: How to build a public website with a Flow JAM Stack

Because of the events next week, I couldn’t work on an episode this week. But next Saturday’s Flow JAM Stack talk during the Automation Saturday will be a 40 minutes compressed teaser. Hope to catch you at one or many of these upcoming events.

Flow JAM Stack Episode 1 - sending data back with Flow as API

In this follow on episde, we dive a fair way in to see how we can customize Flow’s Request trigger to build a web service (API endpoint) that can be called from our static website.

Episode 1

  • Create a Flow service

  • Configure the form input params

  • Configure the service return HTML Redirect

  • Talk about embedding HTML FORM in static sites, but also hosted site scenarios - SharePoint, Power Apps Portal Apps, WordPress, SquareSpace.

We are deliberately going slowly going through some pitfalls and errors that you may see along the way, so the episode is progressing slowly, but I hope that’s the right direction to do this - we make sure there’s a firm foundation before moving to the next step.

I had initially hoped to get into API management, but it looks like that’ll be in a future episode.

In this episode, we extend the application with a HTML Form that will send messages back to Flow, which we then store into our backend datasource. If you hav...


Building modern public sites (JAM Stack) with Microsoft Flow

Web technologies evolve, and we are on the edge of a new stack, it is called JAMStack.

  • Javascript

  • API

  • Markup

In the world of JAM Stack, we create serverless public sites by hosting them directly from a CDN.

Now there are plenty of frameworks that will move to help developers to create this type of applications right now and next.

What I’m writing about is how citizen developers can take advantage of the same pattern to build public websites

Episode 0

  • Define JAM Stack

  • Set up data source (SharePoint)

  • Set up API (Flow)

  • Set up Storage (Azure Storage)

  • Set up CDN (Cloud Flare)

  • Set up dynamic trigger


Whether you are a Professional Developer or a Citizen Developer - you need to understand the basics of this stack. This will save you a LOT of money.

How we can use Microsoft Flow (Power Automate) to build public websites. This is a how-to video that involves defining the JAM Stack, Microsoft Flow, Azure B...