Implementing CORS in Google App Engine server - javascript

I have an app on GAE that checks if a user is logged in to Google using the Google Users Service.If the user isn't logged in, it is supposed to redirect to the login page from Google.
Here is the code that attempts to do this:
class RegistrationHandler(webapp2.RequestHandler):
def post(self):
user = users.get_current_user()
if user:
username = self.request.get(user.nickname())
callback = self.request.get('callback')
member = Member.get_by_id('username')
if member:
self.response.write("A member with that id already exists")
else:
m_username=self.request.get('username')
m_name=self.request.get('name')
member = Member(id=m_username, username=m_username, member_name=m_name)
member.put()
if callback:
self.response.write(callback + '(' + member.toJSON() + ')')
else:
self.response.write(member.toJSON())
else:
self.redirect(users.create_login_url(self.request.uri))
However,when i make the request from my jQuery Mobile app, i get the error message:
XMLHttpRequest cannot load http://localhost:18090/. No 'Access-Control-Allow-Origin'
header is present on the requested resource. Origin 'http://localhost:63343' is
therefore not allowed access.
So i did a little research and found that this was caused by a CORS failure.
So i dug further and found some information on this website which says to use this piece of code:
class CORSEnabledHandler(webapp.RequestHandler):
def get(self):
self.response.headers.add_header("Access-Control-Allow-Origin", "*")
self.response.headers['Content-Type'] = 'text/csv'
self.response.out.write(self.dump_csv())
on the server.
Being a newbie, i am not exactly sure how to implement this.The other suggestions which are in javascript are a bit more complicated.

If what the website outlines is sufficient then add the line
self.response.headers.add_header("Access-Control-Allow-Origin", "*")
inside your post handler and inside your if user condition.
Of course this needs to be done in conjunction with the appropriate javascript at the client end. http://www.html5rocks.com/en/tutorials/cors/

Related

403 Forbidden in Vue.js + CodeIgniter 4

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)

"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.

DOMException: Blocked a frame with origin "http://localhost" from accessing a cross-origin frame

I have two web application on different domain.
Web App1
Web App2
My Final goal is as par below.
I have found the tutorial to login with Google account API in Asp.net MVC - 5.
https://tutorialslink.com/Articles/How-to-login-with-Google-account-API-in-Aspnet-MVC---5/18
By using same concept I am trying to do below things
Open WebApp2 from WebApp1
From WebApp2 on Apply event redirect to specified URL consist of URL + required data in encrypted format.
From WebApp1 by continuously checking for the updated URL and accordingly display the data on WebAp1.
Close the WebApp2.
To achieve the above steps, my source code (WebApp1) as par below.
var REDIRECT = "http://localhost/Home/Test";
var webApp2 = window.open("WebApp2Url", "CrossDomain", '', true);
var pollTimer = window.setInterval(function () {
try {
if (webApp2.document.URL.indexOf(REDIRECT) != -1) {
window.clearInterval(pollTimer);
// logic to retrieve data from webApp2.document.URL
webApp2.close();
debugger;
}
}
catch (e) {
}
}, 500);
I am getting below error at code line
[if (webApp2.document.URL.indexOf(REDIRECT) != -1) {]
DOMException: Blocked a frame with origin "http://localhost" from
accessing a cross-origin frame.
Please any one can guide me to resolve above error.
I have tried with enabling CORS in WebApp2 but it didn't work.
Any idea to design WebApp2 is highly welcome.
I have got the work around for the same.
In my WebApp2 After finishing with processing I am redirect control to my WebApp1 i.e to domain1.
Reference:
How do I get around window.opener cross-domain security

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

How to combine Tornado authentication and AngularJS?

I am using the authentication system provided as an example in the tornado documentation. When I want to combine it with AngularJS - AngularJS complains about a Cross-Origin Request.
How can I combine Tornado's authentication system and AngularJS?
Authentication Handlers
class BaseHandler(tornado.web.RequestHandler):
def get_current_user(self):
user_json = self.get_secure_cookie("my_app")
if not user_json: return None
return tornado.escape.json_decode(user_json)
class AuthGoogleLoginHandler(BaseHandler, tornado.auth.GoogleMixin):
'''
The Google OAuth Handler.
The `AuthGoogleLoginHandler` redirects each accepted user
to the index /.
'''
#gen.coroutine
def get(self):
if self.get_argument("openid.mode", None):
user = yield self.get_authenticated_user()
self.set_secure_cookie("my_app",
tornado.escape.json_encode(user))
self.current_user = user
email = user.get('email')
try:
usr = models.User.objects.get(email=email)
except mongoengine.DoesNotExist as e:
# there is no user with the wished email address
# let's create a new one.
new_user = models.User()
new_user.email = user.get('email')
new_user.first_name = user.get('first_name')
new_user.last_name = user.get('last_name')
new_user.locale = user.get('locale')
new_user.save()
self.redirect(self.get_argument('next', '/'))
return
self.authenticate_redirect()
ProfileHandler
class ProfileHandler(BaseHandler):
'''
returns the username of the current user so that it can be used by the AngularJS Templates
'''
#tornado.web.authenticated
def get(self):
if not self.get_current_user():
response = json.dumps({"userdetails":"my dummy user"})
self.write(response)
# user actually exists
else:
response = json.dumps({"userdetails":self.get_current_user()})
self.write(response)
I think you need to enable a cross origin request, wiki CORS for more info:
class BaseHandler(tornado.web.RequestHandler):
def set_default_headers(self):
self.set_header("Access-Control-Allow-Origin", "http://yoursite.com")
Also, it took me a while to figure this out, but normal sessions don't work when Angular is interacting with a RESTful API. What you want is to send credentials in the HTTP Authorisation header on each request. Check this out:
http://wemadeyoulook.at/en/blog/implementing-basic-http-authentication-http-requests-angular/
Hope that helps a bit!

Categories

Resources