Getting Invalid JWT when creating project - bentley-itwin

When I get the token from the itwin-developer-console, the below PowerShell works. However, when I generate my own token, which appears to be valid per all the parsing I do of it, I get 401 Invalid JWT. I can use the token I generate to query and manipulate work area connections with no problems as long as I provide the product-settings-service scope. I've limited the scopes to just be projects:read projects:modify like the token I get from the console, but no joy. I notice that my token does not populate entitlements. Could that be it?
$url = "https://api.bentley.com/projects/"
$authVal = "Bearer $($oidcClientToken.access_token)"
$today = Get-Date -Format "yyyy-MM-dd"
$projectName = $today + " " + (Get-RandomString -Length 12 -Characters "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
$bodyCreate = ConvertTo-Json -Depth 4 #{
project = #{
displayName = $projectName
projectNumber = $projectName
industry = "Oil and Gas"
projectType = "Offshore Structures"
billingCountry = "US"
status = "active"
allowExternalTeamMembers = $true
}
}
$resp5 = Invoke-RestMethod -ContentType "Application/Json" -Method Post -Uri $url -Body $bodyCreate -Headers #{'Authorization' = $authVal; 'Content-Type' = 'application/json'; 'Accept' = 'application/vnd.bentley.itwin-platform.v1+json' }

You need a different token for calling iTwin Platform APIs, please read the Authorization documentation on this.
Specifically in this case, the token needs to be issued by https://ims.bentley.com instead of https://imsoidc.bentley.com, which is currently used by itwin.js applications. The same client will work.

Related

Create Azure Purview collection using API and Powershell

This is the first time I am working with API.
I am trying to create a purview subcollection using API and powershell.
$tenantID = "XXXXXXXXXXXXXXXXXXXXXXX"
$url = "https://login.microsoftonline.com/$tenantID/oauth2/token"
$params = #{ client_id = "XXXXXXXXXXXXXXXXXXXXXXX"; client_secret = "XXXXXXXXXXXXXXXXXXXXXXXXX"; grant_type = "client_credentials"; resource = ‘https://purview.azure.net’ }
$bearertoken = Invoke-WebRequest $url -Method Post -Body $params -UseBasicParsing | ConvertFrom-Json
$accesstoken = ConvertTo-SecureString $bearertoken.access_token -AsPlainText -Force
$purviewendpoint = "https://testpurview.purview.azure.com/account"
$url = "$purviewendpoint/collections/newcollection1?api-version=2019-11-01-preview"
$childcollection = #"
{
"parentCollection": {
"referenceName": "**testpurview**"
}
}
"#
Invoke-RestMethod -Method PUT -Uri $url -Body $childcollection -Token $accesstoken
Steps I tried:
Created a bearer token.
Created a variable for access_token from bearer token.
newcollection1: new subcollection which I want to create.
testpurview : This is the root collection of my Purview account.
Can someone help me if this is the correct way to create collection?

powershell script to retrieve logs from applications insights

https://api.applicationinsights.io/v1/query
I am using above endpoint to send a post request in powershell script and getting errors in below script.
# Set the ID of the Application Insights resource you want to query
$appId = "app id"
# Set the access token for the Application Insights resource
$accessToken = "access token"
# Encode the access token as a URL-safe string
$accessToken = [System.Uri]::EscapeDataString($accessToken)
# Set the query you want to execute
$query = "customEvents"
# Construct the request body for the Application Insights query endpoint
$requestBody = #{
appId = $appId
query = $query
} | ConvertTo-Json
# Execute the query and retrieve the results
$queryResponse = Invoke-WebRequest -Method POST -Uri "https://api.applicationinsights.io/v1/query" -Headers #{
"Authorization" = "Bearer $accessToken"
"Content-Type" = "application/json"
} -Body $requestBody
# Extract the results from the response
$results = $queryResponse.Content | ConvertFrom-Json
# Print the results
$results
ERROR :
Invoke-WebRequest : {"error":{"message":"The requested path does not exist","code":"PathNotFoundError","correlationId":"1e33e5cd-43a4-4108-b28d-0b0ef4c3942c"}}
At line:26 char:18
+ ... yResponse = Invoke-WebRequest -Method POST -Uri "https://api.applicat ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
The access token i am generating through postman for testing purpose and it is correct. Query is just customevents, not sure what is the issue here.
Edit: 9 Jan 2023
Granted read permission like this api permission but getting below error
Invoke-WebRequest : {"error":{"message":"The provided credentials have insufficient access to perform the requested operation","code":"InsufficientAccessError","correlationId":
I tried to reproduce the same in my environment and got below results:
I registered one Azure AD application and granted API permissions like below:
Now I generated the access token via Postman with below parameters:
POST https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token
grant_type:client_credentials
client_id: <appID>
client_secret: <secret>
scope: https://api.applicationinsights.io/.default
Response:
I got the ID of the Application Insights resource from here:
When I ran the same code by including above details, I got same error as below:
# Set the ID of the Application Insights resource you want to query
$appId = "xxxxxxxxxxxxxxxx"
# Set the access token for the Application Insights resource
$accessToken = "xxxxxxxxxxxxxxxxxxx"
# Encode the access token as a URL-safe string
$accessToken = [System.Uri]::EscapeDataString($accessToken)
# Set the query you want to execute
$query = "customEvents"
# Construct the request body for the Application Insights query endpoint
$requestBody = #{
appId = $appId
query = $query
} | ConvertTo-Json
# Execute the query and retrieve the results
$queryResponse = Invoke-WebRequest -Method POST -Uri "https://api.applicationinsights.io/v1/query" -Headers #{
"Authorization" = "Bearer $accessToken"
"Content-Type" = "application/json"
} -Body $requestBody
# Extract the results from the response
$results = $queryResponse.Content | ConvertFrom-Json
# Print the results
$results
Response:
To resolve the error, modify your code by changing the request URI like below:
# Set the ID of the Application Insights resource you want to query
$appId = "ID"
# Set the access token for the Application Insights resource
$accessToken = "token"
# Encode the access token as a URL-safe string
$accessToken = [System.Uri]::EscapeDataString($accessToken)
# Set the query you want to execute
$query = "customEvents"
# Construct the request body for the Application Insights query endpoint
$requestBody = #{
query = $query
} | ConvertTo-Json
# Execute the query by giving right URI and retrieve the results
$queryResponse = Invoke-WebRequest -Method POST -Uri "https://api.applicationinsights.io/v1/apps/$appID/query" -Headers #{
"Authorization" = "Bearer $accessToken"
"Content-Type" = "application/json"
} -Body $requestBody
# Extract the results from the response
$results = $queryResponse.Content | ConvertFrom-Json
# Print the results
$results
Response:
When I ran $queryResponse, I got the results of the query successfully like below:
Reference: Query - Execute - REST API (Azure Application Insights)
UPDATE:
You are getting InsufficientAccessError as Data.Read permission is removed like below:
If API permissions are removed, they will appear under Other permissions granted for tenant till their admin consent is revoked.
To resolve the error, make sure to add Data.Read permission again and grant admin consent to it.

Databricks: cannot get personal access token. Error 400 Invalid resource ID

$ADB_WORKSPACE_ID = "5555555555555"
$ADB_WORKSPACE_URL = "adb-5555555555555.5.azuredatabricks.net"
$adbGlobalToken = (az account get-access-token --resource 2ff814a6-3304-4ab8-85cb-cd0e6f879c1d | ConvertFrom-Json).accessToken
$azureApiToken= (az account get-access-token --resource "https://management.core.windows.net/" | ConvertFrom-Json).accessToken
$headers = #{
"Authorization" = "Bearer $adbGlobalToken";
"X-Databricks-Azure-SP-Management-Token" = $azureApiToken;
"X-Databricks-Azure-Workspace-Resource-Id" = $ADB_WORKSPACE_ID;
}
$body = #{
"comment" = "This is an example token";
"lifetime_seconds" = 300;
}
$uri = "https://${ADB_WORKSPACE_URL}/api/2.0/token/create"
write-host $uri
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$json = Invoke-RestMethod -Method Post -Uri $uri -Headers $headers -ContentType "application/json" -Body $body
write-host $json
Above code gives me the following error:
Invoke-RestMethod :
Error 400 Invalid resource ID.
HTTP ERROR 400
Problem accessing /api/2.0/token/create. Reason:
Invalid resource ID.
(FictiveDatabricks URL & ID )
Like the error stated, I provided the wrong resource id.
The correct way to get it is the following:
$ADB_WORKSPACE_ID = "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName/providers/Microsoft.Databricks/workspaces/$WorkspaceName"
ResourceId is not the same as the WorkSpaceId.
ResourceId can also be found in the Databricks resource json in the "id" field.

ARM Template deploymentScript PowerShell try catch ignored?

I am using an ARM Template of type "Microsoft.Resources/deploymentScripts". That uses a PowerShell script that should add an identity to a role in Azure AD. When I run that a second time the post requests, the last Invoke-RestMethod, to add the member fails. That intentional and okay because the member is already there. I wrapped that in a try catch and look for the specific error. This works fine locally but not when deployed on Azure. It still stops at the line of the invoke, 41, and does not seem to respect the try catch around that. What am I doing wrong?
param([string] $spObjectId, $roleName, $tenantId, $clientId, $clientSecret)
Write-Host $ErrorActionPreference
$ErrorActionPreference = "Continue"
$Body = #{
'tenant' = $tenantId
'client_id' = $clientId
'scope' = 'https://graph.microsoft.com/.default'
'client_secret' = $clientSecret
'grant_type' = 'client_credentials'
}
$url = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
Write-Host $url
$Params = #{
'Uri' = $url
'Method' = 'Post'
'Body' = $Body
'ContentType' = 'application/x-www-form-urlencoded'
}
$AuthResponse = Invoke-RestMethod #Params
$Headers = #{
'Authorization' = "Bearer $($AuthResponse.access_token)"
}
$roles = Invoke-RestMethod -Uri 'https://graph.microsoft.com/v1.0/directoryRoles' -Headers $Headers
$role = $roles.value | Where-Object { $_.displayName -eq "$roleName" }
$roleId = $role.id
$Body = #{
"#odata.id"= "https://graph.microsoft.com/v1.0/directoryObjects/$spObjectId"
}
$json = $Body | ConvertTo-Json
$url = "https://graph.microsoft.com/v1.0/directoryRoles/$roleId/members/`$ref"
try {
Invoke-RestMethod -Method 'Post' -Uri $url -Body $json -Headers $Headers -ContentType 'application/json'
}
catch {
$errordetails = $_.ErrorDetails.Message | ConvertFrom-Json
if($errordetails.error.message -ne "One or more added object references already exist for the following modified properties: 'members'.")
{
throw $_.Exception
}
}
Write-Host "Done"
The error in the Azure Portal
The provided script failed with the following error:
Microsoft.PowerShell.Commands.HttpResponseException: Response status
code does not indicate success: 400 (Bad Request). at
System.Management.Automation.MshCommandRuntime.ThrowTerminatingError(ErrorRecord
errorRecord) at ,
/mnt/azscripts/azscriptinput/AddMemberToRole.ps1: line 41 at
, : line 1 at ,
/mnt/azscripts/azscriptinput/DeploymentScript.ps1: line 192. Please
refer to https://aka.ms/DeploymentScriptsTroubleshoot for more
deployment script information. (Code: DeploymentScriptError)
Ideally, Invoke-RestMethod's error is captured in the try catch block. Your code looks correct and similar to what has to be done:
try{ $restp=Invoke-RestMethod (...) } catch {$err=$_.Exception}
$err | Get-Member -MemberType Property
TypeName: System.Net.WebException
Name MemberType Definition
---- ---------- ----------
Message Property string Message {get;}
Response Property System.Net.WebResponse Response {get;}
Status Property System.Net.WebExceptionStatus Status {get;}
I suspect two reasons for this behavior:
The ARM template is having issues such that try catch block is neglected. Make sure the syntax is correct and expected (ARM works in local).
An old deployed script is messing with this script. Try changing the resource name and redeploy.

PowerShell Invoke-WebRequest error with Go Daddy API

Following a script (from here) that many others have suggested works OK, I am having an error that is just outside my ability to understand. I am novice-to-intermediate with Power Shell and just beginning with API's.
The script is:
$domain = 'example.com' # your domain
$name = 'xyz' # name of the A record to update
$key = 'myKey # key for godaddy developer API
$secret = 'mySecret' # Secret for godday developer API
$headers = #{}
$headers["Authorization"] = 'sso-key ' + $key + ':' + $secret
$result = Invoke-WebRequest https://api.godaddy.com/v1/domains/$domain/records/A/$name -method get -headers $headers
$content = ConvertFrom-Json $result.content
$dnsIp = $content.data
# Get public ip address
$currentIp = Invoke-RestMethod http://ipinfo.io/json | Select -exp ip
# THE CODE WORKS FINE UP TO HERE
if ( $currentIp -ne $dnsIp) {
$Request = #{ttl=3600;data=$currentIp }
$JSON = Convertto-Json $request
# THE FOLLOWING LINE FAILS WITH THE ERROR NOTED BELOW
Invoke-WebRequest https://api.godaddy.com/v1/domains/$domain/records/A/$name -method put -headers $headers -Body $json -ContentType "application/json"
}
The following error is returned for the final Invoke-WebRequest:
Invoke-WebRequest : {"code":"INVALID_BODY","fields":[{"code":"UNEXPECTED_TYPE","message":"is not a array","path":"records"}],"message":"Request body doesn't fulfill schema, see details in `fields`"}
At C:\tfsCode\tfs\api.ps1:25 char:5
+ Invoke-WebRequest https://api.godaddy.com/v1/domains/$domain/reco ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
The Go Daddy reference page for the Get API is here and for the Put API is here.
The PUT API documentation says it’s expecting the body to be an array. This is also what the error message is saying. Try changing this line:
$Request = #{ttl=3600;data=$currentIp }
to
$Request = #(#{ttl=3600;data=$currentIp })
#() creates an array in PowerShell, when converted to JSON it will still be an array
#{} creates a hashtable in PowerShell, when converted to JSON it will be an object