How to check if a user is in an AD group via Azure AD? - azure-active-directory

Setup Specifications
.NET 4.5.1 MVC Project
Project contains .aspx files (legacy)
Currently user Azure AD for authentication via Cookies.
Azure portal configured (via App Registrations) with "Implicit Grant - ID Tokens" and "Accounts in this organizational directory only"
On-Premise AD groups are pushed up to Azure AD.
Startup.cs Configuration
// COOKIES: Tells it to use cookies for authentication.
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
CookieManager = new SystemWebCookieManager()
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions()
{
ClientId = ClientID,
Authority = Authority,
PostLogoutRedirectUri = PostLogoutRedirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications()
{
AuthenticationFailed = PrincipalService.OnAzureAuthenticationFailure,
AuthorizationCodeReceived = (AuthorizationCodeReceivedNotification notification) =>
{
var username = notification.AuthenticationTicket.Identity.Name.Split('#').LastOrDefault();
var emailAddress = notification.AuthenticationTicket.Identity.Claims.FirstOrDefault(x => x.Type.Contains("emailaddress"))?.Value;
Logger.Log(Level.Auth, $"Azure login success! Username: '{username}' Email: '{emailAddress}'.");
return Task.FromResult(0);
}
}
});
Question
How can I, given this setup, check if the currently logged in user is in a particular AD Group?
What I've tried
All the guides on doing Microsoft Graph API always come up with a problem that I don't know how to get past (e.g. GetAccountsAsync returning empty, etc).
I added the following to our app registration manifest:
"optionalClaims": {
"idToken": [
{
"name": "email",
"source": null,
"essential": true,
"additionalProperties": []
},
{
"name": "groups",
"source": null,
"essential": true,
"additionalProperties": []
}
],
"accessToken": [],
"saml2Token": []
}
email works fine, but obviously groups doesn't as it was a shot in the dark.

1. Getting Group Membership Claims as part of Token
You can enable group claims to come in as part of the access token for your application by editing your application's manifest (this can be done directly in Azure Portal) and setting "groupMembershipClaims" property to "All" or "SecurityGroup" as needed.
2. Group Ids are returned as part of Claims
Once application manifest is updated as mentioned above, you can get Group Id's as part of claims. Here's a quick sample for a decoded JWT token
3. Limit on the number of groups that can be returned as part of token
To ensure that the token size doesn't exceed HTTP header size limits, Azure AD limits the number of objectIds that it includes in the groups claim. If a user is member of more groups than the overage limit (150 for SAML tokens, 200 for JWT tokens), then Azure AD does not emit the groups claim in the token. Instead, it includes an overage claim in the token that indicates to the application to query the Graph API to retrieve the user's group membership.
4. Relevant Microsoft Graph APIs
NOTE: Working with Microsoft Graph APIs can be pretty powerful, since you can get around overage scenarios as well as get all other kinds of information about groups if needed (like name). In this particular case, since intent is to validate group membership, group Id is the best field as it will not change while others like name can.
Check member groups
This one will be helpful if you already know the groups that you want to check/validate membership in.
POST https://graph.microsoft.com/v1.0/users/{id | userPrincipalName}/checkMemberGroups
In request body, you can provide groupdIds, i.e. a collection that contains the object IDs of the groups in which to check membership. Up to 20 groups may be specified.
{
"groupIds": [
"fee2c45b-915a-4a64b130f4eb9e75525e",
"4fe90ae065a-478b9400e0a0e1cbd540"
]
}
user: getMemberGroups
This one will be helpful if you don't already know the group and want to get all the groups that this user belongs to.
POST https://graph.microsoft.com/v1.0/users/{id | userPrincipalName}/getMemberGroups
Here is another related SO Post

Related

Azure AD Directory Extensions claims missing

I have added about 18 extension claims to my access token. Based on the application state you may get different claims from this list. I'm sure that those claims have some values assigned. But for some reason, I'm not receiving all of them as part of my JWT Access token. I can get these values using graph API.
Example of extension claim from jwt token:
"extn.***_**_CreatedDate": [
"30/09/2022 12:21:01 PM +00:00"]
Example of application manifest token configuration:
"optionalClaims": {
"idToken": [
{
"name": "extension_someguid_***_***_CreatedDate",
"source": "user",
"essential": false,
"additionalProperties": []
}]
}
Are there any limits on clams/extension claims count added to AAD access token?
If application sends the claims with data in the form of extension attribute registered on a different application, a claims mapping policy must be used to map the extension attribute to the claim.
New-AzureADPolicy -Definition #('{
"ClaimsMappingPolicy":
{"Version":1,
"IncludeBasicClaimSet":"true",
"ClaimsSchema": [
{
"Source":"user",
"ID":"employeeid",
"SamlClaimType":"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/employeeid","JwtClaimType":"employeeid"
},
{
"Source":"company",
"ID":"tenantcountry",
"SamlClaimType":"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country",
"JwtClaimType":"country"}]}}')
-DisplayName "ExtraClaimsExample"
-Type "ClaimsMappingPolicy"
accesstokenAcceptedVersion must be set to supported value 1, 2, or null , depends on the issuer enpoint obtained from the token.
"acceptMappedClaims" must be set to true, for single tenant app.
Also do make sure to give claims under accessToken in manifest .
Note:
If want to have the claims in the access token then you may need to modify the manifest of the resource app. i.e.; If you have an web App
that calls Web API B and you want the claims in the access_token then
you need to modify the manifest of web api B.
Only extension attributes on user objects can be used for emitting claims to applications.
When adding claims to the access token, the
claims emitted are for a web API and not requested by the
application. So you will be able to see only claims emitted are for
access tokens requested for the application webApi.
Reference: Use Azure AD directory extension attributes in claims - Microsoft Entra | Microsoft Learn

SharePoint Access token has two different scope values for tenants

when I decode SharePoint access token for Tenant A and B it shows as below
for the tenant A
"scp": "AllSites.FullControl User.Read User.ReadBasic.All"
for the tenant B
"scp": ".1f7f4061-caa1-44c4-b29a-6d877e9a5211"
are there any possible reasons to this kind of result for different tenants where i am expecting Teanat A result.
my token request call is similar to this
{ "grant_type", "authorization_code" },
{ "client_id", azureConfig.ClientId },
{ "client_secret", azureConfig.ClientSecret },
{ "scope", "https://123435350365.sharepoint.com/.default"},
{ "redirect_uri","url" },
{ "code", code }
I tried to reproduce the same in my environment and got the scopes successfully in both tenants.
I used the below parameters for both the tenants and got the access token for SharePoint successfully:
After decoding the token, I got the scope for both tenants successfully like below:
Please check the scope you are giving for Tenant B and verify whether your tenant has access to SharePoint API or not.
After decoding the token for Tenant B please check the aud and iss claims are valid or not.
Please note that value for the SharePoint Online Tenant Id may vary for each Tenant.
Make sure if you are giving permissions for Microsoft Graph then change the scope to https://graph.microsoft.com/.default.
If still the issue persists, try to raise Azure Support Ticket.
You can refer the below links to get some pointer to resolve the issue:
azure - SharePoint online OAuth2 token invalid_scope - Stack Overflow
How to access SharePoint Online data using Postman - REST API and Bearer token

Azure Active Directory B2C: How to query MS Graph to get a user's alternative security ID?

B2C uses an alternative security ID to uniquely identify users from social accounts. We have a problem where a user enters credentials for a user, but somehow B2C authenticates the user as someone else. I suspect the IDP is returning bad claims data or the alternative security IDs are the same. How do I view the alternative security ID of a user in Active Directory?
I tried the following MS Graph query trying all the attributes I can think of (including the ones listed in this article), but graph doesn't return data for these attributes.
https://graph.microsoft.com/v1.0/users/<userId>?$select=id,alternativeSecurityId,alternativeSecurityIds,extension_<b2cExtensionAppId>_alternativeSecurityId,extension_<b2cExtensionAppId>_alternativeSecurityIds
Thanks in advance!
AlternativeSecurityId for a B2C user is found in the Identities collection via MS Graph API.
The AlternativeSecurityId claim used in the B2C policy maps to the Identities: issuerAssignedId value for the corresponding issuer.
Eg, for issuerAssignedId: 123 (id from google token) from issuer: google.com
"identities": [
{
"signInType": "federated",
"issuer": "google.com",
"issuerAssignedId": "123"
}
],
You can return the identities collection by calling the /users endpoint of MS Graph API. https://learn.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0&tabs=http

Active Directory not returning groups for all users

I've built a node.js app with express and the passport-azure-ad library in order to authenticate users via AAD. I want to get groups back in the auth callback for users that are logging in so I can ensure they belong to the correct security group before granting them access to parts of my app.
I edited my manifest for my Active Directory App (Clarity) to include
"groupMembershipClaims": "All"
This is working very well for all users that I have had log in except for one. Typically I get a response in the profile object of this form:
accessToken: "scrubbedAccessToken"
aio: "scrubbedAio"
amr: "["pwd"]"
family_name: "My Last Name"
given_name: "My First Name"
groups: Array[1]
0: "[...hugeListofGuids...]"
length: 1
in_corp: "true"
ipaddr: "my ip"
name: "My Name"
oid: "scrubbedOid"
onprem_sid: "scrubbedSid"
sub: "scrubbedSub"
tid: "scrubbedTid"
unique_name: "myemail#microsoft.com"
upn: "myemail#microsoft.com"
ver: "1.0"
But for some reason for one of my users my app gets this instead:
_claim_names: "{"groups":"src1"}"
_claim_sources: "{"src1":{"endpoint":"https://graph.windows.net/scrubbedTid/users/scrubbedOid/getMemberObjects"}}"
accessToken: "scrubbedAccessToken"
aio: "scrubbedAio"
amr: "["pwd"]"
family_name: "scrubbedLastName"
given_name: "scrubbedFirstName"
in_corp: "true"
ipaddr: "scrubbedIp"
name: "scrubbedFulleName"
oid: "scrubbedOid"
onprem_sid: "scrubbedSid"
sub: "scrubbedSub"
tid: "scrubbedTid"
unique_name: "scrubbedEmail"
upn: "scrubbedEmail"
ver: "1.0"
Can anyone give me some insight as to why I'd get different formats for different users? These users are both in the same tenant and their emails are in the same domain.
The number of Group Membership Claims that are returned in the Access Token are limited based on the token type.
Take a look at this blog post: Azure Active Directory, now with Group Claims and Application Roles!
To ensure that the token size doesn’t exceed HTTP header size limits,
Azure AD limits the number of objectIds that it includes in the groups
claim. If a user is member of more groups than the overage limit (150
for SAML tokens, 200 for JWT tokens), then Azure AD does not emit the
groups claim in the token. Instead, it includes an overage claim in
the token that indicates to the application to query the Graph API to
retrieve the user’s group membership.
You are noticing a behavior which implies that this user is a member of too many groups, and you will need to call the AAD Graph API to get those details.

How to get Azure tenant name from graph.microsoft.com?

I need to discover user's tenant name, since the service endpoint, resourceId that I'll be using an Azure service that requires me to specify the tenant name:
service endpoint: https://[tenantnamme].api.crm.dynamics.com/...
resource Id: https://[tenantname].crm.dynamics.com
I was hoping Unified Microsoft Graph API can discover this for me. I looked at the documentation, the closest I can see is to use
graph.microsoft.com/v1.0/organization
which will give me back:
verifiedDomains : [
....
"name" : "contoso.onmicrosoft.com"
]
But, I'm not sure if this is the right approach. What if an org has multiple verified domains? Does verified domain name is the same as tenant name?
Update: This is my real scenario. I have a web app that allows user to authenticate to Azure AD via OAuth2. I have no problem obtaining refresh token and access token from OAuth interactions. However, in other to use other service, it requires [azure-ad-tenant-name] in their service end point. That's my question coming from.
I believe that you're on the right track with the graph.microsoft.com/v1.0/organization endpoint. You should be able to find the tenant name in the verifiedDomains list. The entry that should contain domain with the tenant name is the initial domain:
{
...
"isInitial": true,
"name": "contoso.onmicrosoft.com",
...
}
Same. When you create a AD, you will obtain a domain name and a tenant id without tenant name, they are both the unique identifier of a AD. Use Get-AzureRmTenant to get all tenantid and domains in your subscription.

Resources