Comments (13)
Yes that section is causing the issue.
I start with the user.read delegated permission with a status of granted and then run the scripts on this page sequentially, starting with List Azure AD Applications and then going to Update Azure AD Application Required Permission and concluding with Grant Delegated Permissions. I have used one or many additional permissions and they are all added correctly including mail.read and directory.real.all.
When I add a trap to the end of this search, the error is
{"error":{"code":"Request_MultipleObjectsWithSameKeyValue","message":"Permission entry already exists.
This makes me think that something about the permissions being added is causing it to think it should be an update and not a create event.
I decided to scramble the section order and ran the scripts in this order; List Azure AD Applications, Grant Delegated Permission, Update Azure AD Application Required Permission. I created a new app, which again only had user.read permission. I did NOT grant admin consent and ran a script that Defined the initial variables of the app and permissions as well as the script under the heading Get Microsoft Graph Service Principal object to retrieve permissions references from it. I then ran script above that was flagged as being a problem.
I got the same error message,
{"error":{"code":"Request_BadRequest","message":"Permission entry already exists
but when I refreshed the Azure UI, the lower section of API Permissions had a heading of Other Permissions Granted For.... and it was populated with those 6 permissions in my above script. So that was progress.
I then ran the permission scripts that were under Update Azure AD Application Required Permissions, ie the first 4 script blocks to assign perms. After a refresh of the UI, things were all good as illustrated in your visuals.
So to make a long story even longer, it looks like while you get a 409 error either way, running the Grant Delegated Permissions script blocks first then the others seem to get you to the desired end state. Not sure if this will vary in other testing but I was trying to solve this for a bit and wanted to see if I was missing something else here.
Hope this is helpful.
from simuland.
It didn't provide the check with Granted for... when the service principals where run when running the scripts from top to bottom on the page. This is the result...
from simuland.
Not a problem, just not sure how best to do it.
List Azure AD Applications
$headers = @{“Authorization” = “Bearer $MSGraphAccessToken”} $params = @{ “Method” = “Get” “Uri” = “https://graph.microsoft.com/v1.0/applications” “Headers” = $headers } $AzADApps = Invoke-RestMethod @params
Define initial variables
$ServicePrincipalId = $AzADAppSp.value[0].id $resourceSpDisplayName = ‘Microsoft Graph’ $PropertyType = 'oauth2PermissionScopes' $permissions = @(‘Mail.ReadWrite’)
Get Microsoft Graph Service Principal object
$headers = @{“Authorization” = “Bearer $MSGraphAccessToken”} $params = @{ "Method" = "Get" "Uri" = "https://graph.microsoft.com/v1.0/servicePrincipals?
$filter=displayName eq '$resourceSpDisplayName'"
"Headers" = $headers
}
$ResourceSvcPrincipal = Invoke-RestMethod @params
if ($ResourceSvcPrincipal.value.Count -ne 1) {
Write-Error "Found
}
`
Grant permissions with oauth2PermissionGrants API.
`$body = @{
clientId = $ServicePrincipalId
consentType = "AllPrincipals"
principalId = $null
resourceId = $ResourceSvcPrincipal.value[0].id
scope = "$permissions"
startTime = "$((get-date).ToString("yyyy-MM-ddTHH:mm:ss:ffZ"))"
expiryTime = "$((get-date).AddYears(1).ToString("yyyy-MM-ddTHH:mm:ss:ffZ"))"
}
$headers = @{
“Authorization” = “Bearer $MSGraphAccessToken”
"Content-Type" = "application/json"
}
$params = @{
"Method" = "Post"
"Uri" = “https://graph.microsoft.com/v1.0/oauth2PermissionGrants”
"Body" = $body | ConvertTo-Json –Compress
"Headers" = $headers
}
Invoke-RestMethod @params
`
Update Azure AD Application Required Permissions (OAuth2Permissions)
`$Application = $AzADApps.value[0]
$resourceSpDisplayName = ‘Microsoft Graph’
$PropertyType = 'oauth2PermissionScopes'
$ResourceAccessType = 'Scope'
$permissions = @(‘Mail.ReadWrite’)
#Get Microsoft Graph Service Principal object to retrieve permissions from it.
$headers = @{“Authorization” = “Bearer $MSGraphAccessToken”}
$params = @{
"Method" = "Get"
"Uri" = "https://graph.microsoft.com/v1.0/servicePrincipals?`$filter=displayName eq '$resourceSpDisplayName'"
"Headers" = $headers
}
$ResourceResults = Invoke-RestMethod @params
$ResourceSvcPrincipal = $ResourceResults.value[0]
if ($ResourceResults.value.Count -ne 1) {
Write-Error "Found
}
`
$ResourceAccessItems = @() Foreach ($AppPermission in $permissions) { $RoleAssignment = $ResourceSvcPrincipal.$PropertyType | Where-Object { $_.Value -eq $AppPermission } $ResourceAccessItem = [PSCustomObject]@{ "id" = $RoleAssignment.id "type" = $ResourceAccessType } $ResourceAccessItems += $ResourceAccessItem }
if ($resourceAccess = ($Application.requiredResourceAccess | Where-Object -FilterScript { $_.resourceAppId -eq $ResourceSvcPrincipal.appId })) { Foreach ($item in $ResourceAccessItems) { if ($null -eq ($resourceAccess.resourceAccess | Where-Object -FilterScript { $_.type -eq "$ResourceAccessType" -and $_.id -eq $item.id })) { $Application.requiredResourceAccess[$Application.requiredResourceAccess.resourceAppId.IndexOf($ResourceSvcPrincipal.appId)].resourceAccess += $item } } } else { $RequiredResourceAccess = [PSCustomObject]@{ "resourceAppId" = $ResourceSvcPrincipal.appId "resourceAccess" = $ResourceAccessItems } # Update/Assign application permissions $Application.requiredResourceAccess += $RequiredResourceAccess }
$AppBody = $Application | Select-Object -Property "id", "appId", "displayName", "identifierUris", "requiredResourceAccess" $headers = @{ “Authorization” = “Bearer $MSGraphAccessToken” "Content-Type" = "application/json" } $params = @{ "Method" = "Patch" "Uri" = "https://graph.microsoft.com/v1.0/applications/$($AppBody.id)" "Body" = $AppBody | ConvertTo-Json -Compress -Depth 99 "Headers" = $headers } $updatedApplication = Invoke-WebRequest @params -usebasicparsing if ($updatedApplication.StatusCode -eq 204) { return "Required permissions were assigned successfully" }
from simuland.
Hello @j-stoner ! Thank you very much for the feedback.
Regarding the 409 conflict. The idea is to first add the permissions but then grant it. mmm I wonder if the API to grant is also trying to add the permissions.
from simuland.
Can you share where exactly you get the error message please? Is it right at this part?
Grant permissions with oauth2PermissionGrants API.
$body = @{
clientId = $ServicePrincipalId
consentType = "AllPrincipals"
principalId = $null
resourceId = $ResourceSvcPrincipal.value[0].id
scope = "$permissions"
startTime = "$((get-date).ToString("yyyy-MM-ddTHH:mm:ss:ffZ"))"
expiryTime = "$((get-date).AddYears(1).ToString("yyyy-MM-ddTHH:mm:ss:ffZ"))"
}
$headers = @{
“Authorization” = “Bearer $MSGraphAccessToken”
"Content-Type" = "application/json"
}
$params = @{
"Method" = "Post"
"Uri" = “https://graph.microsoft.com/v1.0/oauth2PermissionGrants”
"Body" = $body | ConvertTo-Json –Compress
"Headers" = $headers
}
Invoke-RestMethod @params
from simuland.
I will do some tests today and improve this section too :)
from simuland.
I start with the user.read delegated permission with a status of granted and then run the scripts on this page sequentially, starting with List Azure AD Applications and then going to Update Azure AD Application Required Permission and concluding with Grant Delegated Permissions. I have used one or many additional permissions and they are all added correctly including mail.read and directory.real.all.
Does it mean that it worked the first time? You say that it worked with multiple permissions?
from simuland.
I then ran the permission scripts that were under Update Azure AD Application Required Permissions, ie the first 4 script blocks to assign perms. After a refresh of the UI, things were all good as illustrated in your visuals.
which script did you use? this one? https://github.com/Azure/SimuLand/blob/main/2_deploy/aadHybridIdentityADFS/scripts/Update-AzureADAppPermissions.ps1
from simuland.
So to make a long story even longer, it looks like while you get a 409 error either way, running the Grant Delegated Permissions script blocks first then the others seem to get you to the desired end state. Not sure if this will vary in other testing but I was trying to solve this for a bit and wanted to see if I was missing something else here
Would you mind sharing the scripts and code used to get it to work? Maybe if you are using sections from the docs and then the script, can you just point to the script lines in GitHub or sections in the docs? Please
from simuland.
Not a problem, just not sure how best to do it.
List Azure AD Applications
$headers = @{“Authorization” = “Bearer $MSGraphAccessToken”} $params = @{ “Method” = “Get” “Uri” = “https://graph.microsoft.com/v1.0/applications” “Headers” = $headers } $AzADApps = Invoke-RestMethod @params
Define initial variables
$ServicePrincipalId = $AzADAppSp.value[0].id $resourceSpDisplayName = ‘Microsoft Graph’ $PropertyType = 'oauth2PermissionScopes' $permissions = @(‘Mail.ReadWrite’)
Get Microsoft Graph Service Principal object
$headers = @{“Authorization” = “Bearer $MSGraphAccessToken”} $params = @{ "Method" = "Get" "Uri" = "https://graph.microsoft.com/v1.0/servicePrincipals?
$filter=displayName eq '$resourceSpDisplayName'"
"Headers" = $headers
}
$ResourceSvcPrincipal = Invoke-RestMethod @params
if ($ResourceSvcPrincipal.value.Count -ne 1) {
Write-Error "Found$($ResourceSvcPrincipal.value.Count) service principals with displayName '$ ($resourceSpDisplayName)'"
}
`Grant permissions with oauth2PermissionGrants API.
`$body = @{
clientId = $ServicePrincipalId
consentType = "AllPrincipals"
principalId = $null
resourceId = $ResourceSvcPrincipal.value[0].id
scope = "$permissions"
startTime = "$((get-date).ToString("yyyy-MM-ddTHH:mm:ss:ffZ"))"
expiryTime = "$((get-date).AddYears(1).ToString("yyyy-MM-ddTHH:mm:ss:ffZ"))"
}$headers = @{
“Authorization” = “Bearer $MSGraphAccessToken”
"Content-Type" = "application/json"
}
$params = @{
"Method" = "Post"
"Uri" = “https://graph.microsoft.com/v1.0/oauth2PermissionGrants”
"Body" = $body | ConvertTo-Json –Compress
"Headers" = $headers
}
Invoke-RestMethod @params
`Update Azure AD Application Required Permissions (OAuth2Permissions)
`$Application = $AzADApps.value[0]
$resourceSpDisplayName = ‘Microsoft Graph’
$PropertyType = 'oauth2PermissionScopes'
$ResourceAccessType = 'Scope'
$permissions = @(‘Mail.ReadWrite’)#Get Microsoft Graph Service Principal object to retrieve permissions from it.
$headers = @{“Authorization” = “Bearer $MSGraphAccessToken”}
$params = @{
"Method" = "Get"
"Uri" = "[https://graph.microsoft.com/v1.0/servicePrincipals?$filter=displayName](https://graph.microsoft.com/v1.0/servicePrincipals?%60$filter=displayName) eq '$resourceSpDisplayName'" "Headers" = $headers } $ResourceResults = Invoke-RestMethod @params $ResourceSvcPrincipal = $ResourceResults.value[0] if ($ResourceResults.value.Count -ne 1) { Write-Error "Found $($ResourceResults.value.Count) service principals with displayName '$($resourceSpDisplayName)'" }
$ResourceAccessItems = @() Foreach ($AppPermission in $permissions) { $RoleAssignment = $ResourceSvcPrincipal.$PropertyType | Where-Object { $_.Value -eq $AppPermission } $ResourceAccessItem = [PSCustomObject]@{ "id" = $RoleAssignment.id "type" = $ResourceAccessType } $ResourceAccessItems += $ResourceAccessItem }
if ($resourceAccess = ($Application.requiredResourceAccess | Where-Object -FilterScript { $_.resourceAppId -eq $ResourceSvcPrincipal.appId })) { Foreach ($item in $ResourceAccessItems) { if ($null -eq ($resourceAccess.resourceAccess | Where-Object -FilterScript { $_.type -eq "$ResourceAccessType" -and $_.id -eq $item.id })) { $Application.requiredResourceAccess[$Application.requiredResourceAccess.resourceAppId.IndexOf($ResourceSvcPrincipal.appId)].resourceAccess += $item } } } else { $RequiredResourceAccess = [PSCustomObject]@{ "resourceAppId" = $ResourceSvcPrincipal.appId "resourceAccess" = $ResourceAccessItems } # Update/Assign application permissions $Application.requiredResourceAccess += $RequiredResourceAccess }
$AppBody = $Application | Select-Object -Property "id", "appId", "displayName", "identifierUris", "requiredResourceAccess" $headers = @{ “Authorization” = “Bearer $MSGraphAccessToken” "Content-Type" = "application/json" } $params = @{ "Method" = "Patch" "Uri" = "https://graph.microsoft.com/v1.0/applications/$($AppBody.id)" "Body" = $AppBody | ConvertTo-Json -Compress -Depth 99 "Headers" = $headers } $updatedApplication = Invoke-WebRequest @params -usebasicparsing if ($updatedApplication.StatusCode -eq 204) { return "Required permissions were assigned successfully" }
Niceee!!! So all that code worked to get the Granted
check mark right? @j-stoner
from simuland.
Yeah, it was doing the service principal first then permissions that seemed to work...both threw 409 which is odd....
from simuland.
Ohh so even when getting it work, it stills returns a 409 response code .Interesting. I am testing it today.
from simuland.
Ok I figured it our after some testing. The issue that I had was the when I register an AD application for this lab, I was adding the User.Read
delegated permissions and granting admin consent to it. Somehow, the Grant API was not liking me to grant another permissions when there was already another one granted.
I updated the instructions that after deploying the Hybrid environment for the first lab, an Azure AD app needs to be registered and added a delegated permissions User.Read
, but it does not need to be granted admin consent.
After that, I ran through all the steps to update the application permissions and grant Mail.ReadWrite
permissions and it worked fine. Thank you very much for all the details. It was very helpful to figure it out :)
I appreciate you taking the time @j-stoner to open the issue and provide details. Thank you!
from simuland.
Related Issues (20)
- Template Validation Error - "Microsoft.Network/networksecuritygroups/nsg-rdp-allow" HOT 5
- Failed deployWinADFS Deployment HOT 2
- New AADInternals scripts running to avoid error HOT 2
- Issue Enabling Audit Log Search in O365 HOT 2
- Enforce TLS 1.2 Azure AD Connect HOT 1
- AAD diagnostic setting build failure HOT 2
- Error on enableOffice365AuditLogSearch.md HOT 1
- M365 Defender Connector - Missing Consent - Invalid License HOT 26
- CreateADForest Conflict Error HOT 6
- No authorization to deploy HOT 3
- Update Windows Events Data Collection to Data Collection Rules (DCR) and XPath Queries
- Cost Analysis Question HOT 1
- Invalid content link HOT 1
- Certificate thumbprint error in Install-ADFS HOT 3
- SetupADFS VM Extension Failing, SetupDC VM Extension failing with 403 Forbidden message
- incorrect uri to Import Identity Workbook HOT 1
- Issue on page /environments/aadHybridIdentityADFS/README.html HOT 3
- Exiting. Error Message: invalid uri https://STORAGE ACCOUNT.blob.core.windows.net/pfx_blob
- InvalidContentLink - https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Parsers/ASimFileEvent/ARM/vimFileEventMicrosoftSysmonCreated/vimFileEventMicrosoftSysmonCreated.json
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from simuland.