403 Forbidden in Vue.js + CodeIgniter 4 - javascript

I created a simple api using CodeIgniter 4 that currently has 2 routes :
$routes->get('/expenses','Home::getAllExpenses');
$routes->post('/expenses','Home::addRecord');
I display the data using Vue, so the first one returns some json data about expenses while the second one should store the data from a form.
What happens is when I hit submit I get a 403 Forbidden for the post route.
The call is made like this:
this.validationError = false;
this.request.sum = this.sum;
this.request.type = this.type;
this.request.name = this.name;
this.$http.post(base_api_url + 'expenses', this.request)
.then(function(response){
console.log(response);
});
The get request is ok and nothing on the CI forum helped me :(

Could you check to see if your POST requests also includes cookies (in developer tools > network tab)? It's a fairly common problem that fetch/xhr libraries (like this.$http) do not send credentials (cookies) by default. If the cookies are missing from your, you can enable sending credentials by:
Vue.http.options.credentials = true;
Assuming you are using Vue-resource (this.$http)

Related

"redirect_uri_mismatch" when sending authentication code to GoogleAPI

I am having trouble with the authentication process for the GoogleAPI. In the end I want to be able to read the users steps using the GoogleFit API and then store that value in a database. Currently I'm using restdb.io and executing javascript in codehooks.
The documentation from Google that I am following can be found here, clicking on the HTTP/REST option in the code examples. At the moment I am at step 5: I have gotten the users authentication code and stored it in the database. Now I have to POST the code along with some other parameters and get the access and refresh tokens.
If the POST is successful (from what I understand) I should get back a 200-OK message that the request was valid. Google will then POST a JSON body with the access and refresh token to the redirect_uri that I have specified in my GoogleAPI credentials page and the initial request. At redirect_uri I have to handle the request and save the two values.
The problem is that I receive a redirect_uri_mismatch - Bad Request message from Google as a response when executing the request. I get it at the log.debug("ERROR HERE: " + [...]); in the code below:
async function mainFunction(){
const authCode = THIS_IS_MY_AUTHENTICATION_CODE;
try {
var answer = await postRequestToGoogle(authCode);
//do stuff with response from Google
} catch (error) {
//do stuff
}
}
async function postRequestToGoogle(authCode){
//body for the request
const params = "code=" + authCode + "&" +
"client_id=THIS_IS_MY_CLIENT_ID" + "&" +
"client_secret=THIS_IS_MY_CLIENT_SECRET" + "&" +
"redirect_uri=THIS_IS_MY_REDIRECT_URI" + "&" +
"grant_type=authorization_code";
try{
const result = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: params})
.then(res => {
log.debug("ERROR HERE: " + JSON.stringify(res.json()));
return res.json();
})
//return JSON back main function
return result;
}catch(error){
//do stuff
}
}
I looked up the error message and tried some things:
Copy and pasted multiple different Authorized redirect URI from the GoogleAPI credentials page into the code to make sure that there is no problem with
http/https
www/no www
trailing slashes
typos or capitalization
Waited for changes to be processed by Google (read that it can more than 30min)
Changed all the other parameters to see if the redirect_uri is actually the problem
If code is changed the message is invalid_grant - Bad Request
If client_id is changed the message is invalid_client - The OAuth client was not found
If client_secret is changed the message is invalid_client - Unauthorized
If the grant_type is changed the message is unsupported_grant_type - Invalid grant_type
That's why I think the issue is the redirect_uri, but it's unclear to me how since I copy&pasted it. Something that came to mind was that maybe the value of redirect_uri gets changed when it's read by Google? Or maybe when the request is being put together? Do some characters have to be replaced?
I tried to analyze the request with Wireshark but didn't think about the fact that it's HTTPS so I would have I would have to decrypt it.. Is that something I should look into?
Thank you for taking the time to read all of this! If you have any advice please let me know :)
Update 16.11.20:
I have created a new OAuth 2.0 Client ID and used the new id/secret in my request. The resulting message the same as before. I will wait and try again tomorrow to see if maybe Google needs some more time. Then I'll try to delete all current IDs and start with a fresh GoogleAPI project.
Update 19.11.20:
Creating a new OAuth 2.0 Client ID did not resolve my problem, neither did creating a whole new GoogleAPI project and adding those credentials into the request. I am in contact with the developers of restdb.io and have asked them to add the Google Auth Library: Node.js Client to the list of supported Node.js packages. Hopefully that will help, I will give it a try as soon as it can be used :)
Update 02.12.20:
No progress so far, but I'm optimistic that the developers will add the package soon. I will post a final update as soon as I am done with this project.

Angular 5 InMemoryWebAPI - How to simulate CRUD with HTTP Verbs?

In working with the Angular docs / tutorial on the in-memory web api, I want to return some JSON values that indicate the success or failure of a request. i.e.:
{success:true, error:""}
or
{success:false, error:"Database error"}
But, the code in the example for the in-memory-data.service.ts file only has the one method: createDb().
How do update that service code to respond to a PUT/POST/DELETE request differently than a GET?
Note: In real-life / production, the backend will be PHP, and we can return these values any way we want (with the correct status codes). This question is specifically directed at making the In Memory Web API mock those responses.
Example:
Executing:
return = this.http.post(url,someJsonData,httpHeaders);
I would want return to be:
{success:'true',id:1234} with an HTTP Status code of 200.
Later, to delete that record that was just created:
url = `/foo/` + id + '/'; // url = '/foo/1234/';
this.http.delete(url);
This wouldn't really need a JSON meta data response. An HTTP Status code of 200 is sufficient.
How do update that service code to respond to a PUT/POST/DELETE
request differently than a GET?
The server will always respond to the requests that you have made. So if you fire an Ajax request it may be one of the known HTTP Methods (like POST, GET, PUT...). Afterwards you'll wait for the answer.
/** POST: add a new hero to the database */
addHero (hero: Hero): Observable<Hero> {
return this.http.post<Hero>(this.heroesUrl, hero, httpOptions)
.pipe(
catchError(this.handleError('addHero', hero))
);
}
/** GET: get a new hero from the database */
getHero (heroId: number): Observable<Hero> {
return this.http.get(this.heroesUrl + '/' + heroId)
}
I found the answer I was looking for: It's HttpInterceptors.
This blog post and the corresponding github repo demonstrate exactly how to simulate CRUD operations in Angular 2/5 without having to setup a testing server.

Generate Google ReCaptcha from a local website

I'm crawling a website using the python requests module. A form on this website requires to solve a ReCaptcha. I've managed to recreate this ReCaptcha on a local website with the same site-key. If I solve the ReCaptcha on my local website and get the 'g-captcha-response' key, would I be able to post this key to the original website? If so, would this work or is Google requiring other informations other than the response key?
# I get the response key from my local website
CaptchaKey = response-key
# I post the response key on the original website
request.post(SubmitURL, data={'g-captcha-response': CaptchaKey}
Would this work? If so, how do I check if the request has been successfully posted?
Google captcha key won't be enough. You should consider a method with selenium+requests.
first part:
from selenium import webdriver
driver = webdriver.Chrome("C:\chromedriver.exe")
driver.get('desiredurl')
#somesleep/waittill element/anything to wait till you solve the recaptcha
cookies = driver.get_cookies()
part 2
session = requests.Session()
for cookie in cookies:
session.cookies.set(cookie['name'], cookie['value'])
payload = { 'username' : '',
'password' : '',
'g-captcha-response': CaptchaKey}
login = session.post('DESIREDURL', data = payload)
This method should work

REST service cache strategy with AngularJS

I have an AngularJS application and I want to cache the REST service responses. I found some libraries like angular-cached-resource which can do this by storing the data into the local storage of the web browser.
But sometimes I do some POST / PUT / DELETE REST calls and then some of the REST previously cached service responses need to be performed again. So it seems that it is possible to delete the cached responses then and the call will be sent to the server next time.
But what about if the server sends me in HTTP Header some values like the expires or the etag? I have to read the HTTP Header and react by myself or is there a library in AngularJS which can also handle this?
So if I should hit the server and not read the cache of the local storage is dependent on the HTTP Header Cache fields and if there are any PUT / POST / DELETE calls which have the response that for example "reload of every user settings element" are needed. So I have to take this response and create a map which tells me that for example REST services A, C and F (user settings related stuff) needs to hit the server again next time when they are executed or if the Cache expires from the HTTP Headers.
Is this possible with an AngularJS library or do you have any other recommendations? I think this is similar to Observer or PubSub Pattern, isn't it?
One more thing: Is it also possible to have something like PubSub without using a cache / local storage (so also no HTTP Header Cache controls)? So I can not call the REST service, because then it would hit the server, which I do not want in some circumstances (response from a previous REST call which returns me the event "reload of every user settings element").
You can try something like this.
app.factory('requestService', ['$http', function ($http) {
var data = {};
var service = {
getCall : funtion(requstUrl, successCallback, failureCallback, getFromCache){
if(!getFromCache){
$http.get(requstUrl)
.success(function(data){
successCallback(data);
data.requstUrl = data;
})
.error(function(){
failureCallback(data);
})
}else{
successCallback(data.requstUrl);
}
},
postCall : function(requestUrl, paramToPass, successCallback, failureCallback, getFromCache){
if(!getFromCache){
$http.post(requestUrl, paramToPass)
.success(function(data){
successCallback(data);
data.requstUrl = data;
})
.error(function(data){
failureCallback(data);
})
}else{
successCallback(data.requstUrl);
}
}
};
return service;
}]);
This is just a simple code I wrote to implement your concept. I haven't tested it and is all yours.

Send user details (session token) within every AJAX requests (Sencha Touch 2)

i am building a Sencha Touch 2 Application with userspecific datasets.
Architecture of the App:
Sencha Touch App <=====> Java Server backend with REST Services
( many AJAX requests =) )
What i actually have is:
Login the user with username/password
The app gets initialized and the loginform comes into play. After submitting the form as a AJAX request, the server backend checks the userdata and calls the client callback function.
And what i want to do is:
The callback function should
create a cookie with the sessiontoken or
store the sessiontoken within the localstorage (http://docs.sencha.com/touch/2-0/#!/api/Ext.data.proxy.LocalStorage) or
store the sessiontoken within js variable
Okay, shouldn't be the problem.
But how can i achieve the following:
Most of the data is specific for one user and should be returned by the REST service if needed (by clicking on the navigation,...). How can i send the sessiontoken (see above) within every AJAX request - so the server can provide the suitable datasets (assuming the token is valid)?
Send cookies within AJAX requests
I have already read that cookies gets automaticly added to the request if the url is on the same space, right? The Java Server is on the same domain (localhost:8080) but the cookies aren't available - instead of requests on urls like 'app.json'. I thought that cross-domain-requests are really domain specific?
Send paramaters within AJAX requests
Because the cookies aren't avi i thought about the possiblity of 'manually' adding parameters to the ajax requests. The App will contain many AJAX requests and thats why i dont want to add the token manually - i tried to override the requests function of Ext.Ajax but i failed ;-( :
(function() {
var originalRequest = Ext.data.Connection.prototype.request;
Ext.override(Ext.data.Connection, {
request : function(options) {
alert("Do sth... like add params");
return originalRequest.apply(this, options);
}
});
})();
ERROR:
Uncaught Error: [ERROR][Ext.data.Connection#request] No URL specified
I also tried to add a listener
Ext.Ajax.add({
listeners : {
beforerequest : function( conn, options, eOpts ){
alert("Do sth... like add params");
}
}
});
ERROR:
Uncaught TypeError: Object [object Object] has no method 'add'
Any idea about how i can add the token?
Or any better way of handling these case?
Thanks!
Finally i successfully used:
function addAjaxInterceptor(context)
{
Ext.Ajax.on('beforerequest', function(conn, options, eOptions)
{
// add the param to options...
}, context);
}
Executed from the app (=> addAjaxInterceptor(this)).
But the following solution is more suitable for my situation i think:
Ext.Ajax._defaultHeaders = {
// params as json
};
(Cause Ext.Ajax is a singleton object and i dont change the params for every request)

Categories

Resources