Unable to get folder by id when using Boxr JWT get_user_token- Box API - ruby

I'm unable to a folder by providing an id to that folder using Boxr gem. Previously I didn't has the enterprise settings as shown in this post which I have now fixed. I'm creating a token using JWT authentication get_user_token method the following way.
token = Boxr::get_user_token("38521XXXX", private_key: ENV.fetch('JWT_PRIVATE_KEY'), private_key_password: ENV.fetch('JWT_PRIVATE_KEY_PASSWORD'), public_key_id: ENV.fetch('JWT_PUBLIC_KEY_ID'), client_id: ENV.fetch('BOX_CLIENT_ID'), client_secret: ENV.fetch('BOX_CLIENT_SECRET'))
I then pass this this token when creating a client.
client = Boxr::Client.new(token)
when I check the current user on client this is what I get:
client.current_user
=> {"type"=>"user",
"id"=>"60853XXXX",
"name"=>"OnlineAppsPoC",
"login"=>"AutomationUser_629741_06JgxiPtPj#boxdevedition.com",
"created_at"=>"2018-10-04T08:41:32-07:00",
"modified_at"=>"2018-10-04T08:41:50-07:00",
"language"=>"en",
"timezone"=>"America/Los_Angeles",
"space_amount"=>10737418240,
"space_used"=>0,
"max_upload_size"=>2147483648,
"status"=>"active",
"job_title"=>"",
"phone"=>"",
"address"=>"",
"avatar_url"=>"https://app.box.com/api/avatar/large/6085300897"}
When I run client.methods I see there is folder_from_id however when I call that method I get the following error:
pry(#<FormsController>)> client.folder_from_id("123456", fields: [])
Boxr::BoxrError: 404: Not Found
from /usr/local/bundle/gems/boxr-1.4.0/lib/boxr/client.rb:239:in `check_response_status'
I have the following settings:
I also authorize the application. Not sure what else to do.

token = Boxr::get_user_token(user_id,
private_key: ENV.fetch('JWT_PRIVATE_KEY'),
private_key_password: ENV.fetch('JWT_PRIVATE_KEY_PASSWORD'),
public_key_id: ENV.fetch('JWT_PUBLIC_KEY_ID'),
client_id: ENV.fetch('BOX_CLIENT_ID'),
client_secret: ENV.fetch('BOX_CLIENT_SECRET'))
client = Boxr::Client.new(token.access_token)
folder = client.folder_from_id(folder_id)
client.upload_file(file_path, folder)

For anybody using C# and BOXJWT.
You just need to have a boxManager set up and will get you with anything you need, say BoxFile, Folder etc.
If you have the folderID, well & good, but if you need to retrieve, this can be done as shown below:
string inputFolderId = _boxManager.GetFolder(RootFolderID).Folders.Where(i => i.Name == boxFolder).FirstOrDefault().Id; //Retrieves FolderId
Folder inputFolder = _boxManager.GetFolder(inputFolderId);

Related

Every error in the book from google-api-ruby-client but no data

I have been attempting to work on a request from my boss this week that requires using the google admin directory api.
At this point I am questioning if what I am trying to do is even possible.
Can I retrieve data from the scope "https://www.googleapis.com/auth/admin.directory.device.mobile.readonly" with a service account? Is it even possible?
The errors I have seen in the past hour are below...
Many of them sound the same and I have no idea what is going on or why this is such a difficult journey for such basic information.
PERMISSION_DENIED: Request had insufficient authentication scopes. (Google::Apis::ClientError)
`check_status': Unauthorized (Google::Apis::AuthorizationError)
Authorization failed. Server message: (Signet::AuthorizationError)
{
"error": "unauthorized_client",
"error_description": "Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested."
}
`check_status': permission_denied: request had insufficient authentication scopes
`check_status': badRequest: Bad Request
My current test script is below...
require "google/apis/admin_directory_v1"
require "googleauth"
require "googleauth/stores/file_token_store"
require "fileutils"
APPLICATION_NAME = "Directory API Ruby Quickstart".freeze
CREDENTIALS_PATH = "credentials.json".freeze
CUSTOMER_ID = "thasgunnabeanopefrommedawg".freeze
SCOPE = ["https://www.googleapis.com/auth/admin.directory.device.mobile.readonly"].freeze
authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
json_key_io:
File.open('credentials.json'),
scope: SCOPE)
authorizer.update!(sub: "fullbl00m#citadelny.com")
authorizer.fetch_access_token!
# puts authorize
# Initialize the API
service = Google::Apis::AdminDirectoryV1::DirectoryService.new
service.client_options.application_name = APPLICATION_NAME
service.authorization = Google::Auth.get_application_default(SCOPE)
response = service.list_mobile_devices(customer_id: CUSTOMER_ID)
puts response.to_json
EDITS BELOW *** [27th, MAY, 2022]
I have been trying with ruby, python, and postman for two weeks at this point :/
Last night I took the ruby snippet that was posted by user:Daimto below.
I was able to return a token with the following modified version of the ruby snippet provided in the answer below.
require 'googleauth'
require 'google/apis/admin_directory_v1'
creds = {
"type": "service_account",
"project_id": "MYPROJECTNAME",
"private_key_id": "MYPRIVATEKEYID",
"private_key": "-----BEGIN PRIVATE KEY-----\n-MY PRIVATE KEY
WILL BE HERE BUT REMOVED FOR SECURITY-----END PRIVATE KEY-----\n",
"client_email": "emailfromserviceaccount-compute#developer.gserviceaccount.com",
"client_id": "MYCLIENTIDISACTUALLYHERE",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/compute%40developer.gserviceaccount.com"
}
creds_json = creds.to_json
creds_json_io = StringIO.new(creds_json)
auth = Google::Auth::ServiceAccountCredentials.make_creds(
json_key_io: creds_json_io,
scope["https://www.googleapis.com/auth/admin.directory.device.mobile.readonly","https://www.googleapis.com/auth/admin.directory.device.chromeos.readonly","https://www.googleapis.com/auth/admin.directory.device.mobile"]
)
auth.sub = "emailfrommyserviceaccount-
compute#developer.gserviceaccount.com"
puts auth.fetch_access_token
Please excuse the formatting.
I took the service account out of the env variable for now to make sure I can get it to work without adding extra layers of abstraction at this time.
When trying to add the additional code from the Directory Api Quickstart to the above snip I STILL RETURN THE ERROR
/var/lib/gems/2.7.0/gems/google-apis-core-0.5.0/lib/google/apis/core/http_command.rb:224:in `check_status': Unauthorized (Google::Apis::AuthorizationError)
The additional code added is below...
The last line of the previous snip gets changed to the first line of the snip that comes after this. This is to properly pass the token to the example after modifying user:Daimto's response.
authorize = auth.fetch_access_token
# Initialize the API
service = Google::Apis::AdminDirectoryV1::DirectoryService.new
service.client_options.application_name = "my-application-name"
service.authorization = authorize
# List the first 10 users in the domain
response = service.list_users(customer: "my_customer",
max_results: 10,
order_by: "email")
puts "Users:"
puts "No users found" if response.users.empty?
response.users.each { |user| puts "- #{user.primary_email} (#{user.name.full_name})" }
The method Method: mobiledevices.list requires one of the following scopes.
So to answer your first question yes you can use the https://www.googleapis.com/auth/admin.directory.device.mobile.readonly scope.
Error number 1
PERMISSION_DENIED: Request had insufficient authentication scopes.
You were probably getting this error when you had supplied a different scope.
Error 3;
Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.
There are three types of clients you can create on google cloud console.
web client
native client
service account
The json file you get from creating these clients is all different. The code that uses them is also different. The error is telling you that you have a client.json file that you are using which does not match the type of code you are using.
How to create service account credetinals
The code for a service account would be like this Not tested you may need to fix the scope. Remember that the service account needs to be configured properly on your workspace domain for the sub to work.
require 'googleauth'
require 'google/apis/admin_v1'
creds = ENV['GOOGLE_SERVICE_ACCOUNT'] # JSON downloaded from cloud console
# is saved in this ENV variable
creds_json = JSON.parse(creds)
creds_json_io = StringIO.new(creds_json.to_json)
auth = Google::Auth::ServiceAccountCredentials.make_creds(
json_key_io: creds_json_io,
scope: [Google::Apis::ADMINV1::ADMIN_DIRECTORY_MOBILE_READONLY]
)
auth.sub = 'admin#yourdomain.com'
auth.fetch_access_token
Tip: You have a lot of errors there, I feel that you have been struggling with this for a while. Advice step back, have a look at the sample on the readme for the Google-api-ruby-client. Start over. Just get your auth to work. Once you get the code right and the client right all the pieces will fit into place.

Google Cloud Identity API - missing hostname fields/data

Thank you beforehand for taking the time to check out my question.
While using Cloud Identity API to query for managed devices (Windows, Mac) details from our Google Workspace, I am able to query successfully by the "device ID" assigned by google, however, the "hostname" field is not included in the response.
This is an example of the call and response that I get.
https://cloudidentity.googleapis.com/v1/devices
def device_query():
FILTER = urllib.parse.quote_plus('serial:'+<serialNumber>)
list_url = BASE_URL + 'devices?name=' + FILTER
auth_header = {'Authorization': 'Bearer ' + getAuthToken()}
content = urllib.request.urlopen(
urllib.request.Request(list_url, headers=auth_header)).read()
response = json.loads(content)
deviceDetails = response['devices']
print(deviceDetails)
{'devices':
[{'name': 'devices/xxxxxxxxxxxx',
'createTime': '9999-99-99T20:11:31.680Z',
'lastSyncTime': '9999-99-99T15:01:51.922Z',
'ownerType': 'Company Owned',
'model': 'Windows',
'osVersion': 'Win10',
'deviceType': 'Windows',
'serialNumber': '737dh39he8d3978'}]
}
When looking at any device through Workspace, I can see similar details including the hostname.
[Workspace UI device hostname example][1]
The UI URL looks like this: https://admin.google.com/ac/devices/details/8613sw4fa4-90b2-5098-61384-d139d0775r9gg/information?uid=7dhdhsw7hd3h83d&dt=4
This is the API endpoint: cloudidentity.googleapis.com/v1 I am using to retrieve device data.

DocuSign / Ruby - unsupported_grant_type when trying to obtain token

We are moving away from using the DocuSign::Esign gem and we are trying to make the API calls following the How to get an access token with JWT Grant authentication instructions. The consent has already been granted for this application when we set up this originally with the DocuSign::Esign gem.
I am getting the following error:
{"error"=>"invalid_grant", "error_description"=>"unsupported_grant_type"}
I am using Ruby and am running this code in the console
config = Padrino.config.docusign
current_time = Time.now.utc
header = {
typ: 'JWT',
alg: 'RS256'
}
body = {
iss: config.integrator_key,
sub: config.user_id,
iat: current_time.to_i,
exp: (current_time + 1.hour).to_i,
aud: config.host,
scope: 'signature impersonation'
}
key_file = "-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAiOMDM5jdGYTEOC/nFVUTQ3+5U2TCUpEKyUD+mByldDbgvT9q
. . .
jDjfX6L15x8JcY9eiXvCvZNF6Za2dg8cagK+ff5d6KLodmVFD5o=
-----END RSA PRIVATE KEY-----"
private_key = OpenSSL::PKey::RSA.new(key_file)
token = JWT.encode(body, private_key, 'RS256')
uri = 'https://account-d.docusign.com/oauth/token'
data = {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: token
}
auth_headers = {content_type: 'application/x-www-form-urlencoded'}
However, when I call the api, I get a RestClient::Bad response error
irb(main):352:0> begin
irb(main):353:1> RestClient.post(uri, data.to_json, auth_headers)
irb(main):354:1> rescue RestClient::BadRequest => e
irb(main):355:1> JSON.parse(e.http_body)
irb(main):356:1> end
=> {"error"=>"invalid_grant", "error_description"=>"unsupported_grant_type"}
I am not sure what I am doing wrong. The JWT decodes correctly when I check it in https://jwt.io/. I am using the grant_type exactly as provided in the documentation.
Hmmm,
scope claim only needs to be signature (impersonation is implied since you're using the JWT grant flow.)
For the aud claim, what is config.host? It should be account-d.docusign.com for the developer system (Do not include https://)
Your main error is that you are sending the data hash in JSON format. That's wrong, it must be sent in url form format. Try
RestClient.post(uri, data, auth_headers)
instead. (Don't convert the data to json.)

How to create and execute a function using the Apps Script API

I created a script following "Ruby Quickstart" but I can't run it with the API.
I know that I should publish it as API executable. To do that I need to switch the script project to use a "standard GCP project" and I couldn't find how to do it from the API.
If I switch it manually it works. When I execute the code below I get this error:
> 403, PERMISSION_DENIED: The caller does not have permission
This is the code:
def create_and_execute
# Initialize the API
service = Google::Apis::ScriptV1::ScriptService.new
service.client_options.application_name = APPLICATION_NAME
service.authorization = authorize
# Make the API request.
request = Google::Apis::ScriptV1::CreateProjectRequest.new(
title: "My Script3"
)
resp = service.create_project request
script_id = resp.script_id
content = Google::Apis::ScriptV1::Content.new(
files: [
Google::Apis::ScriptV1::File.new(
name: "hello",
type: "SERVER_JS",
source: "function helloWorld() {\n console.log('Hello, world!');\n}"
),
Google::Apis::ScriptV1::File.new(
name: "appsscript",
type: "JSON",
source: "{\"timeZone\":\"America/Los_Angeles\",\"exceptionLogging\":\"CLOUD\",\"executionApi\":{\"access\":\"ANYONE\"}}"
)
],
script_id: script_id
)
service.update_project_content(script_id, content)
service.create_project_version(script_id,Google::Apis::ScriptV1::Version.new(script_id: script_id))
service.create_project_deployment(script_id,Google::Apis::ScriptV1::DeploymentConfig.new(script_id: script_id,version_number: 1))
service.run_script(script_id, Google::Apis::ScriptV1::ExecutionRequest.new(function: 'helloWorld', dev_mode: true))
end
I am sorry to inform you that this operation is not possible. You need to use a standard browser interface (read as not an API) to switch a GCP project as described here. On this docs you can find more information about how to use Apps Script on your app, and here you can learn how to activate any API (included Apps Scripts API).

Error working with Typhoreus and SeoMoz API

I am working with the SEOMoz API using the Typhoreus gem. To authenticate(Signed Authentication) with the API, I use the following code:
url = "http://lsapi.seomoz.com/linkscape/url-metrics/"+website.url.strip+"?Cols=103079231520"
response = Typhoeus::Request.get(url, :username => "member-xxxxxxx", :password => "abcxyzwhatever")
To which I get the error: Ethon::Errors::InvalidOption: The option: username is invalid.
Please try userpwd instead of username.
If I change the username to userpwd, it asks to change password to userpwd as well.
Where am I going wrong?
The api changed a bit, that should work:
Typhoeus::Request.get(url, :userpwd => "member-xxxxxxx:abcxyzwhatever")

Resources