AzureAD - ConditionalAccessPolicy PersistentBrowser error - azure

I have the following script to create a Conditional Access policy but i get below error.
And i dont understand what is wrong
$conditions = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessConditionSet
$conditions.Applications = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessApplicationCondition
$conditions.Applications.IncludeApplications = "Office365"
$conditions.Users = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessUserCondition
$conditions.Users.IncludeRoles = #('62e90394-69f5-4237-9190-012177145e10', 'f28a1f50-f6e7-4571-818b-6a12f2af6b6c', '29232cdf-9323-42fd-ade2-1d097af3e4de', 'b1be1c3e-b65d-4f19-8427-f6fa0d97feb9', '194ae4cb-b126-40b2-bd5b-6091b380977d', '729827e3-9c14-49f7-bb1b-9608f156bbb8', '966707d0-3269-4727-9be2-8c3a10f19b9d', 'b0f54661-2d74-4c50-afa3-1ec803f12efe', 'fe930be7-5e62-47db-91af-98c3a49a38b1')
$conditions.Users.ExcludeGroups = $ExcludeCAGroup.ObjectId
$conditions.ClientAppTypes = #('Browser', 'MobileAppsAndDesktopClients')
$controls = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessGrantControls
$controls._Operator = "OR"
$controls.BuiltInControls = "MFA"
$session = New-Object -TypeName Microsoft.Open.MSGraph.Model.conditionalAccessSessionControls
$sessioncontrols = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessSignInFrequency
$sessioncontrols.Type = "days"
$sessioncontrols.Value = 30
$sessioncontrols.IsEnabled = $true
$session.SignInFrequency = $sessioncontrols
$persistent = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessPersistentBrowser
$persistent.IsEnabled = $true
$persistent.Mode = "never"
$session.PersistentBrowser = $persistent
New-AzureADMSConditionalAccessPolicy -DisplayName "GRANT: Require MFA for Admin users and never persistent sessions" -State "Disabled" -Conditions $conditions -GrantControls $controls -SessionControls $session
The error i get is
New-AzureADMSConditionalAccessPolicy : Error occurred while executing NewAzureADMSConditionalAccessPolicy
Code: BadRequest
Message: 1032: ConditionalActionPolicy validation failed due to InvalidConditionsForPersistentBrowserSessionMode.
anyone have any ideas?

I have tried in my environment and got the same error like below:
If you are including persistent browser mode in your script, then make sure to select All applications for session control as mentioned in this MsDoc.
By Changing the IncludeApplications from office365 to All like below:
$conditions.Applications.IncludeApplications = "All"
I was able to create conditional access policy successfully :
I also tried keeping included app as office365,but changed $persistent.IsEnabled=$false .This worked maybe because it can only be enabled for all apps as suggested in the MsDoc.

Related

Create more than one delegated permission in Azure application with PowerShell?

I am creating a script to create a new app registration within Azure.
So far, all is working well, I can create the app, create the service principal, set a secret and add a redirect uri.
The issue I face is that I can create a delegation permission for the application using the below function:
$graph = "00000003-0000-0000-c000-000000000000"
$sharePoint = "00000003-0000-0ff1-ce00-000000000000"
$userRead = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"
$myFilesWrite = "2cfdc887-d7b4-4798-9b33-3d98d6b95dd2"
$allSitesWrite = "640ddd16-e5b7-4d71-9690-3f4022699ee7"
Function SetPermissions($resourceId, $argument)
{
$rra = New-Object -TypeName "Microsoft.Open.AzureAD.Model.RequiredResourceAccess"
$rra.ResourceAppId = $resourceId
$rra.ResourceAccess = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList $argument ,"Scope"
Set-AzureADApplication -ObjectId $myApp.ObjectId -RequiredResourceAccess $rra
}
SetPermissions $graph $userRead
but I will need three permissions for my app - when I call the function a second time it just overwrites the existing permission rather than adding a new one.
Any advice on how I can create multiple app permissions?
I tried to reproduce the same in my environment and got below results.
When I ran the same code as you, User.Read permission is added to the application like below:
Now I changed the arguments and ran the code again as below:
$myApp = Get-AzureADApplication -SearchString MyApp
$graph = "00000003-0000-0000-c000-000000000000"
$sharePoint = "00000003-0000-0ff1-ce00-000000000000"
$userRead = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"
$myFilesWrite = "2cfdc887-d7b4-4798-9b33-3d98d6b95dd2"
$allSitesWrite = "640ddd16-e5b7-4d71-9690-3f4022699ee7"
Function SetPermissions($resourceId, $argument)
{
$rra = New-Object -TypeName "Microsoft.Open.AzureAD.Model.RequiredResourceAccess"
$rra.ResourceAppId = $resourceId
$rra.ResourceAccess = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList $argument ,"Scope"
Set-AzureADApplication -ObjectId $myApp.ObjectId -RequiredResourceAccess $rra
}
SetPermissions $sharePoint $allSitesWrite //Changed this
Response:
When I checked the same in Portal, existing permission removed, and new permission added like below:
To add multiple delegated permissions to Azure AD application from PowerShell, you can make use of below script:
$Graph = New-Object -TypeName "Microsoft.Open.AzureAD.Model.RequiredResourceAccess"
$Graph.ResourceAppId = "00000003-0000-0000-c000-000000000000"
$SharePoint = New-Object -TypeName "Microsoft.Open.AzureAD.Model.RequiredResourceAccess"
$SharePoint.ResourceAppId = "00000003-0000-0ff1-ce00-000000000000"
$userRead = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "e1fe6dd8-ba31-4d61-89e7-88639da4683d","Scope"
$myFilesWrite = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "2cfdc887-d7b4-4798-9b33-3d98d6b95dd2","Scope"
$allSitesWrite = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "640ddd16-e5b7-4d71-9690-3f4022699ee7","Scope"
$Graph.ResourceAccess = $userRead
$SharePoint.ResourceAccess = $myFilesWrite, $allSitesWrite
$myApp = Get-AzureADApplication -SearchString MyApp
Set-AzureADApplication -ObjectId $myApp.ObjectId -RequiredResourceAccess $Graph, $SharePoint
Response:
When I checked the same in Portal, multiple delegated permissions added to the application successfully like below:
Reference:
How to assign Permissions to Azure AD App by using PowerShell by rajaniesh

Get-PnPTenantSite : Attempted to perform an unauthorized operation

Currently we get an access token and then pass this token to PowerShell script to loop across all ODFB personal sites.
$url = "https://XXXXX-admin.sharepoint.com"
$conn = Connect-PnPOnline -Url $url -AccessToken $access_token -ReturnConnection
$sitecollections = Get-PnPTenantSite -IncludeOneDriveSites:$true -Filter "Url -like '-my.sharepoint.com/personal/'" -Connection $conn | Select-Object -ExpandProperty Url
foreach ($site in $sitecollections)
{
....
}
It worked successfully for years until it was broken a while ago.
I tried different versions of PnP PowerShell:
PnP version
Error
SharePointPnPPowerShellOnline 3.21.2005.2 (currently used)
Get-PnPTenantSite : Attempted to perform an unauthorized operation.
SharePointPnPPowerShellOnline 3.29.2101.0
Get-PnPTenantSite : The current connection holds no SharePoint context.
PnP.PowerShell 1.10.28
Get-PnPTenantSite : Attempted to perform an unauthorized operation.
If I change script to use an user/password instead the access token, the script works without problems:
$url = "https://XXXXX-admin.sharepoint.com"
$User = "admin#mydomain.com"
$PWord = ConvertTo-SecureString -String "Password" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord
$conn = Connect-PnPOnline -Url $url -Credentials $Credential -ReturnConnection
$sitecollections = Get-PnPTenantSite -IncludeOneDriveSites:$true -Filter "Url -like '-my.sharepoint.com/personal/'" -Connection $conn | Select-Object -ExpandProperty Url
foreach ($site in $sitecollections)
{
....
}
So the error happens when the script connects to SP Online using an access token.
Perhaps the some things were changed. But what exactly? Have some scope to be added when an access token is requested?
Or have some new permissions to be added for the application in Azure AD?
Update:
Modified the script (added Write-Output "Connection is:" $conn | fl) to provide more details about connection and got the difference in ConnectionType property when SharePointPnPPowerShellOnline 3.21.2005.2 is used:
When an access token is used (and the script doesn't work properly), ConnectionType : O365
When an access token is used (and the script works fine), ConnectionType : TenantAdmin

Adding Sharepoint user remotely PowerShell script

Running EnsureUser on an existing domain account give an error that the user could not be found. Same command(s) works fine in PowerShell on SharePoint server locally. I am able to create a SharePoint group remotely, just can't add a user to that group.
$site = new-object Microsoft.SharePoint.SPSite("http://sharepoint.company.com/dev")
$web = $site.OpenWeb()
function GrantUserpermission($userName)
{
$folder.BreakRoleInheritance("true")
$web.SiteGroups.Add("test_group", $web.Site.Owner, $web.Site.Owner, "Desc")
$ownerGroup = $web.SiteGroups["test_group"]
$ownerGroup.AllowMembersEditMembership = $true
$ownerGroup.Update()
$sitename = Get-SPWeb http://sharepoint.company.com/dev
$EnsuredUser = $sitename.EnsureUser("domain\user")
Set-SPUser -Identity $EnsuredUser -web $sitename -group "test_group"
$AddGroup = $web.SiteGroups["test_group"]
$roleAssignment = new-object Microsoft.sharepoint.SPRoleAssignment($AddGroup)
$roleDefinition = $web.RoleDefinitions["Contribute"]
$roleAssignment.RoleDefinitionBindings.add($roleDefinition)
$folder.RoleAssignments.Add($roleAssignment)
$folder.SystemUpdate()
Check if the domain user exists before use the EnsureUser method.
If you want to add SharePoint user to group in remote server, we can use CSOM with PowerShell to achieve it.
$url="http://sharepoint.company.com/dev"
$userName="administrator"
$password="**"
$domain="test"
$sGroup="test_group"
$sUserToAdd="domain\user"
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($url)
$credentials = New-Object System.Net.NetworkCredential($userName,$password,$domain)
$ctx.Credentials = $credentials
$groups=$ctx.Web.SiteGroups
$ctx.Load($groups)
#Getting the specific SharePoint Group where we want to add the user
$group=$groups.GetByName($sGroup)
$ctx.Load($group)
#Ensuring the user we want to add exists
$user = $ctx.Web.EnsureUser($sUserToAdd)
$ctx.Load($user)
$userToAdd=$group.Users.AddUser($user)
$ctx.Load($userToAdd)
$ctx.ExecuteQuery()

AcquireTokenAsyn in Azure cloud shell

I'm trying to make some graph API calls from AZure CloudShell. To make the API call I have to acquire a token. I have a 100% working code in Azure Desktop version (PSVersion 5.1)
But same code not working in CloudShell, which runs s with (Core - 6.2)
Cloudshell libraries have couple of mismatches with documentations
Im trying to use this version of AcuireTokenAsync.
For which I have to initial PlatmforParameter
but when Im getting an error
$platformParameters = New-Object
"Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters"
"Auto" New-Object : Cannot find an overload for "PlatformParameters"
and the argument count: "1". At line:1 char:23
+ ... arameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirecto ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
Seems PlatformParameters accepting no arg constructor
This is my working code in Powershell Desktop 5.1 version
$clientId = "1950a258-227b-4e31-a9cf-717495945fc2" # well-known client ID for AzurePowerShell
$redirectUri = "urn:ietf:wg:oauth:2.0:oob" # redirect URI for Azure PowerShell
$resourceAppIdURI = "https://graph.windows.net"
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
$platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList 'Auto'
$authResultTask = $authContext.AcquireTokenAsync($resourceAppIdURI, $clientId, $redirectUri, $platformParameters)
$authResultTask.Wait()
$authResult = $authResultTask.Result
But same code doesn't work in CloudShell
Is there any well known variation of acquiring token from Azure Cloud shell
I wanted to automate the application creation and configuration via powershell script
As mentioned in the comment, no need to call the MS Graph APIs manually, you can automate them via AzureAD powershell module, which is also available in the cloud shell.
Samples:
1.Create application - New-AzureADApplication
New-AzureADApplication -DisplayName "My new application" -IdentifierUris "http://mynewapp.contoso.com"
2.Update an application - Set-AzureADApplication
For example, set the API permissions for the application.
$req = New-Object -TypeName "Microsoft.Open.AzureAD.Model.RequiredResourceAccess"
$acc1 = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "311a71cc-e848-46a1-bdf8-97ff7156d8e6","Scope"
$acc2 = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "aaff0dfd-0295-48b6-a5cc-9f465bc87928","Role"
$req.ResourceAccess = $acc1,$acc2
$req.ResourceAppId = "00000002-0000-0000-c000-000000000000"
$reqe = New-Object -TypeName "Microsoft.Open.AzureAD.Model.RequiredResourceAccess"
$acc1e = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "ddb3ca45-a192-477d-acb2-46bf9dc586de","Scope"
$acc2e = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "28379fa9-8596-4fd9-869e-cb60a93b5d84","Role"
$reqe.ResourceAccess = $acc1e,$acc2e
$reqe.ResourceAppId = "00000009-0000-0000-c000-000000000000"
Set-AzureADApplication -ObjectId <ObjectId> -RequiredResourceAccess #($req,$reqe)
I test the script in local and cloud shell, both work fine. If you have other requirements, just look into the Azure AD PowerShell doc, you can do most things related to AAD via this module.
For more details about the sample, you could refer to the two links, 1 and 2.

Make Azure Authentication Run Silently without Password Prompt

I have a PowerShell script that connects to Azure, then downloads data. The script runs great with human interaction, but I'm trying to run it silently as a scheduled task. Currently, every time the script runs, it prompts for user credentials. I change 'Always' to 'Never' and it doesn't seem to store the credentials for any length of time.
$clientId = "<CLIENTIDHERE>" # PowerShell clientId
$redirectUri = "<REDIRECTURIHERE>"
$MSGraphURI = "https://graph.microsoft.com"
$authority = "https://login.microsoftonline.com/$tenantId"
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
$authResult = $authContext.AcquireToken($MSGraphURI, $clientId, $redirectUri, "Always")
$token = $authResult.AccessToken
Ideally the credentials would be passed through based on the credentials running in the scheduled task. If that isn't an option, at least I'm hoping to put the username and password in the script and have the script send those credentials to authenticate. How does one authenticate silently to Azure?
You could check the script shared by Bogdan Gavril from this thread .
#Require -Version 5.0
using namespace Microsoft.IdentityModel.Clients.ActiveDirectory
$adalDll = [Reflection.Assembly]::LoadFile("<path_to>\Microsoft.IdentityModel.Clients.ActiveDirectory.dll")
$ADAuthorityURL = "https://login.windows.net/common/oauth2/authorize/"
$resourceURL = "https://analysis.windows.net/powerbi/api"
$AADuserName = "foo"
$AADpassword = "bar"
Write-Host "Retrieving the AAD Credentials...";
$credential = New-Object UserPasswordCredential($AADuserName, $AADpassword);
$authenticationContext = New-Object AuthenticationContext($ADAuthorityURL);
$authenticationResult = [AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync($authenticationContext, $resourceURL, $AADClientID, $credential).Result;
$ResultAAD = $authenticationResult.AccessToken;
I was able to figure this out. The initial authentication code I presented used an Azure-specific pop-up window to grab your credentials. Using the following link [1] I converted the code to the PowerShell Get-Credential method instead. From there, I used the information in this link [2] (Example 7) to configure the Get-Credential method to pull from plain text instead of a pop-up Window.
Now plain text passwords isn't ideal, but for our needs, it was good enough.
$clientId = "<CLIENTIDHERE>" # PowerShell clientId
$redirectUri = "REDIRECTURIHERE"
$MSGraphURI = "https://graph.microsoft.com"
$authority = "https://login.microsoftonline.com/$tenantId"
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
$User = "<USERNAMEHERE>"
$PWord = ConvertTo-SecureString -String "<PASSWORDHERE>" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord
$AADCredential = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential" -ArgumentList $credential.UserName,$credential.Password
$authResult = $authContext.AcquireToken($MSGraphURI, $clientId, $AADCredential)
$token = $authResult.AccessToken
[1] https://blogs.technet.microsoft.com/cloudlojik/2017/09/05/using-powershell-to-connect-to-microsoft-graph-api/
[2] https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.security/get-credential?view=powershell-6

Resources