On AWS, I built a Lambda function which is exposed on the web using API Gateway.
Access to the API is secured by Amazon Cognito.
My problem is I can't send a request to this API from a client hosted at test.mydomain.com, even after I successfully authenticate on Cognito (thus sending the required token in the request header).
The code I use on my web client to send the request to API Gateway endpoint:
function ajaxPost(url, data, callback) {
var req = new XMLHttpRequest();
req.open("POST", url);
req.addEventListener("load", function () {
if (req.status >= 200 && req.status < 400) {
callback(req.responseText);
} else {
console.error(req.status + " " + req.statusText + " " + url);
}
});
req.addEventListener("error", function () {
console.error("URL " + url + " unreachable.");
});
req.setRequestHeader("Content-Type", "application/json");
req.setRequestHeader("Authorization", data.get("id-token"));
data = JSON.stringify(data);
req.send(data);
}
I enabled CORS on the API method via AWS console, and also on my browser for testing, so cross-domain requests should be allowed.
EDIT
After adding Access-Control-Expose-Headers in the API Gateway CORS config,
the error message I get from the Chrome console is: "XMLHttpRequest cannot load https://XXXX.execute-api.us-east-1.amazonaws.com/prod/RessourceName. Response for preflight has invalid HTTP status code 401" and I can see "x-amzn-errortype:UnauthorizedException" in the OPTIONS response Header.
It's been a few days now, and after looking at every API Gateway tutorials and config, I'm still stucked... Any help would be appreciated, thanks a lot!
Solved!
Apparently, there would be a bug in AWS, where enabling/editing CORS after the API has been deployed would do nothing.
See SO response here: https://stackoverflow.com/a/40733680/7717871
I tried creating a new API from AWS Console, enabling CORS at the very beginning of the process, and then deploying the newly created API: it worked.
Related
I've been trying to send a verification code to a phone via the Google Identity Toolkit API, I have all the right keys generated via Google Cloud Console and the ReCaptcha V3 token generated by the web app (See in code) but I still get an error when trying to send a request to the account:sendVerificationCode endpoint of the API. Maybe someone can help the community who has encountered this error too and me.
Important: I'm calling the endpoint from a valid URL added in the Google Cloud Console. It is an Authorized Domain.
Framework: Ionic + Angular
Language: Typescript
Environment Variables:
googleapisurl: "https://identitytoolkit.googleapis.com/v1/accounts:sendVerificationCode"
Error:
Code to get the ReCaptcha V3 token (ng-recapcha library):
this.recaptchaToken = await firstValueFrom(this.recapchaV3Service.execute('importantAction'));
Code to send the HTTP request using Angular HTTP Client:
let map: Map<string, string> = new Map<string, string>();
map.set("phoneNumber", this.phoneNumber);
map.set("recaptchaToken", this.recaptchaToken);
let jsonObject = {};
map.forEach((value, key) => {
jsonObject[key] = value
});
let url: URL = new URL(environment.googleapisurl);
url.searchParams.append("key", environment.googlecloudapikey);
await firstValueFrom(this.httpClient.post(url.toString(), JSON.stringify(jsonObject))).then(response => {
console.log(response);
this.presentAlert();
});
Note: Trying from Postman gets the same error.
I have encountered a strange issue with a GET request that I am stuck on.
I am calling a GET request from my ASP.Net application that works fine in postman but does not hit my userGETReq.onload.
function getUser(username){
userGETReq.open("GET", userURL + "/" + username);
userGETReq.send();
userGETReq.onload = () => {if(userGETReq.status === 200){//cool stuff }}
I am running on a localhost in the browser - the function to start this is being called from a form that returns false.
<form onsubmit="login(this); return false">
POSTMAN
Picture of successful postman response for the GET request
I have other GET requests from the same application that work.
The only difference between this and the other one that works is that it has a 'variable' that gets passed in and has a set route:
[Route("api/User/{username}")]
public List<User> Get(string username)
This is how my CORS is set up
that is the problem
CORS:
EnableCorsAttribute cors = new EnableCorsAttribute("*","*","*");
config.EnableCors(cors);
Any help would be greatly appreciated!
The waring I am getting:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:56390/api/user/test3. (Reason: CORS request did not succeed).
to resolve CORS issue, you can write another method in service as follows
Every time service call is made, OPTIONS is triggered first to check if the service call is allowed and once the OPTIONS returns allowed, actual method is invoked
//here you can add URL of calling host or the client URL under HEADER_AC_ALLOW_ORIGIN
#OPTIONS
#Path("/yourservice/")
#LocalPreflight
public Response options() {
String origin = headers.getRequestHeader("Origin").get(0);
LOG.info(" In options!!!!!!!!: {}", origin);
if ("http://localhost:4200".equals(origin)) {
return Response.ok()
.header(CorsHeaderConstants.HEADER_AC_ALLOW_METHODS, "GET,POST,DELETE,PUT,OPTIONS")
.header(CorsHeaderConstants.HEADER_AC_ALLOW_CREDENTIALS, "false")
.header(CorsHeaderConstants.HEADER_AC_ALLOW_ORIGIN, "http://localhost:4200")
.header(CorsHeaderConstants.HEADER_AC_ALLOW_HEADERS, "content-type")
.build();
} else {
return Response.ok().build();
}
}
We are receiving 403 responses when posting to the company shares endpoint.
This happens when using the example company 2414183 and our chosen company.
The call to is-company-share-enabled endpoint is successful.
We are checking that the user is authenticated before making the request.
The LinkedIn profile we are using is set up as an company admin.
The domains we are calling from have been added to the Valid SDK Domains list.
It looks like the app usage & limits is counting these failed requests.
We can successfully post from Postman to both companies shares with varying payloads (using Postmans in built OAuth 2.0).
Would anyone be able to help us with this?
Here are some of the failed request ids
58LETKI9LD
RBG4DRL5VT
XYCOX9XID1
JPY6AORIKW
The code being used is mostly from the developer guides.
<script type="text/javascript" src="//platform.linkedin.com/in.js">
api_key: [removed]
authorize: false
</script>
$scope.postToLinkedInCompanyPage = function () {
if (!IN.User.isAuthorized()) {
IN.User.authorize(shareLinkedInCompanyPageContent);
}
else {
shareLinkedInCompanyPageContent();
}
};
function shareLinkedInCompanyPageContent() {
if (!IN.User.isAuthorized()) {
console.error("User not authorized");
return;
}
var payload = {
"comment": "Check out developer.linkedin.com! http://linkd.in/1FC2PyG",
"visibility": {
"code": "anyone"
}
};
var cpnyID = [removed];
IN.API.Raw("/companies/" + cpnyID + "/shares?format=json")
.method("POST")
.body(JSON.stringify(payload))
.result(onSuccess)
.error(onError);
}
function onSuccess(data) {
console.log(data);
}
function onError(error) {
console.log(error);
}
06/12/2018 - Update
I tried the code out into a simple web app.
Converting the angular into plain JavaScript.
When posting to the test company 2414183, I still receive 403
POST https://api.linkedin.com/v1/companies/2414183/shares?format=json 403
{errorCode: 0, message: "Unauthorized request", requestId: "259UFIKLIR", status: 403, timestamp: 1544085898666}
Version 1 of the API is no longer supported.
Here is an extract from the LinkedIn dev blog
Update: As of May 1, 2019, Version 1.0 of our API is no longer
supported. Applications requesting Version 1.0 APIs may experience
issues as we begin to remove services. To find the latest updates, go
to the new LinkedIn Developers site at
https://www.linkedin.com/developers/. You can learn more about our
Version 2.0 APIs, our developer program, and how to migrate your apps.
I'll update the tags and header so this isn't picked up in future searches
My post works in postman but doesn't work inside my app. What am I doing wrong?
let data = obj;
let url = 'https://us123.api.mailchimp.com/3.0/lists/{somenumber}/members';
let username: string = 'user';
let password: string = 'mytokenhere';
let headers = new Headers();
headers.append("Authorization", "Basic " + btoa(username + ":" + password));
headers.append("Content-Type", "application/x-www-form-urlencoded");
return this._http.post(url, data, {headers: headers}).subscribe(
data => this.response(data),
error => this.response(error)
);
I'm getting a CORS error in app:
'XMLHttpRequest cannot load https://us123.api.mailchimp.com/3.0/lists/{{somenumber}}/members. 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. The response had HTTP status code 501.'
Mailchimp doesn't support client side calls to their API. What you would need to do is setup a server that can proxy the requests from the browser to Mailchimp. There isn't much you can do client side to get it to work if the Mailchimp API doesn't provide the CORS response headers.
If your API that you create is on the same domain as the website, then the CORS issue would be eliminated (or you can also fix by setting the appropriate headers)
See the note under Authentication:
https://developer.mailchimp.com/documentation/mailchimp/guides/get-started-with-mailchimp-api-3/
More Info:
https://www.moesif.com/blog/technical/cors/Authoritative-Guide-to-CORS-Cross-Origin-Resource-Sharing-for-REST-APIs/
I'm having an issue retreiving the OAuth2 token for google using DotNetOpenAuth 4.2.0.13024.
I've got to the point where I can successfully make the authorization request to the google endpoint https://accounts.google.com/o/oauth2/auth
When the user clicks 'OK', google then calls my callback URL as expected with the appropriate "code" query string.
However, I am unable to exchange this code for a token, as my calls keep failing with "Protocol exception was unhandled" execption and "400 Bad request" as the inner exception. This is the code I am using to exchange the token
private static AuthorizationServerDescription authServerDescription = new AuthorizationServerDescription
{
TokenEndpoint = new Uri("https://accounts.google.com/o/oauth2/token"),
AuthorizationEndpoint = new Uri("https://accounts.google.com/o/oauth2/auth")
};
static GoogleContacts()
{
Client = new WebServerClient(authServerDescription, "{my_cliend_id}", "{me_secret_key}");
}
var authorization = Client.ProcessUserAuthorization(); // <- Exception is thrown here
if (authorization != null)
{
Authorization = authorization;
Response.Redirect(Request.Path); // get rid of the /?code= parameter
}
PS: it seems like a new version of DotNerOpenAuth has been released but, I am unable to get it because the zip download still points to the older version and Nuget keeps failing on me :(