RC-IamErrorResponse - Account context in the query param is different from the account context in the token - ibm-cloud

I'm trying to get resource groups via an api key.
First, I authenticate to IAM...
apikey = 'myapikeyvalue'
self.log.debug('Authenticating to IAM')
url = self.iam_endpoint + '/identity/token'
data = "apikey={}&grant_type=urn%3Aibm%3Aparams%3Aoauth%3Agrant-type%3Aapikey".format(apiKey)
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic Yng6Yng="
}
response = requests.post(url, headers=headers, data=data)
token_type, access_token = # get token_type and access_token from response
Then I receive the account_id ...
url = self.iam_endpoint + '/v1/apikeys/details'
headers = {
"IAM-Apikey": apiKey,
'accept': 'application/json',
'authorization': '{} {}'.format(token_type, access_token),
'cache-control': 'no-cache',
'content-type': 'application/json'
}
response = self._request(url=url, http_method='get', description='_get_account_id', additional_headers=headers)
account_id = response.json()['account_id']
Next, I try to retrieve the resource_groups ...
url = self.region.rc_endpoint() + '/v1/resource_groups?account_id=' + account_id
response = self.client._request(url=url, http_method='get', description='get_resource_groups')
return response.json()
However, this results in:
{
"error_code":"RC-IamErrorResponse",
"message":"Account context in the query param is different from the account context in the token.",
"status_code":401,
"transaction_id":"7e89f6873e1bd4f92d57829e0f08f4ad"
}
Any ideas?

For some reason, returned value seems to be of the format: xxxxxxxxxxxY-YYYY and we only need the x's. This worked for me
return account_id.split('-')[0][:-1]

Related

Flutter Boundary Regex not accepted

I have to make a post call to upload a image. Getting an error due to the boundary values in the header. (Regex not matched)
var requestUrl = API_URL;
// INITIALIZE MULTIPART REQUEST
http.MultipartRequest request;
// PREPARE HEADER VALUES
request = new http.MultipartRequest("POST", Uri.parse(requestUrl));
Map<String, String> headers = {
'Content-Type': 'multipart/form-data',
'Accept': 'multipart/form-data',
'Authorization': 'Bearer '+accessToken,};
request.headers.addAll(headers);
// DECLARE FILE NAME WEB
String imageType = "image." + this.xfile!.mimeType.toString().split('/').last;
// ADD TO REQUEST
request.files.add(http.MultipartFile.fromBytes('image', await this.xfile!.readAsBytes(), filename:imageType ));
// SEND REQUEST
http.StreamedResponse responseAttachmentSTR = await request.send();
I deployed the codes to the server. Apparently this causes a 403 Forbidden error, when I try to upload an image.
Through debugging, it was because of the regex in the Header (Boundary):
boundary=dart-http-boundary-poYEiL0Ungmxkla.2lkZeC6Mub.-Fupw5T_MmJpxColFVjXf-qr
What can I do about this?

Failed to upload apk via Connect API

I am working on a python script to update the app on Huawei AppGallery via Connect API.
I successfully fetched the token and upload URL but not able to upload the APK/AAB.
Getting this error -
{'result': {'CException': {'errorCode': 70001405, 'errorDesc': 'get no file from request!'}, 'resultCode': '70001405'}}
Here's my python script
def uploadAAB(uploadUrl, authCode, accessToken, appId):
try:
fileName = 'latest_hms.apk'
headers = {
"Authorization": "Bearer " + accessToken,
"accept": "application/json",
"client_id": clientId,
"Content-Type": "multipart/form-data"
}
uploadBody = {
"authCode": authCode,
"fileCount": 1
}
with open(aabPath, 'rb') as f:
f.seek(0, os.SEEK_END)
print(f.tell()) # printing the correct size
first_phase = requests.post(
uploadUrl,
files={fileName: f},
data=uploadBody,
headers=headers)
if first_phase.status_code == 200:
print(first_phase.json())
body = {
'fileType': 5,
'files': [{
'fileName': fileName,
'fileDestUrl': first_phase.json()['result']['UploadFileRsp']['fileInfoList'][0]['fileDestUlr'],
'size': str(first_phase.json()['result']['UploadFileRsp']['fileInfoList'][0]['size'])
}]
}
fileHeader = {
'client_id': clientId,
'Authorization': 'Bearer ' + accessToken,
}
params = {
'appId': appId,
}
second_phase = requests.put(
BASE_URL + "/publish/v2/app-file-info",
headers=fileHeader,
json=body,
params=params)
print(second_phase.json())
except (requests.exceptions.RequestException, requests.exceptions.HTTPError, KeyError) as err:
stopOnError(repr(err))
Please help me out here.
{'result': {'CException': {'errorCode': 70001405, 'errorDesc': 'get no file from request!'}, 'resultCode': '70001405'}}
This error means there is no file in the request. the file is not include successfully in the request. Please make sure the file is achievable.
It seems Huawei made a change to the AppGallery API in February 2022. I don't know if this was intentional, but you must now specify a filename of "file" instead of your original filename (which worked before). See my pull request on Natgho's HMS-Publishing-API code.

401 Auth error with apps script connecting to 3rd party API

I am beating my head up trying to get this to work.
Any assistance would be appreciated.
I have tested the auth in Insomnia and Postman and its working fine but not with apps script. I am getting a "401 Authorization Required" response.
function myFunction() {
var url = "https://api.tempo.io/core/3/worklogs/project/MYPROJECT";
var token = "THISISATOKEN";
var headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer "+ token,
"muteHttpExceptions": true
};
var options = {
"method" : "get",
"headers" : headers
};
var response = UrlFetchApp.fetch(url,headers);
Logger.log(response);

http post - how to send Authorization header?

How do you add headers to your http request in Angular2 RC6?
I got following code:
login(login: String, password: String): Observable<boolean> {
console.log(login);
console.log(password);
this.cookieService.removeAll();
let headers = new Headers();
headers.append("Authorization","Basic YW5ndWxhci13YXJlaG91c2Utc2VydmljZXM6MTIzNDU2");
this.http.post(AUTHENTICATION_ENDPOINT + "?grant_type=password&scope=trust&username=" + login + "&password=" + password, null, {headers: headers}).subscribe(response => {
console.log(response);
});
//some return
}
The problem is, that angular doesn't add Authorization header. Instead of that, in request I can see following additional headers:
Access-Control-Request-Headers:authorization
Access-Control-Request-Method:POST
and sdch added in Accept-Encoding:
Accept-Encoding:gzip, deflate, sdch
Unfornately there is no Authorization header. How should I add it correctly?
Whole request sent by my code looks as follow:
OPTIONS /oauth/token?grant_type=password&scope=trust&username=asdf&password=asdf HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: POST
Origin: http://localhost:3002
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Access-Control-Request-Headers: authorization
Accept: */*
Referer: http://localhost:3002/login
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,pl;q=0.6
Ok. I found problem.
It was not on the Angular side. To be honest, there were no problem at all.
Reason why I was unable to perform my request succesfuly was that my server app was not properly handling OPTIONS request.
Why OPTIONS, not POST? My server app is on different host, then frontend. Because of CORS my browser was converting POST to OPTION:
http://restlet.com/blog/2015/12/15/understanding-and-using-cors/
With help of this answer:
Standalone Spring OAuth2 JWT Authorization Server + CORS
I implemented proper filter on my server-side app.
Thanks to #Supamiu - the person which fingered me that I am not sending POST at all.
you need RequestOptions
let headers = new Headers({'Content-Type': 'application/json'});
headers.append('Authorization','Bearer ')
let options = new RequestOptions({headers: headers});
return this.http.post(APIname,body,options)
.map(this.extractData)
.catch(this.handleError);
for more check this link
I believe you need to map the result before you subscribe to it. You configure it like this:
updateProfileInformation(user: User) {
var headers = new Headers();
headers.append('Content-Type', this.constants.jsonContentType);
var t = localStorage.getItem("accessToken");
headers.append("Authorization", "Bearer " + t;
var body = JSON.stringify(user);
return this.http.post(this.constants.userUrl + "UpdateUser", body, { headers: headers })
.map((response: Response) => {
var result = response.json();
return result;
})
.catch(this.handleError)
.subscribe(
status => this.statusMessage = status,
error => this.errorMessage = error,
() => this.completeUpdateUser()
);
}
If you are like me, and starring at your angular/ionic typescript, which looks like..
getPdf(endpoint: string): Observable<Blob> {
let url = this.url + '/' + endpoint;
let token = this.msal.accessToken;
console.log(token);
return this.http.post<Blob>(url, {
headers: new HttpHeaders(
{
'Access-Control-Allow-Origin': 'https://localhost:5100',
'Access-Control-Allow-Methods': 'POST',
'Content-Type': 'application/pdf',
'Authorization': 'Bearer ' + token,
'Accept': '*/*',
}),
//responseType: ResponseContentType.Blob,
});
}
And while you are setting options but can't seem to figure why they aren't anywhere..
Well.. if you were like me and started this post from a copy/paste of a get, then...
Change to:
getPdf(endpoint: string): Observable<Blob> {
let url = this.url + '/' + endpoint;
let token = this.msal.accessToken;
console.log(token);
return this.http.post<Blob>(url, null, { // <----- notice the null *****
headers: new HttpHeaders(
{
'Authorization': 'Bearer ' + token,
'Accept': '*/*',
}),
//responseType: ResponseContentType.Blob,
});
}
I had the same issue. This is my solution using angular documentation and firebase Token:
getService() {
const accessToken=this.afAuth.auth.currentUser.getToken().then(res=>{
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': res
})
};
return this.http.get('Url',httpOptions)
.subscribe(res => console.log(res));
}); }}
Here is the detailed answer to the question:
Pass data into the HTTP header from the Angular side (Please note I am
using Angular4.0+ in the application).
There is more than one way we can pass data into the headers.
The syntax is different but all means the same.
// Option 1
const httpOptions = {
headers: new HttpHeaders({
'Authorization': 'my-auth-token',
'ID': emp.UserID,
})
};
// Option 2
let httpHeaders = new HttpHeaders();
httpHeaders = httpHeaders.append('Authorization', 'my-auth-token');
httpHeaders = httpHeaders.append('ID', '001');
httpHeaders.set('Content-Type', 'application/json');
let options = {headers:httpHeaders};
// Option 1
return this.http.post(this.url + 'testMethod', body,httpOptions)
// Option 2
return this.http.post(this.url + 'testMethod', body,options)
In the call you can find the field passed as a header as shown in the image below :
Still, if you are facing the issues like.. (You may need to change the backend/WebAPI side)
Response to preflight request doesn't pass access control check: No
''Access-Control-Allow-Origin'' header is present on the requested resource. Origin ''http://localhost:4200'' is therefore not allowed
access
Response for preflight does not have HTTP ok status.
Find my detailed answer at https://stackoverflow.com/a/52620468/3454221
if you are a ruby on rails developer and you facing a similar issue, this is because of the config of your backend: especially in api mode
so with
gem 'rack-cors' installed
goto app/config/cors.rb
Be sure to restart your server when you modify this file.
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins 'domain_name:port or just use *'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head],
credentials: true
end
end
the *credentials:true line does the trick
then in your SessionController
after a user is valid for login
insert a line(this assumes you are using gem 'jwt')
token = user.generate_jwt
response.headers['Authorization'] = token
generate_jwt is a method called in model User , it is
JWT.encode(id, key, alogrithm)
If you use django, that is already taken care for you
you just have to use
installed app: restframework_simplejwt

Groovy wslite.rest.RestClient post or put results in a 411 Length Required Error

Using the wslite.rest.RestClient, if I use post or put, I'm getting a 411 Length Required error returned from the service. I've added the header Content-Length: (size) but I still get an error. Does anyone have suguestions? Here's the code for a put request:
def builder = new JsonBuilder()
// required json data
def root = builder {
"ActivationDate" "\\/Date(1434563608000-0500)\\/"
"EmailAddress" "ebaa#gmail.com"
"ExpirationDate" "\\/Date(1435686808000-0500)\\/"
"FirstName" "ebaa"
"LastName" "ebaa"
"MiddleName" "ebaa"
"OtherName" "ebaa"
"Password" "abc12345"
"Status" 1
}
RESTClient restClient = new RESTClient('https://serviceBaseUrl')
Response response
try {
restClient.authorization = new HTTPBasicAuthorization(username: 'user', password: 'pass')
restClient.defaultCharset = 'UTF-8'
restClient.defaultContentTypeHeader = 'application/json'
restClient.defaultAcceptHeader = 'application/json'
response = restClient.put(path: "/Location/${locName}/Administrator/${name}",
headers:['Accept': 'application/json',
'Accept-Language':'en-US,en;q=0.5', 'Content-Type': 'application/json; charset=UTF-8',
'Connection':'keep-alive', 'Pragma':'no-cache', 'Cache-Control':'no-cache',
'Content-Length': builder.toString().length()],
data: builder.toPrettyString().getBytes())
return response.json
} catch(ex) {
ex.printStackTrace()
}
I've also tried changing the data: param to body, but I get the same response. Also, If I use the Firefox plugin, HttpRequester (https://addons.mozilla.org/En-us/firefox/addon/httprequester/) and make the same request, I get a 200 status code and the appropriate data is updated. Thanks!
For put or post it is expecting the payload to be in a closure. Try the following, this should send the data and automatically set the right Content-Length:
....
....
response = restClient.put(
path: "/Location/${locName}/Administrator/${name}",
headers:['Accept': 'application/json',
'Accept-Language':'en-US,en;q=0.5',
'Content-Type': 'application/json; charset=UTF-8',
'Connection':'keep-alive',
'Pragma':'no-cache',
'Cache-Control':'no-cache'])
{
text builder.toPrettyString()
//bytes builder.toPrettyString().bytes // or as bytes
//json 'ActivationDate': '...', 'EmailAddress': '...' // or a json string from a map
}
See the Sending Content section of the README.