Wednesday, August 19, 2026

Entra ID Temporary Access Pass (TAP) Delivery method for non Supported IGA tools

Standard

 Anytime you need to bring a batch of new users into a tenant at once a large new-hire cohort, a bulk migration, a group of external users who need day-one access you run into the same identity problem: how do you get everyone a usable credential securely, without a static password sitting in someone's inbox?

This post explains how I automated the process with Microsoft Entra ID Temporary Access Pass (TAP), Microsoft Graph, and Power Automate. My requirement is bulk onboarding, but it can also serve as the joiner trigger in the IGA process for general onboarding.

The problem

When a batch of new accounts lands in your Entra ID tenant, those people have zero trust relationship with your organization yet. You don't have their passwords, you can't assume their personal email is secure, and you generally don't know if their mobile number has been verified by anyone. So how do you get them a usable credential? 

The answer most identity teams land on is a Temporary Access Pass (TAP)  a time-boxed, single-use code that lets someone sign in and register their real credentials (Passkey, Authenticator, Windows Hello for Business) without ever touching a static password.

Additionally, if your organization has started rolling out phishing-resistant MFA, this is the best way to onboard new joiners and enforce conditional access so MFA is used only for phishing-resistant MFA. For the conditional access part, I’ll add a link at the bottom there.

The remaining problem is delivery. If you email someone their TAP and their sign-in instructions in the same message, you've just made one compromised mailbox equivalent to a compromised account. So the design principle I built around was simple:

Never put the credential and the instructions in the same channel.

The architecture

The pipeline has four moving parts:

  • A Microsoft Entra ID app registration — a scoped service identity that calls Microsoft Graph on the flow's behalf
  • Azure Key Vault — holds the app's client secret so it never sits in plaintext inside a flow definition
  • A SharePoint list — the new-user roster, which also doubles as an audit log (I’m using this because of limitations in my test environment, where Workday or the IGA tool isn’t provisioned.)
  • A Power Automate flow — the orchestrator

The sequence, once a new user row lands in SharePoint: For the test environment, SharePoint is currently the trigger point, but based on the requirements, we can move it to either Workday or an API connection.

  1. Get an OAuth token for Microsoft Graph (client credentials flow, secret pulled live from Key Vault)
  2. Resolve the user's Entra ID object ID from their UPN
  3. Generate a TAP for that user — single-use, capped lifetime, and optionally a delayed start time matched to their actual start date
  4. Send an email immediately with sign-in instructions. Additionally, we can arrange for an SMS connector and TAP to be delivered.
  5. Wait a few minutes
  6. Log the outcome back to the SharePoint row


 Prerequisites:

  • Azure Subscription
  • Power Automate Licensing for premium connectors
  • [Optional] SMS Gateway Subscription

Step by Step Configuration 

Step 1: App registration for Graph API access

  • Go to Entra ID > App registrations > New registration
  • Name it something like TAP-Automation-Onboarding
  • API permissions needed: UserAuthenticationMethod.ReadWrite.All, User.Read.All (application, not delegated, since this runs unattended)
  • Get admin consent

  • Go to Certificates & secrets and generate the New Client Secret
  • Note down the Value
  • go to Overview and note down the Client ID and Tenant ID as well 


Step 2: Trigger

  • Create a SharePoint Site and SharePoint List. List should content blow columns
    • ID Rename with UPN
    • Name - Single line of text
    • PersonalEmail - Single line of text
    • JoinDate - Date and Time
    • MobileNo - Single line of text
    • Status - Single line of text
    • TAP Generated - Date and Time
    • Email Sent - Yes/No
    • SMS Sent - Yes/No

Step 3: Create the flow

  • Go to make.powerautomate.com
  • Solutions (if you're using a solution for this project, recommended for ALM/deployment tracking) or My flows
  • New flow > Automated cloud flow
  • Name: Acquisition-TAP-Onboarding
  • Trigger: search for your list source, e.g. "When an item is created" (SharePoint) or "When a row is added" (Dataverse/Excel)
  • Configure the trigger's Site Address/List Name (or table)

  • Step 4: Initialize variables

    Add seven Initialize variable actions in sequence (click + > Add an action > search "Initialize variable" each time):
    NameTypeValue (set now or later from trigger)
    varUPNString                    dynamic content: trigger's email/UPN field
    varMobileString                    dynamic content: trigger's mobile field
    varAccessTokenString                    leave blank
    varTAPString                    leave blank
    varUserIdString                    leave blank
    varRecipientEmailString                    dynamic content: trigger's email field 
    varJoinDate           String                    leave blank

    Rename each action title via three dots (⋮) > Rename, e.g. Set varUPN, so the canvas is readable.

    Example:

    Step 5: Create an Azure Vault

    • Go to portal.azure.com
    • Subscriptions > open your subscription > Access control (IAM) > Add > Add role assignment
    • Search for Key Vault Secrets Officer, assign it to your own account (lets you manage secrets in any vault under this subscription)
    • Search for Key Vault in the top search bar > Create
    • Name: kv-tap-onboarding-wiley
    • Choose the correct subscription, resource group, and region > Review + create
    • Once deployed, open kv-tap-onboarding-wiley > Access control (IAM) > Add > Add role assignment
    • Search for Key Vault Secrets User, assign it to your automation app's service principal (search for TAP-Automation-Onboarding)

    Part 6: Get the client secret from Key Vault

    1. Go back to 
    2. + > Add an action > search Azure Key Vault
    3. Select Get secret
    4. If prompted to create a connection:
      • Connection name: Azure Key Vault - Get secret
      • Authentication type: Service Principal (Client Secret) — not Client Certificate Auth
      • Vault name: your vault name
      • Client ID: your app registration's Application (client) ID
      • Tenant: your tenant ID
      • Client Secret: paste the client secret value directly here (this one exception is fine, as discussed)
      • Click Create
    5. In the action body, Name of the secret: type TAP-Automation-ClientSecret exactly as named in the vault. (This is what we have created on step 5)
    6. Rename action: Get Client Secret

    Save.

    Part 7: Get an OAuth token from Microsoft Entra ID

    1. + > Add an action > search HTTP, filter to Built-in if both connector and built-in versions show up, select the plain HTTP action (icon is a simple shape, no service logo)
    2. Method: POST
    3. URI:
    https://login.microsoftonline.com/YOUR-TENANT-ID/oauth2/v2.0/token

    (Replace with Tenant ID)
    4. Headers: Key Content-Type, Value application/x-www-form-urlencoded
    5. Body: type this, then insert the dynamic token where indicated:

    grant_type=client_credentials&client_id=YOUR-APP-CLIENT-ID&client_secret=

    Click right after client_secret=, press /, select Get Client Secret > value. Then continue typing after the inserted token:

    &scope=https://graph.microsoft.com/.default
    1. Rename action: Get OAuth Token

    Save.

    Part 8: Parse the token response

    1. + > Add an action > search Parse JSON (Data Operations, built-in)
    2. Content: click in, press /, select Get OAuth Token > Body
    3. Schema: click "Use sample payload to generate schema", paste:
    json
    {
        "type": "object",
        "properties": {
            "token_type": {
                "type": "string"
            },
            "expires_in": {
                "type": "integer"
            },
            "ext_expires_in": {
                "type": "integer"
            },
            "access_token": {
                "type": "string"
            }
        }
    }
    1. Click Done
    2. Rename action: Parse Token Response

    Save.


    Part 9: Store the access token

    1. + > Add an action > search Set variable
    2. Name: select varAccessToken
    3. Value: click in, press /, select access_token under Parse Token Response's outputs
    4. Rename action: Set varAccessToken

    Save.

    Part 10: Look up the acquired user's object ID in Entra ID

    1. + > Add an action > search HTTP (built-in again)
    2. Method: GET
    3. URI:
    https://graph.microsoft.com/v1.0/users/@{variables('varUPN')}

    (insert varUPN via dynamic content/expression inside the URI field)
    4. Headers: Key Authorization, Value: type Bearer then insert varAccessToken dynamic content right after the space
    5. Rename action: Get User Object ID

    Save.

    Part 11: Parse the user lookup response

    1. + > Add action > Parse JSON
    2. Content: Get User Object ID > Body
    3. Schema: sample:
    json
    {
        "type": "object",
        "properties": {
            "id": {
                "type": "string"
            },
            "userPrincipalName": {
                "type": "string"
            }
        }
    }
    1. Rename: Parse User Lookup

    Save.

    Part 12: Store the user's object ID

    1. + > Add action > Set variable
    2. Name: varUserId
    3. Value: id from Parse User Lookup's outputs
    4. Rename: Set varUserId

    Save.

    Part 13: Generate the TAP

    1. + > Add action > HTTP (built-in)
    2. Method: POST
    3. URI:
    https://graph.microsoft.com/v1.0/users/@{variables('varUserId')}/authentication/temporaryAccessPassMethods
    1. Headers:
      • Authorization: Bearer + varAccessToken dynamic content
      • Content-Type: application/json
    2. Body:
    json
    {
      "lifetimeInMinutes": 480,
      "isUsableOnce": true,
      "startDateTime": "@{variables('varJoinDate')}"
    }
    1. Rename: Generate TAP

    Save.

    Note: Lifetimeinminutes follows the default TAP life time. In my environment, it is 8hr.

    Part 14: Parse the user lookup response

    1. + > Add action > Parse JSON
    2. Content: Generate TAP > Body > Body
    3. Schema: sample:
    json
    {
        "type": "object",
        "properties": {
            "id": {
                "type": "string"
            },
            "isUsable": {
                "type": "boolean"
            },
            "methodUsabilityReason": {
                "type": "string"
            },
            "temporaryAccessPass": {
                "type": "string"
            },
            "createdDateTime": {
                "type": "string"
            },
            "startDateTime": {
                "type": "string"
            },
            "lifetimeInMinutes": {
                "type": "integer"
            },
            "isUsableOnce": {
                "type": "boolean"
            }
        }
    }
    1. Rename: Parse User Lookup

    Save.

    Part 15: Store the TAP Value

    1. + > Add action > Set variable
    2. Name: varTAP
    3. Value: id from Parse Tap Response outputs
    4. Rename: Set varTAP

    Part 16: Send the email leg 

    1. + > Add action > search Send an email (V2) (Outlook connector)
    2. To: varRecipientEmail or trigger's email field
    3. Subject: Your XXX account is ready
    4. Body:
    Hello,
    
    Your account has been created: [insert varUPN dynamic content]
    
    Sign in at: https://myaccount.microsoft.com
    
    You will receive a one-time access code via SMS shortly. Do not share this code with anyone, including IT staff.
    
    Regards,
    IT Security
    1. Rename: Send Email Instructions

    Save.

    Part 17: Delay

    1. + > Add action > Delay
    2. Count: 5, Unit: Minute

    Save.

    Part 18: Send the SMS leg (TAP only)

    Requires an Azure Communication Services connection with a provisioned phone number, we haven't built this yet. When ready:

    1. + > Add action > search Azure Communication Services or Send SMS
    2. Set up connection with your ACS connection string
    3. From: your ACS number
    4. To: varMobile dynamic content
    5. Message: Your Wiley access code: + varTAP dynamic content + . Valid 24 hours, single use only.
    6. Rename: Send SMS TAP

    Save.

    Part 19: Log the outcome

    1. + > Add action > Update item (SharePoint) or Update a row (Dataverse), targeting the same row
    2. Set fields for status/timestamp

    Save.

    In the SharePoint columns we created for status, the SMS (Yes/No) and Email (Yes/No) fields will be filled in by this flow.

    Click the Test button on the top and do a manual test. once you update the sharepoint list this should send a email notification. for the email please check the Junk as if you are sending to your personal email ID. these can be flag as spam. 


    NOTE:

    In my scenario, I have built up to part 16 only. As per our requirement, we will deliver this to the hiring manager, who will verify it and share the information with the candidate. Additionally, for bulk onboarding, we only use the personal email ID as the acquisition email ID, so both the TAP and the email ID are delivered through email. 

    Additionally, for SMS, you need to provision Azure Communication Services first, or use another connector that supports SMS. Both options require a paid subscription to send SMS, which I have not covered here since my organization's requirement is only to send email at this moment. However, I believe SMS is the better way to share the TAP.

    Endless possibilities

    • Rather than triggering from SharePoint, there are connectors available for Workday or HTTP APIs to trigger from your organization's source of truth or IGA tool. You only need to change the trigger, and the rest of the workflow can remain the same.
    • For delivering to hiring managers, you can get a variable to set the end user's manager and share this with the manager as well.
    • SMS or secure link delivery methods can be integrated based on your requirement.


    Friday, December 5, 2025

    Azure PIM rollout with best practices

    Standard

    Common Roles and Responsibilities

    Azure role

                   Permissions

    Owner

    ·       Grants full access to manage all resources

    ·       Assign roles in Azure RBAC

    Contributor

    ·       Grants full access to manage all resources

    ·       Can't assign roles in Azure RBAC

    ·       Can't manage assignments in Azure Blueprints or share image galleries

    Reader

    ·       View all resources but does not allow you to make any changes.

    Role Based Access Control Administrator

    ·       Manage user access to Azure resources

    ·       Assign roles in Azure RBAC

    ·       Assign themselves or others the Owner role

    ·       Can't manage access using other ways, such as Azure Policy

    User Access Administrator

    ·       Manage user access to Azure resources

    ·       Assign roles in Azure RBAC

    ·       Assign themselves or others the Owner role

    Azure built-in roles - Azure RBAC | Microsoft Learn

    To create a subscription or billing profile, you need to have either the Account Admin or Enterprise Admin role. These roles are assigned directly and are not managed through PIM. Users with these roles are responsible for creating subscriptions and managing billing profiles. IAM Emergency access account will be added to Enterprise administrator role to as a recovery account. In situations where old employee is left and new employees need access; these emergency accounts could be used for recovery. 

    below diagram shows how we can grant Access using PIM.


    As indicated above, the basic method for managing permissions is to create and manage them using a Security group.

    Propose a plan to manage the management root. This permission applies to all subscriptions and resource groups. According to Microsoft best practices, the number of management root owners should not exceed three.
    Management Group permission management 

    This method ensures that only the IAM team can grant access to resources. If a task requires the Owner role for the Cloud team, they can obtain it through an approval workflow.

    Tips:

    • After the Enterprise admin creates a subscription, the user will automatically become the owner. Once the task is assigned to the IAM team, they should remove the previously added owner, as access will be properly inherited from the management group.
    • Alerts should be set up to notify multiple teams to ensure complete visibility on role enablement. We can also assign the SOC team to monitor these alerts.
    • Regarding the owner approval workflow, we can assign additional approvals if we need to accommodate multiple time zones and availability.
    • Even if you are listed on the approval list, you cannot approve your own request; it must be approved by someone else. Both the requester and the approver are required to add a justification as well.


    Tuesday, November 18, 2025

    PAW/SAW device filter refers to a device filtering technique in Entra ID

    Standard

     PAW/SAW device filter refers to a device filtering technique used in Microsoft Entra ID (formerly Azure AD) Conditional Access policies. Administrators apply it to target or exclude specific devices based on attributes, often to enforce secure administrative access.



    Key Concepts

    • PAW → Privileged Access Workstation: A hardened, locked-down device (physical or virtual) that privileged users (e.g., admins) must use for sensitive tasks, such as accessing Microsoft 365 admin portals, Azure resources, or PowerShell. PAWs reduce attack surface by isolating admin activities from everyday workstations.
    • SAW → Secure Access Workstation (or sometimes Secured Admin Workstation): A similar but slightly lower-tier concept than PAW, used for elevated but not fully privileged access. Some organizations and Microsoft guidance use PAW/SAW interchangeably or as a hierarchy (PAW for highest privilege, SAW for mid-tier).

    How the "Device Filter" Works in Conditional Access

    Microsoft Entra Conditional Access includes a "Filter for devices" condition (available since ~2021, now generally available). This allows policies to include/exclude devices matching rules based on device properties, such as:

    • device.extensionAttribute1 (commonly used)
    • device.trustType
    • device.isCompliant
    • device.displayName
    • device.deviceId, etc.

    A frequent pattern for PAW/SAW enforcement:

    1. Mark approved PAW/SAW devices in Entra ID by setting a custom attribute (e.g., extensionAttribute1 = "PAW" or "SAW").
    2. Create a Conditional Access policy targeting privileged users/roles:
      • Block access to sensitive cloud apps (e.g., Azure Management API, Microsoft 365 admin centers).
      • Under Conditions → Filter for devices → Configure → Exclude filtered devices where extensionAttribute1 Equals PAW (or SAW).
      • Result: Admins can only sign in from tagged PAW/SAW devices; all others are blocked.

    This forces privileged actions from secure workstations only, aligning with Zero Trust and Microsoft’s privileged access strategy.

    Why "PAW/SAW" Together?

    Documentation and community guidance often mention both:

    • PAW for the most sensitive roles (e.g., Global Admins).
    • SAW as a stepped-down version for less-critical elevated access.
    • The same device filter technique applies to both.

    Friday, September 5, 2025

    How to locate the application that's used for Entra ID application-based authentication?

    Standard

    What is Entra ID application base authentication? 



    Microsoft Entra ID application-based authentication (also known as app-based authentication) is a secure method for authenticating applications or services to Microsoft Entra ID (formerly Azure Active Directory). It leverages an application identity through the OAuth 2.0 client credentials flow, using certificate credentials or client secrets instead of traditional username/password combinations. This approach is ideal for service-to-service interactions, such as those in Microsoft Entra Connect (formerly Azure AD Connect), promoting passwordless security and reducing risks like credential exposure.

    Key Concepts

    • Application Identity: An app is registered in Entra ID as a service principal, assigned credentials (e.g., a certificate or client secret) for self-authentication, eliminating the need for user accounts.
    • OAuth 2.0 Client Credentials Flow: The app presents its credentials to Entra ID to acquire an access token, enabling access to resources like Microsoft Graph APIs without user involvement.
    • Passwordless Design: Certificates (preferred) or secrets minimize vulnerabilities associated with passwords, such as theft or rotation issues.
    • Use Cases: Backend integrations (e.g., app-to-app communication), automation scripts, and hybrid identity sync via Microsoft Entra Connect, where it replaces legacy service accounts for syncing on-premises Active Directory with Entra ID.

    Prerequisites

    • Entra Connect version 2.5.76.0 or later (download from the Microsoft Entra admin center, not the Download Center).
    • Administrative roles: Global Administrator or Hybrid Identity Administrator.
    • For certificates: Self-signed or CA-issued, with non-exportable private keys (preferably in HSM/TPM); Windows Server 2016+ with TLS 1.2.


    Locating the Application in Microsoft Entra ID

    After enabling, the app is registered automatically as a single-tenant, non-Microsoft application. It won't appear with names like "Microsoft Entra ID Connect"—instead:

    • Navigate to Microsoft Entra admin center > Enterprise applications > All applications.
    • Search for "ConnectSyncProvisioning" to find it.
    • For multiple servers: Each installation creates a unique app named "ConnectSyncProvisioning_[server name]", where [server name] is the Entra Connect server's hostname (e.g., "ConnectSyncProvisioning_ADConnectServer1").

    Viewing via Entra Connect Wizard
    • Launch the wizard and select Tasks > View or export current configuration.
    • Application ID will be visible on the configuration

    Benefits

    • Security Boost: Automatic rotations (every 6 months) and hardware protection via TPM/HSM.
    • Ease of Management: Reduces manual interventions; monitor via event logs (e.g., Event ID 1011 for expiration warnings).
    • Alignment with Zero Trust: Supports Microsoft's passwordless initiatives.

    Best Practices and Considerations

    • Certificate Management: For BYOC, use RSA 2048-bit keys with SHA256; revoke via admin center if compromised.
    • Monitoring: Use Azure Monitor for auth events; check logs for issues.
    • Limitations: Service-to-service only—not for user sign-ins. Test in staging servers first.
    • Troubleshooting: If not auto-configuring, ensure network access to Entra endpoints; manually rotate certificates via wizard if needed.