Automatically Adding Users to Security Groups based on Sign In

Jinki Lee 100 Reputation points
2026-07-02T16:58:58.58+00:00

In our Entra External ID tenant, we support customers from two different business units, each with its own application and login page. We would like to classify users and assign them to security groups based on the application they use to sign in.

For example:

abc.domain.com = customer belongs to the “abc” business unit

xyz.domain.com = customer belongs to the “xyz” business unit

Some customers may sign in to both applications, in which case they would belong to both business units.

What is the recommended approach or best practice for handling this scenario? Should we use a Function App to add users to the appropriate security groups after a successful sign-in (based on the App Registration Client ID)?

User's image

Microsoft Security | Microsoft Entra | Microsoft Entra External ID
0 comments No comments

1 answer

Sort by: Most helpful
  1. Jerald Felix 16,015 Reputation points Volunteer Moderator
    2026-07-03T13:50:51.34+00:00

    Hello Jinki Lee ,

    Greetings! Thanks for raising this question in the Q&A forum.

    Your instinct to use a Function App keyed off the App Registration Client ID is exactly the right approach, and it maps directly onto a built-in capability rather than something you need to bolt on separately. Instead of triggering the Function App as a separate step after sign-in completes, hook it into the sign-in flow itself using a custom authentication extension on the OnTokenIssuanceStart event. This event fires for every sign-in, and its payload already includes the client application's App ID (under clientServicePrincipal.appId) and the user's object ID, which is exactly what you need to determine which business unit group the user should belong to, with no separate post-login call or extra latency for the user.

    1. Create the Azure Function that will act as your custom claims provider REST API

    The function receives the OnTokenIssuanceStart payload, reads data.authenticationContext.clientServicePrincipal.appId to determine which app the user is signing into, maps that to the correct security group ID (abc.domain.com app registration's Client ID maps to the "abc" group, xyz.domain.com's maps to the "xyz" group), and then calls Microsoft Graph to add the user to that group if they are not already a member.

    1. Add the group membership call using Microsoft Graph inside the function

    Use application permissions (client credentials) since this runs server-side with no user context:

    POST https://graph.microsoft.com/v1.0/groups/{groupId}/members/$ref
    Content-Type: application/json
    
    {
      "@odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/{userId}"
    }
    

    Check membership first (or catch the duplicate-member error and ignore it) so repeat sign-ins do not fail the extension:

    GET https://graph.microsoft.com/v1.0/users/{userId}/memberOf/microsoft.graph.group?$filter=id eq '{groupId}'
    
    1. Register the Function App as the API Authentication app for the extension and grant it Graph permissions

    The app registration created during the custom authentication extension setup (used to secure calls to your Function) needs GroupMember.ReadWrite.All as an application permission with admin consent, in addition to the CustomAuthenticationExtension.ReceivePayload permission that gets granted automatically when you click Grant permission during setup.

    1. Register the custom authentication extension for the TokenIssuanceStart event

    In the External ID tenant, go to Entra ID > External Identities > Custom authentication extensions > Create a custom extension, select TokenIssuanceStart, and point it at your Function's URL. Do this once, since a single custom claims provider can serve multiple applications, your function logic differentiates behavior per app using the client App ID from the payload rather than needing a separate extension per app.

    1. Attach the custom claims provider to both applications

    For each of your two app registrations (abc and xyz), go to the corresponding enterprise application's Single sign-on > Attributes & Claims > Advanced settings > Custom claims provider, and select the extension you created. This ensures the OnTokenIssuanceStart event fires, and your function runs, regardless of which of the two apps the customer signs into.

    1. Handle the users who sign into both apps naturally, no special logic needed

    Since the function runs independently on every sign-in and simply adds to a group if not already present, a customer who signs into both abc.domain.com and xyz.domain.com over time will end up in both groups automatically the first time they authenticate through each app, with no extra code required to handle that case.

    1. Keep the function fast and idempotent

    Custom authentication extensions have a short response time budget (a few seconds) before Entra ID times out the call and proceeds without the extension's changes, so keep the Graph calls minimal, use a single application-permission-based Graph client that is reused across invocations rather than re-authenticating each time, and make sure your logic tolerates being called multiple times for the same user without erroring.

    If this answer helps you kindly accept the answer which will help others who have similar questions.

    Best Regards,

    Jerald Felix.

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.