Close Menu
Peter Klapwijk – In The Cloud 24-7Peter Klapwijk – In The Cloud 24-7
    Facebook X (Twitter) Instagram
    Peter Klapwijk – In The Cloud 24-7Peter Klapwijk – In The Cloud 24-7
    • Home
    • Intune
    • Windows
      • Modern Workplace
    • macOS
    • Android
    • iOS
    • Automation
      • Logic Apps
      • Intune Monitoring
      • GitHub
    • Security
      • Passwordless
      • Security
    • Speaking
    • About me
    Peter Klapwijk – In The Cloud 24-7Peter Klapwijk – In The Cloud 24-7
    Home»Automation»Build your own user onboarding automation – Day 1: enable the account and create a Temporary Access Pass
    Automation

    Build your own user onboarding automation – Day 1: enable the account and create a Temporary Access Pass

    Peter KlapwijkBy Peter KlapwijkFebruary 18, 2025Updated:May 16, 202511 Mins Read

    Recently I shared this blog post about creating a low-code automation solution to easily create users in Entra ID. This is the follow-up blog post in the user onboarding automation series.

    This second automation flow enables the user account of users that have a hire date of today. Besides that a Temporary Access Pass is created for passwordless onboarding. The new user is informed on the personal e-mail account and the manager is informed a new colleague is starting today.

    The solution is short

    This second Logic Apps flow runs every day, early in the morning, and checks for all user accounts in the Entra ID environment of which the status is disabled and the creation date is in the last 7 days. The idea of this is that the automatically created accounts are still in a disabled state and have been created in the past week. When the hire date of one of these accounts matches the date of today, the flow is further executed. The flow creates a Temporary Access Pass (TAP) for the user, with the start date/ time today 9:00AM and lifetime for 180 minutes. This means the onboarding can be done with the TAP between 9:00AM and 12:00PM.

    The users manager is retrieved, to inform the manager per e-mail about the new joiner and the TAP is shared with the manager. Also the new user is informed by the flow on the personal email address, sharing some welcome information including the User Principal Name.

    The flow is available as a template on my GitHub repo for easy deployment.

    Requirements

    We have some requirements that need to be in place before we can use our Logic Apps flow.

    To enable the user account, create a TAP and get the managers information, we make use of Graph API queries. To be allowed to run these queries, we need an identity for authentication and to assign permissions to. I prefer to make use of a Managed Identity, as that is an easy to manage and secure option. We have the option to use a system-assigned and user-assigned managed identity, as you can read in the documentation. In my case, I make use of a system-assigned MI, as that is considered the most secure. 

    This Managed Identity needs to have (application) permissions to execute all the Graph calls we make. These are the application permissions needed for our flow;
    User.ReadWrite.All
    UserAuthenticationMethod.ReadWrite.All

    As I inform the manager and new user per e-mail, I need a (service) account to send e-mails from a shared mailbox. If you have other needs to inform the manager or user, this requirement differs.

    Setting up the flow

    When we have our requirements in place including the SharePoint Lists, we can start building the Azure Logic Apps flow.

    Sign in to the Azure portal and open the Logic Apps service. Create a Logic App of type Consumption.
    We need to select a subscription, resource group, and region, and enter the name of the flow before we can create the Logic Apps flow.

    When the flow is created, click on the name of the flow at the top of the screen, and open the Identity section. On the System assigned tab, set the switch to On.

    Make sure to assign the application permissions to the system-assigned manager identity.

    Browse to the Overview tab and click on Edit. 
    The first thing we need to add to the flow is a Trigger. Click on Add a trigger and search for Schedule. We need to add a Recurrence trigger to the flow.

    With the recurrence trigger, we trigger the flow to start based on the schedule we create. I want to run the flow every day, at 6:00AM and to avoid issues with time zones, I also select the Time Zone.

    Next, we add our first HTTP action to run a Graph API call.

    With this HTTP action we query all Entra ID user accounts, that are disabled. Besides that the filter checks if the hire date is today between 00:00:00 and 23:59:59.

    Select GET as Method.
    Next, select Authentication under Advanced parameters.
    As Authentication type select Managed identity.
    Select System-assigned managed identity from the list.
    And add https://graph.microsoft.com as Audience.
    Enter below URI:

    https://graph.microsoft.com/v1.0/users?$select=id,displayName,givenName,surname,userPrincipalName,mail,otherMails,accountEnabled,createdDateTime,employeeHireDate&$filter=employeeHireDate%20ge%20@{formatDateTime(utcNow(), 'yyyy-MM-dd')}T00:00:00Z%20and%20employeeHireDate%20le%20@{formatDateTime(utcNow(), 'yyyy-MM-dd')}T23:59:59Z%20and%20accountEnabled%20eq%20false&$count=true

    In the above URI we have something with [formatDateTime] twice. These are Expressions. With these expressions we can add the current date and time (but also add hours or days to the current date/ time, or we can take the current date minus a number of days if needed). We can add expressions by clicking on the fx button.

    For the first hire date filter I want to use the date of today and time 00:00, and for the second hire date filter I want todays data and time 23:59. Therefor we can use the below expression in oth cases, which adds todays date with uctNow (which means today, this time). And I also specify the format, which is yyyy-MM-dd. With this format I only retrieve the date, and not the time. As the time for both cases is specified already in the URI.

    formatDateTime(utcNow(), 'yyyy-MM-dd')

    Next, we need to add a Parse JSON action, which is a Data operations action. We parse the output of the HTTP action, to be able to use the values later on in the flow.

    Add the Parse JSON action to the flow.
    In the Content field, we add Body, which is found as dynamic content of the HTTP action. Dynamic content can be found by hitting the lightning button.

    We don’t have to write the schema ourselves, we can generate it by adding a sample payload. We can get this example payload, by running the current flow and grabbing the output from the HTTP action. We can also grab the body when we run the same query via Graph Explorer.

    Schema:

    {
        "type": "object",
        "properties": {
            "@@odata.context": {
                "type": "string"
            },
            "@@odata.count": {
                "type": "integer"
            },
            "value": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "id": {
                            "type": "string"
                        },
                        "displayName": {
                            "type": "string"
                        },
                        "givenName": {
                            "type": "string"
                        },
                        "surname": {
                            "type": "string"
                        },
                        "userPrincipalName": {
                            "type": "string"
                        },
                        "mail": {
                            "type": "string"
                        },
                        "otherMails": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        },
                        "accountEnabled": {
                            "type": "boolean"
                        },
                        "createdDateTime": {
                            "type": "string"
                        },
                        "employeeHireDate": {
                            "type": "string"
                        }
                    },
                    "required": [
                        "id",
                        "displayName",
                        "givenName",
                        "surname",
                        "userPrincipalName",
                        "mail",
                        "otherMails",
                        "accountEnabled",
                        "createdDateTime",
                        "employeeHireDate"
                    ]
                }
            }
        }
    }

    And the Parse JSON action;

    For some error handling I added a Condition action, which is a Control action, to the flow. With this condition I check if the employee hire date starts with the day of today. Just to make sure we don’t run the flow for an user who will start tomorrow, for example.

    In the left field, we add employeeHireDate which is a value from the Parse JSON action. This adds the Condition action in a For each action. This is a loop action, to loop through all disabled accounts.
    Select starts with from the drop-down list.

    In the right field add below expression, to add the current date to the condition:

    formatDateTime(utcNow(),'yyyy-MM-dd')

    And this is our condition action. When the hire date starts with the date of today, the outcome is true and the flow continues.

    Under True, we add an HTTP action.

    Select PATCH as Method.
    Next, select Authentication under Advanced parameters.
    As Authentication type select Managed identity.
    Select System-assigned managed identity from the list.
    And add https://graph.microsoft.com as Audience.
    Enter below URI:

    https://graph.microsoft.com/v1.0/users/[ID]

    Replace [ID] with the ID found as dynamic content from the Parse JSON action.

    As body we use below JSON to enable the user account:

    {
      "accountEnabled": true
    }

    In the next HTTP action, we will create the Temporary Access Pass.

    Select POST as Method.
    With this URI:

    https://graph.microsoft.com/v1.0/users/[ID]/authentication/temporaryAccessPassMethods

    Replace [ID] with the ID found as dynamic content from the Parse JSON action.

    And the below JSON in the Body field:

    {
      "startDateTime": "[formateDateTime]T09:00:00.000Z",
      "lifetimeInMinutes": 180,
      "isUsableOnce": false
    }

    Fill in the required header information:
    Content-Type – application/json

    As date we use an expression, to replace [formateDateTime]:

    formatDateTime(utcNow(),'yyyy-MM-dd')

    This will set the start date time for the TAP to today with a start time of 9:00.
    Change the time, lifetime and is usable once to your own needs.

    Another option for the expression for the data and time is to also set the time, instead of specifying the time in the JSON. This below expression for example takes the current date and time and adds three hours to it:

    formatDateTime(addHours(utcNow(),3),'yyyy-MM-ddTHH:mm:ssZ')

    The JSON than looks like below:

    The TAP is readable in the history of the flow. This means everybody with access to the flow has access to the TAP. To avoid this, we can change the security of the HTTP Action on the Settings tab.
    Under security, switch Secure inputs/ outputs to On.

    We need to parse the output from the HTTP action with a Parse JSON action.

    Add the Body from the HTTP action in the Content field and create the schema.

    Schema:

    {
        "type": "object",
        "properties": {
            "@@odata.context": {
                "type": "string"
            },
            "id": {
                "type": "string"
            },
            "isUsable": {
                "type": "boolean"
            },
            "methodUsabilityReason": {
                "type": "string"
            },
            "temporaryAccessPass": {
                "type": "string"
            },
            "createdDateTime": {
                "type": "string"
            },
            "startDateTime": {
                "type": "string"
            },
            "lifetimeInMinutes": {
                "type": "integer"
            },
            "isUsableOnce": {
                "type": "boolean"
            }
        }
    }

    To be able to inform the manager of the new user, we need to get some information of the manager. This can be retrieved with a HTTP Get action.

    We use the below URI:

    https://graph.microsoft.com/v1.0/users/[ID]/manager?$select=id,displayName,givenName,surname,mail

    Replace [ID] with the ID found as dynamic content from the first Parse JSON action.

    And of course, this is followed by a Parse JSON action:

    The account is enabled, the Temporary Access Pass created and information about the manager retrieved. We can now inform the manager and the new colleague.

    Add a Send and email from a shared mailbox action.

    Fill in an Original Mailbox Address from the shared mailbox. In the To field, we can add mail. This is a dynamic content value of the Parse JSON action related to the HTTP action that retrieved the managers information.
    Add some text to your needs to the Body field. In the body we also include the Temporary Access Pass.

    On the settings tab, under Security switch on Secure inputs/ outputs (as the action contains the TAP).

    We add a parallel branch to the flow, to run both send email actions at the same time. For this, hit the plus button above the first send an email action and select Add a parallel branch. Under the new branch, add the second Send an email action.

    Fill in the information to your needs, including the User Principal Name of the new user. The UPN is dynamic content from the Get disabled users Parse JSON action.

    In the To field, we need to enter the new colleagues personal e-mail, which is stored under otherMails (at least I hope it is, otherwise you don’t have an option to share the UPN automatically with the new colleague).

    OtherMails could contain multiple e-mail addresses, therefor we use below expression to grab the first mail address:

    first(item()?['otherMails'])

    With the send an email action added, we finished our flow.

    At the end of the flow, we can add some actions for error handling like shown in the first part of this onboarding series.

    The end result

    The end-result is that the users account is enabled on the hire date and a Temporary Access Pass is created.

    The users manager is informed the new colleague starts today and the TAP is shared with the manager.

    The new colleague itself is also informed by e-mail. In the e-mail the user can find the User Principal Name and inform the user this is shared with the manager.

    By creating the two Azure Logic Apps flows we created low-code automation for our HR department, so they can easily create new user accounts, including license and group assignment. Early in the morning of the hire date, the users account is enabled, a TAP created and both the manager and user are informed.

    That’s it for now. Keep an eye on the upcoming blog posts related to automating the user onboarding experience.

    The JSON template to deploy the flow can be found on GitHub including a script to assign permissions to the Managed Identity.

    Hit the below button to upload the template to your Azure environment directly.

    Thanks for reading!

    Automation Entra ID Identity Management Modern Workplace Power Automate user onboarding
    Share. Facebook Twitter LinkedIn Email WhatsApp
    Peter Klapwijk
    • Website
    • X (Twitter)
    • LinkedIn

    Peter is a Security (Intune) MVP since 2020 and is working as Modern Workplace Engineer at Wortell in The Netherlands. He has more than 15 years of experience in IT, with a strong focus on Microsoft technologies like Microsoft Intune, Windows, and (low-code) automation.

    Related Posts

    Build your own user onboarding automation: Send a notification when Windows 365 provisioning is finished

    February 25, 2025

    Build your own user onboarding automation – Entra ID user account creation

    February 13, 2025

    How I solved a strange Kerberos issue

    December 12, 2024
    Add A Comment
    Leave A Reply Cancel Reply

    Peter Klapwijk

    Hi! Welcome to my blog post.
    I hope you enjoy reading my articles.

    Hit the About Me button to get in contact with me or leave a comment.

    Awards
    Sponsor
    Latest Posts

    Update Windows Defender during Windows Autopilot enrollments

    May 16, 2025

    Hide the “Turn on an ad privacy feature” pop-up in Chrome with Microsoft Intune

    April 19, 2025

    How to set Google as default search provider with Microsoft Intune

    April 18, 2025

    Using Windows Autopilot device preparation with Windows 365 Frontline shared cloud PCs

    April 13, 2025
    follow me
    • Twitter 4.8K
    • LinkedIn 6.1K
    • YouTube
    • Bluesky 1.5K
    Tags
    Administrative Templates Android Automation Autopilot Azure Azure AD Browser Conditional Access Edge EMS Exchange Online Feitian FIDO2 Flow Google Chrome Graph Graph API Identity Management Intune Intune Monitoring iOS KIOSK Logic Apps macOS MEM MEMMonitoring Microsoft 365 Microsoft Edge Microsoft Endpoint Manager Modern Workplace Office 365 OneDrive for Business Outlook Passwordless PowerApps Power Automate Security SharePoint Online Teams Windows Windows 10 Windows10 Windows 11 Windows Autopilot Windows Update
    Copy right

    This information is provided “AS IS” with no warranties, confers no rights and is not supported by the authors, or In The Cloud 24-7.

     

    Copyright © 2025 by In The Cloud 24-7/ Peter Klapwijk. All rights reserved, No part of the information on this web site may be reproduced or posted in any form or by any means without the prior written permission of the publisher.

    Shorthand; Don’t pass off my work as yours, it’s not nice.

    Recent Comments
    • Adam on Get notified on expiring Azure App Registration client secrets
    • Peter Klapwijk on Update Windows Defender during Windows Autopilot enrollments
    • Rob van de Ven on Add a certificate to the Trusted Publishers with Intune without reporting errors
    • Carl on Update Windows Defender during Windows Autopilot enrollments
    • Peter Klapwijk on The next step in a passwordless Windows experience
    most popular

    Application installation issues; Download pending

    October 1, 2024

    Restrict which users can logon into a Windows 10 device with Microsoft Intune

    April 11, 2020

    How to change the Windows 11 language with Intune

    November 11, 2022

    Update Microsoft Edge during Windows Autopilot enrollments

    July 9, 2024
    Peter Klapwijk – In The Cloud 24-7
    X (Twitter) LinkedIn YouTube RSS Bluesky
    © 2025 ThemeSphere. Designed by ThemeSphere.

    Type above and press Enter to search. Press Esc to cancel.

    Manage Cookie Consent
    To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
    Functional Always active
    The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
    Preferences
    The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
    Statistics
    The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
    Marketing
    The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
    Manage options Manage services Manage {vendor_count} vendors Read more about these purposes
    View preferences
    {title} {title} {title}