Server's location is being sent instead of user's location - ruby-on-rails

I have the following stack:
Rails API (backend)
Next.js (frontend)
In my Rails API, I am tracking where the request is coming from such as ip, user_agent, city, country, latitude, and longitude.
But the problem is that, instead of the user's data, it's the server's data that is being sent.
In my Next.js app, I use https://nextjs.org/docs/api-routes/introduction, since the access_token for the API is stored in the session. And I don't want to expose it to the client.
So the process would be, from React, I will make a POST request to /api/process/ of Next.js API endpoint. Then in /api/process I will take the access_token from the session and make a request to Rails API.
Since the Next.js API endpoint is the one made the request to Rails API. My Rails API stores the location of the frontend server instead of the actual user's info.
Pseudocode:
In React Frontend:
fetch('/api/process', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ some: 'data' })
})
In pages/api/process.js:
export default function handler(req, res) {
fetch(RAILS_API_ENDPOINT, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${req.session.token}` // attach token here
},
body: req.body
})
}
Is there any workaround for this? I don't seem to want to expose the access_token in the client and make the request there to the Rails API directly.

You've set up a proxy API, as a result the Rails server knows nothing about the FE client because theres a layer in between. So there are 2 options:
Set up the FE client to call rails directly (which you said you don't want to do).
Forward this FE client information as part of either headers or in the payload to the rails API. From there the Rails API can then do whatever it wants with this data.

Related

401 Unauthorized - Chrome App Oauth to invoke Google Cloud Functions

I'm following this: https://developer.chrome.com/apps/tut_oauth
But it doesn't work. When I invoke Cloud Function, I get 401 error. The Authorization: Bearer "access-token" is added in the request header. Although another question here[1] states that ID_TOKEN should be used. Which I tried via curl but have the same 401 error.
chrome.identity.getAuthToken({interactive: true}, function(token) {
var dat = {
"user_email":email_id,
"user_id":user_id
};
$.ajax({
type: "POST",
data:dat,
dataType: 'json',
url:str,
contentType: "application/json",
error: function (xhr, status, error) {
console.log(xhr)
}, success: function (data, status, xhr) {
console.log('Success!' +data + status);
},
headers:{
'x-goog-project-id': 'xxxxxxxxxxxxx',
'Authorization': 'Bearer ' + token,
'Content-Type':'application/json',
'Accept': 'application/json'
}
});
});
[1] Why doesn't granting 'allAuthenticatedUsers' member the 'Cloud Functions Invoker' role work for google cloud functions?
The tutorial that you mentioned used "access-token" to accesses a user's Google contacts using the Google People API and the Chrome Identity API.
If you want to access a Google Cloud Function which does not Allow unauthenticated invocations you have to use an ID_TOKEN.
For testing you can create a service account with --role="roles/cloudfunctions.invoker", then create a key.json file and export the GOOGLE_APPLICATION_CREDENTIALS env variable link
Finaly you can use:
curl "https://us-central1-your-project.cloudfunctions.net/yourfunction"
# Error 403 (Forbidden)
curl "https://us-central1-your-project.cloudfunctions.net/yourfunction" -H "Authorization: bearer $(gcloud auth print-identity-token)"
#Success
I gave up on this as there is no direct solution to invoke Cloud function using oauth in Chrome Apps. The alternative solution that worked is to authenticate via API key. That is using Cloud Function with Cloud Endpoints.
I followed the logic here: https://medium.com/#akash.mahale/triggering-google-cloud-functions-with-cloud-endpoints-and-api-key-857e94a8a3aa
But just need to take note that rotation of API keys should be done regularly and automatically..

AADSTS90014: The request body must contain the following parameter: 'grant_type'

I am trying to send a post request to receive my access token from https://login.microsoftonline.com/common/oauth2/v2.0/token. When I tried this in my REST client, it works, but when I try to integrate it to my app, it sends me a error 400 Bad Gateway, with the message AADSTS90014: The request body must contain the following parameter: 'grant_type'. I tried searching for answers, and found out that I need to implement headers in my post request, so I did that, but it still won't work. Any ideas?
Http Imports:
import { HttpClient, HttpHeaders, HttpRequest } from '#angular/common/http';
Call to post request:
var url=this.outlook_authentification_endpoint+"token";
var query_parameters=JSON.stringify({grant_type:"authorization_code", client_id:this.outlook_client_id, code: this.outlook_user_code, client_secret: this.outlook_secret_key, redirect_uri: this.outlook_redirect_uri});
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded'
})
};
this.query_service.postOutlook(url, query_parameters, httpOptions, (data)=>
{
console.log(data);
});
Call to the post function:
public postOutlook(url, query, headers, callback)
{
this.operation_pending=true;
this.http_client.post(url,query, headers).subscribe((data)=>
{
this.operation_pending=false;
callback(data);
});
}
Can anyone see where my error is?
You are using wrong OAuth2 flow (the way of getting tokens). You are using the Auth code grant, which cannot be used in browser applications, because you would have to keep your client secret in JavaScript, which means make it public. So you cannot access the /token endpoint either.
You should use the Implicit grant, which is designed for browser applications. Then you get tokens right into your Angular application without the need of going to the /token endpoint.

Recieving 400 bad request when trying to exchange authorization code with oauth 2 tokens

I'm trying to connect to an rss api provider 'Inoreader' and I'm using react native. I am able to get the authorization code but when I submit a post request for exchanging with tokens, I get 400 bad request. The response text is undefined. I checked and all their parameters are matching with my app's. I have tried.
This is their documentation: https://www.inoreader.com/developers/oauth
fetch('https://www.inoreader.com/oauth2/token', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Host': 'www.inoreader.com',
'Content-length': '217',
'User-Agent': navigator.userAgent,
'Content-type': 'application/x-www-form-urlencoded'
},
body: JSON.stringify({
'code':`${this.state.auth_code}&redirect_uri=${this.state.gizmos}&client_id=${this.state.userId}&client_secret=${this.state.userKey}&scope=&grant_type=authorization_code`
})
})
.then((res) => {
this.setState({
userName: res.access_token
});
console.log(res.status);
});
I see three problems in your code
You have a fixed Content-length value (217) from the Inoreader example. This way, the server reads just 217 characters of the request and the rest is discarded if the request is longer.
The request Content-type is urlencoded, but you probably don't URL encode the values. You can use the [encodeURIComponent()][1] function to do it.
The /token endpoint requires you to send a client secret, but your application cannot keep it safe, so the secret can easily get compromised. As they write in the guide, the request should be done from a backend. Or you can ask them to support OAuth2 for native apps.

Authorization Token is not being received by Django server from ios - React native

When I do a request using Fetch (in ios) from a react native app with a Django backend, the header Authorization Token is not being received, but the others headers are.
I try using nc -l 8090 just to check out if the app was correctly sending the header and it was there. Also, this just happens in the ios version, the android one works just fine.
At checking the Django backend, the Authorization Token is not being received ( I printed what i got in the authentication.py file )
I put the fetch code here:
let response = fetch('http://xxx.xxx.x.xxx:8000/' + 'users', {
method: 'GET',
headers: {
'content-type': 'application/json',
'x-app-key': xxxxxxxxxx,
'Authorization': 'Token xxxxxxxxxxxxxxxxxxxx'
}
}).then((response) => {...}
The error message that im getting in the response is "403 django standar not valid authentication".
I'm not using OAuth2. Any other information that could provide, please let me know and thank you for any help.
Something weird that I just noticed is that when I use the nc cmd (lc -l 8000), at the port 8000, it has the same behavior. The authorization token is not being received.
I solved my problem added a slash at the end of the URL.
let response = fetch('http://xxx.xxx.x.xxx:8000/' + 'users/', {
method: 'GET',
headers: {
'content-type': 'application/json',
'x-app-key': xxxxxxxxxx,
'Authorization': 'Token xxxxxxxxxxxxxxxxxxxx'
}
}).then((response) => {...}
I had a variation of this issue with a backend using the laravel framework. I finally resolved it by using the following in the .htaccess file of the public folder.
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
Combined with one other important factor in my case, losing the trailing slash from the url in the fetch.
Hope this helps, either way. Good luck.

Encrypt (or hide) an auth token being sent through AJAX request

I'm making an ajax request to an API which requires an auth token to be sent in the HTTP headers. Here's what I've got:
$.ajax({
type: 'GET',
url: 'http://foo.com/bar.json',
headers: { "Authorization": 'Token token=' + SECRET_KEY },
dataType: 'json',
...
}
Thing is I don't want SECRET_KEY to be publicly visible if someone were to view the javascript file. Can't seem to find a good workaround, but can't imagine no one else has encountered this... This request is being sent to a Rails app FWIW.

Resources