access sharepoint REST api using powershell with windows authentication - powershell

I have a sharepoint 2013 server, which I can log into using Windows Authentication via a web-browser. When I have logged on using my browser, if I then - using that same browser - browse to http://mysharepointserver/_api/web I get some useful XML.
However, I want to write a powershell script that uses this XML. To that end, following the suggestions from this page:
How to make an authenticated web request in Powershell?
I wrote the following code:
$PWord = ConvertTo-SecureString –String "MyAwesomePassword" –AsPlainText -Force
$creds = New-Object System.Net.NetworkCredential("MyUserName",$PWord,"TheDomain")
$webclient = New-Object System.Net.WebClient
$webclient.Credentials = $creds
$url = "http://mysharepointserver/_api/web"
$output = $webclient.DownloadString($url)
echo $output
However, when I run this code, I get the error message:
Exception calling "DownloadString" with "1" argument(s): "The remote server returned an error: (403) Forbidden."
Even though I can access the same URL using a web-browser, if I type in the (same) credentials using the Windows login dialog that pops up for authentication purposes.
Does anyone know if it is possible to do this using Powershell?
thanks heaps all

Why aren't you using the default CMDlets that come with Powershell (unless using PS2 or lower)?
Invoke-Webrequest and Invoke-Restmethod both support the -credential switch which can be used to authenticate against the webserver.
You can also use Get-credential to store your credentials (though you can't get yhem from a file or string that way, at least not the password)
Script (in pseudo code and since i'm on my phone no code tags) would look like this :
Invoke-Restmethod -uri 'http://bla/api' -credential (get-credential)

Related

Authentication error when using SharePoint Migration Tool PowerShell cmdlets

Server 2012 R2 file share to SharePoint Online migration
I am attempting to automate scheduling some file share synchronization to SharePoint Online using the migration tool, however I get an error that my credentials are incorrect.
The same credentials work using the GUI version of the SPMT so I know they are correct, and these credentials are for the global administrator of 365 so there should absolutely be no permissions issues.
The error that I receive:
Task 7967a651-6a2a-47ed-afcd-6b1567496e7d did NOT pass the parameter validation, the error message is 'Username or password for target site https://tenant.sharepoint.com/sites/FileShareSite is not correct' Migration finished, but some tasks failed! You can find the report and log at X:\log.log
The code I am using:
Import-Module Microsoft.SharePoint.MigrationTool.PowerShell
$SPOUrl = "https://tenant.sharepoint.com/sites/FileShareSite"
$Username = "admin#tenant.onmicrosoft.com"
$Password = ConvertTo-SecureString -String "PasSWorD" -AsPlainText -Force
$SPOCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username, $Password
Register-SPMTMigration -SPOCredential $SPOCredential -Force -MigrateWithoutRootFolder -PreserveUserPermissionsForFileShare $true -WorkingFolder "X:\log"
Add-SPMTTask -FileShareSource "\\file-server\shares\ShareOne" -TargetSiteUrl $SPOUrl -TargetList "ShareOne" -TargetListRelativePath "/"
Start-SPMTMigration -NoShow
According to the logs, I am seeing 400 response codes, as well as some 'An existing connection was forcibly closed by the remote host.'
Something so simple so I don't know what the problem could be; OS is supported, credentials are correct, URL is correct, all these settings work in the GUI version of the tool.
In the logs I see references to logging into AAD, we do not have AAD on this tenant, I am a little curious to know if that is just semantics or if that is part of the problem. I would have assumed the GUI and the PowerShell module use the same mechanisms behind the scenes. Error happened in AAD login MSAL.Desktop.4.37.0.0.MsalServiceException: ErrorCode: user_realm_discovery_failed Microsoft.Identity.Client.MsalServiceException: Response status code does not indicate success: 400 (BadRequest).
So I figured it out, the issue turned out to be PowerShell using an outdated SSL/TLS cipher. I forced TLS1.2 on the PowerShell session using [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 and it is now working as expected.

Selenium (Powershell) Run as a different user

I want to start Selenium (Google Chrome - WebDriver) as a different user and I am pretty much lost as I don't know where to add $mycreds. This is quite easy to achieve if I want to start a normal Chrome session, however, I am stuck when it comes to achieving this using Selenium. Any advice ?
$username = "domain\name"
$password = ConvertTo-SecureString "password" -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $password
$Driver = Start-SeChrome
Enter-SeUrl -Url 'https://www.google.com/' -Driver $Driver
If I try to pass it along using -Arguments , it will still use my account to open the browser without returning any error.
$Driver = Start-SeChrome -Arguments $mycreds
The easy way to do this is by starting Powershell as-another-user instead. Make sure you have the module set up for that user as well as any other environment stuff you might need.
The selenium-powershell module itself does not support starting the selenium drivers as a different user from the current one.
You may also want to make sure you're using an updated version of the module as well, since (in pre-release):
Start-SeChrome and other have been removed in favor of Start-SeDriver -Browser Chrome (#100)

Execute an App registration without AzureAD

For a professional project, a chunk of the pipeline must be able to create an application (the first App registration, so I only have a global Admin) automatically within Azure AD. So far I used AzureAD which works well with Powershell 5.6 on Windows.
I now must be able to run the code with Ubuntu 20.04 and its Powershell 7.2. Unfortunately for me, AzureAD module is only supported on non-core Windows PowerShell, therefore it does not work on core PS6 or PS7. A very simplified piece of code is the following:
# Connection infos
$tenantId = "abcdef12345-1234-1234-124-abcdef12346789"
$account = "my_admin#domain.com" # Is cloud Admin by default
$password = ConvertTo-SecureString "MyPassword" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential -ArgumentList ($account, $password)
Connect-AzureAD -Credential $psCred -Tenant $tenantId
# Create app
$appName = "MyApp"
New-App -appName $appName -tenant_id $tenantId
I am stuck and my question is the following: how could I run such an operation with Powershell 7.2 considering AzureAD is not usable? I did check Connect-MgGraph for the connection part only (https://github.com/microsoftgraph/msgraph-sdk-powershell) but the clientId is an infos that I don't have -and want to create-.
Thanks in advance
You can use DeviceLogin as explained in this article to obtain an oAuth access token for you Global Administrator account in PowerShell (independent of the version) but this first step needs a human interaction.
After obtaining the token, you can use it to make Graph API calls with your Global Administrator permissions to create an application.
Once you create your first application, you must attribute required permissions and use it to automate the process (obtain token programmatically using API calls) for application creation in PowerShell.
You could use Resource Owner Password Credentials (ROPC) to authenticate, however Microsoft actively discourages it in their documentation due to the security implications of sending a password over the wire.
If the security issues present with this method of authentication are still tolerated within your acceptance criteria, you would still need a ClientID. Luckily, AzureAD has a well-known ClientID that you can use to authenticate. This ID is 1950a258-227b-4e31-a9cf-717495945fc2
The below Powershell code should get you started. I've basically translated the HTTP request within Microsoft's documentation into a splatted Invoke-RestMethod command.
$LoginWithROPCParameters = #{
URI = "https://login.microsoftonline.com/contoso.onmicrosoft.com/oauth2/v2.0/token"
Method = "POST"
Body = #{
client_id = "1950a258-227b-4e31-a9cf-717495945fc2"
scope = "user.read openid profile offline_access"
username = "username#contoso.onmicrosoft.com"
password = "hunter2"
grant_type = "password"
}
}
Invoke-RestMethod #LoginWithROPCParameters

Deleting Gmail Emails via Google API using Powershell v2.0

$user = "example#gmail.com"
$pass= "examplepassword"
$secpasswd = ConvertTo-SecureString $user -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($pass, $secpasswd)
Invoke-RestMethod 'https://www.googleapis.com/gmail/v1/users/me/messages/0' -Method Delete -Credentials $cred
So, my problem here is twofold.
I originally tried using Invoke-WebRequest to delete gmail emails via the Google API with a http delete request. However, this did not work because Powershell 2.0 does not support Invoke-WebRequest.
Thereafter, I turned to attempting to utilize Invoke-RestMethod after experimentation with IMAP and POP3, which both required external dependencies (Adding .dlls to the machines I am working with is not optimal).
Therefore, if someone could show me the appropriate way to delete an email via the Google API in Powershell, I would appreciate it. I have provided some sample code as to what I am working with above. Please excuse any mistakes it may contain, as I am relatively new to Powershell, and my experience remains limited in working with RESTful services.
The GMail API is going to require Oauth2 authentication unless this is a gsuit / domain admin / GMail account in which case you can use a service account for authentication. In either case you cant use login and password.
My powershell knowledge is very limited have you considered doing this directly though the mail server IMAP and SMTP and not using the API. No idea if that's possible or not with powershell
Update:
I was able to do it using Invoke-WebRequest you will still need to get an access token first.
Invoke-WebRequest -Uri "https://www.googleapis.com/gmail/v1/users/me/messages/0?access_token=$accesstoken"-Method Get | ConvertFrom-Json
seams to also work
Invoke-RestMethod -Uri "https://www.googleapis.com/gmail/v1/users/me/messages/0?access_token=$accesstoken"-Method Get
Put up a the code for OAuth on GitHub if your interested: Google Oauth Powershell

Calling Graph API with powershell or batch

In trying to design a simplified script for use with the office 365 graph API I can't seem to find any way to call it from a simplified outset.
For the use that I have intended for it I really don't want to take the time to build and compile an actual program when everything else can be done from powershell or a batch script.
In specific, I really only want to be able to call the graph API for a list of groups and store the result (in an array or text file). Is it possible to call the graph API from powershell or command line and if so, how?
In specific, I really only want to be able to call the graph API for a list of groups and store the result (in an array or text file).
If you just need to export a list of groups. I suggest you using the Azure Active Directory PowerShell.
$msolcred = get-credential
connect-msolservice -credential $msolcred
Get-MsolGroup | Out-File C:\Workbench\temp\tests\export.txt
Is it possible to call the graph API from powershell or command line and if so, how?
Yes, it is possible, to call the REST API:
First, you need to Obtaining an Access Token
Then, use the Invoke-RestMethod to call Graph API.
Invoke-RestMethod -Uri $uri -Headers #{Authorization = "Bearer {your_access_token}"}
You can use the PSMSGRAPH module for this. Can be download from the gallery
You must register an application in Azure to authenticate and delegate the necessary right to your app. You can do it at the appreg portal
Once this is done you just need to auth and run your request.
When running the code you will have to provide a credential to authorize.
$username = 'entertheappidhere'
$password = 'entertheapppaswordhere' | ConvertTo-SecureString -AsPlainText -Force
$ClientCredential = New-Object -TypeName
System.Management.Automation.PSCredential($username,$password)
$GraphAppParams = #{}
$GraphAppParams.Add('Name','Office365TenantMigration')
$GraphAppParams.Add('ClientCredential',$ClientCredential)
$GraphAppParams.Add('RedirectUri','https://localhost/')
$GraphAppParams.Add('Tenant','yourtenant.onmicrosoft.com')
$GraphApp = New-GraphApplication #GraphAppParams
# This will prompt you to log in with your O365/Azure credentials.
$AuthCode = $GraphApp | Get-GraphOauthAuthorizationCode
$GraphAccessToken = $AuthCode | Get-GraphOauthAccessToken -Resource 'https://graph.microsoft.com/'
$GraphAccessToken | Export-GraphOAuthAccessToken -Path 'f:\O365Report\AccessToken.XML'
$GraphAccessToken = Import-GraphOAuthAccessToken -Path 'f:\O365Report\AccessToken.XML'
$GraphAccessToken | Update-GraphOAuthAccessToken -Force
### Run the query
Invoke-GraphRequest -Uri "https://graph.microsoft.com/v1.0/groups"-Method GET -AccessToken $GraphAccessToken