Where to store Laravel Passport "client_secret" in VueJS - javascript

I am a bit new to VueJS and I am using Laravel as API only and VueJS as a separate project.
In my App.vue, I have following setup:
http://api.com is my virtual host!
<script>
import axios from 'axios';
export default {
data () {
return {
}
},
created() {
const postData = {
grant_type: "password",
client_id: 2,
client_secret: 'MvEyvm3MMr0VJ5BlrJyzoKzsjmrVpAXp9FxJHsau',
username: 'mail#gmail.com',
password: '**********',
scope: ''
}
axios.post('http://api.com/oauth/token', postData)
.then(response => {
const header = {
'Accept': 'application/json',
'Authorization': 'Bearer ' + response.data.access_token,
};
axios.get('http://api.com/api/user', { headers: header })
.then(response => {
console.log(response.data)
})
})
}
}
</script>
But this file is totally visible to front-end which is not good due to security reasons.
What I did, I made a new route in Laravel as Route::post('get_client_creds', MyController#index); and then made a request from axios as:
axios.post('http://api.com/get_client_creds')
.then(response => {
this.client_secret = response.client_secret;
});
And but then I thought anyone can also access the route using Postman or may be through console using axois, so can someone give me some suggestions about where to store these secrets???
Thanks in Advance!

There are two different ways to specify config settings for vue
#1 Vue.js non-cli projects, you can use src/config.js
Create a new file src/config.js and add as following
export const API_CLIENT_ID = '123654';
To use this, try import like:
import { API_CLIENT_ID } from '../config'
// in your code
console.log(API_CLIENT_ID);
#2 For Vue CLi projects follow these steps.
You must use the .env files hold the configuration variables.
It could be structured like
.env # loaded in all cases
.env.local # loaded in all cases, ignored by git
.env.[mode] # only loaded in specified mode
.env.[mode].local # only loaded in specified mode, ignored by git
Here is how you can specify the variable.
FOO=bar
API_CLIENT_ID=123456
And you can use this as:
console.log(process.env.API_CLIENT_ID)
Please follow the documentation for more details.
https://cli.vuejs.org/guide/mode-and-env.html#environment-variables

Related

Stripe Payment element show saved card

I am using laravel with stripe payment element. I am trying to show the saved cards for the customers that we already have. I have followed the stripe docs and found how I can show it on checkout. But the problem is that I am not getting the saved cards for the customer. And instead I am facing an error on my console as:
When authenticating with an ephemeral key, you must set the Stripe-Version header to an explicit API version, such as 2020-08-27
I have checked and changed lot of versions from here:
$ephemeralKey = \Stripe\EphemeralKey::create(
['customer' => "$user->stripe_customer_id"],
['stripe_version' => '2019-11-05']
);
I changed the version to different version that I can see on my stripe dashboard:
This is my Js Initialize function:
// Fetches a payment intent and captures the client secret
async function initialize() {
// Customize the appearance of Elements using the Appearance API.
const appearance = { /* ... */ };
// Enable the skeleton loader UI for the optimal loading experience.
const loader = 'auto';
const { clientSecret, customerOptions } = await fetch("{{ route("user-create-stripe-element-payment") }}", {
method: "POST",
headers: {
"Content-Type" : "application/json",
"accept" : "application/json",
'X-CSRF-TOKEN': "{{ csrf_token() }}",
'stripe_version':"2019-11-05"
},
body: JSON.stringify({ totalCharge:total }),
}).then((r) => r.json());
elements = stripe.elements({
clientSecret,
appearance,
loader,
customerOptions
});
const paymentElement = elements.create("payment");
paymentElement.mount("#payment-element");
}
And I am also using the betas which is given in the documentation:
const stripe = Stripe("{{env('STRIPE_KEY')}}", {
betas: ['elements_customers_beta_1'],
});
But this error is not going away. And its not even populating the Payment element.
Please help me debug this or if someone has any suggestion to check what is going on here.
Thanks in advance.
You are not providing an API version in your JS here
const stripe = Stripe("{{env('STRIPE_KEY')}}", {
betas: ['elements_customers_beta_1'],
});
change the above code to
const stripe = Stripe("{{env('STRIPE_KEY')}}", {
betas: ['elements_customers_beta_1'],
apiVersion: 'Your Version Here'
});
In your case, it should be something like this
const stripe = Stripe("{{env('STRIPE_KEY')}}", {
betas: ['elements_customers_beta_1'],
apiVersion: '2019-11-05'
});
You can read more here. https://stripe.com/docs/api/versioning?lang=node
It is for nodejs but the API version override will work in the same way.

Axios get call in Vue3 not working, although curl and javascript work as expected

I'm trying to make an API call from my Vue3 app. The prepared API has an endpoint like http://localhost:8888/api/dtconfigsearch, where one needs to pass a json payload like { "Modelname": "MyFancyModel"} to get the full dataset with the given modelname. Pure get functions without a payload / a body do work from my Vue3 project to the golang backend, but I'm having problems with passing a payload to the backend.
Test with curl -> ok
$ curl -XGET localhost:8888/api/dtconfigsearch -d '{"Modelname" : "MyFancyModel" }'
{"ID":4,"Modelname":"MyFancyModel","ModelId":"96ee6e80-8d4a-b59a-3524-ced3187ce7144000","OutputTopic":"json/fancyoutput"}
$
This is the expected output.
Test with javascript ok
Source file index.js:
const axios = require('axios');
function makeGetRequest() {
axios.get(
'http://localhost:8888/api/dtconfigsearch',
{
data: { Modelname : "MyFancyModel" },
headers: {
'Content-type' : 'application/json'
}
}
)
.then(resp => {
console.log(resp.data)
})
.catch(err => {
console.log(err)
})
}
makeGetRequest()
Output
$ node index.js
{
ID: 4,
Modelname: 'MyFancyModel',
ModelId: '96ee6e80-8d4a-b59a-3524-ced3187ce7144000',
OutputTopic: 'json/fancyoutput'
}
$
Here, I also get the desired output.
Test within Vue fails :-(
Source in the Vue one file component:
onSelection(event) {
let searchPattern = { Modelname : event.target.value }
console.log(event.target.value)
console.log("searchPattern = " + searchPattern)
axios.get("http://localhost:8888/api/dtconfigsearch",
{
data : { Modelname : "Windshield"},
headers: {
'Content-type' : 'application/json',
'Access-Control-Allow-Origin': '*'
}
})
.then(response => {
console.log(response.data)
})
.catch(err => {
console.log(err)
alert("Model with name " + event.target.value + " not found in database")
})
},
Output in browser:
In the image you can see in the terminal log on the right side that the backend is not receiving the body of the API call. However, in the browser information of the call there is content in the config.data part of the object tree, which is the payload / the body. The only thing that bothers me that it is not a json object, but stringified json, although it was entered as json object. According to the documentation, the parameter name (data) in the call should be correct to hold the body content of the api call.
I've tried different header information, looked if it could be a CORS issue, what it isn't to my opinion, exchanged key data with body, used axios instead of axios.get and adapted parameter, all without success. The version of the axios library is 0.27, identical for Vue and vanilla javascript. After checking successfully in javascript, I was sure that it would work the same way in Vue, but it didn't.
Now I'm lost and have no further ideas how to make it work. Maybe someone of you had similar issues and could give me a hint? I'd be very grateful for some tipps!!

CORS No 'Access-Control-Allow-Origin' error in React app w/ Facebook

I'm a junior developer that's fairly new to using Facebook for Developers. I'm hitting a wall with the ReactJs application I'm building and could use your help!
My boss has requested a Grid representation of the Page Plugin, not the actual Plugin itself. For this project, he's requested I make and use a test 'Page' I've found that DevExtreme's Data Grid seems to be the best option in terms of the desired visual, and I'm trying to call my Facebook Page using the Graph API documentation. I know it's hitting at least the area I want it to with my console.log because it's returning the error message.
Here are the errors my browser is returning:
Access to fetch at 'https://www.facebook.com/Feeds-Tester-170107151801959/' from origin 'https://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
GET https://www.facebook.com/Feeds-Tester-170107151801959/ net::ERR_FAILED
The link you'll see referenced in my URL variable has been triple checked to be the correct link. Since I'm using NodeJS, I tried installing the CORS npm package but I'm not 100% sure where to put it to use it, I'm wondering if that's the cause of the issue?
Here's my full code snippet (I'm using VS Code, if that helps):
/*global FB*/
import React from 'react';
import { DataGrid, Editing, Scrolling, Lookup, Summary, TotalItem } from 'devextreme-react/data-grid';
import { Button } from 'devextreme-react/button';
import { SelectBox } from 'devextreme-react/select-box';
import CustomStore from 'devextreme/data/custom_store';
import { formatDate } from 'devextreme/localization';
import 'whatwg-fetch';
const URL = 'https://www.facebook.com/Feeds-Tester-170107151801959/';
const REFRESH_MODES = ['full', 'reshape', 'repaint'];
class Grid extends React.Component {
constructor(props) {
super(props);
this.state = {
fbData: null,
ordersData: new CustomStore({
key: 'OrderID',
load: () => this.sendRequest(`${URL}`, 'GET'),
}),
requests: [],
refreshMode: 'reshape'
};
this.clearRequests = this.clearRequests.bind(this);
this.handleRefreshModeChange = this.handleRefreshModeChange.bind(this);
var body = 'Reading JS SDK documentation';
FB.api('/me/feed', 'post', { message: body }, function(response) {
if (!response || response.error) {
console.log('Error occured');
} else {
console.log('Post ID: ' + response.id);
}
})
}
sendRequest(url, method, data) {
method = method || 'GET';
data = data || {};
this.logRequest(method, url, data);
if(method === 'GET') {
return fetch(url, {
method: method,
credentials: 'include',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'Access-Control-Allow-Origin': '*'
}
}).then(result => result.json().then(json => {
if(result.ok) return json.data;
throw json.Message;
}));
}
const params = Object.keys(data).map((key) => {
return `${encodeURIComponent(key) }=${ encodeURIComponent(data[key])}`;
}).join('&');
return fetch(url, {
method: method,
body: params,
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
credentials: 'include'
}).then(result => {
if(result.ok) {
return result.text().then(text => text && JSON.parse(text));
} else {
return result.json().then(json => {
throw json.Message;
});
}
});
}
logRequest(method, url, data) {
const args = Object.keys(data || {}).map(function(key) {
return `${key }=${ data[key]}`;
}).join(' ');
const time = formatDate(new Date(), 'HH:mm:ss');
const request = [time, method, url.slice(URL.length), args].join(' ');
this.setState((state) => {
return { requests: [request].concat(state.requests) };
});
}
clearRequests() {
this.setState({ requests: [] });
}
handleRefreshModeChange(e) {
this.setState({ refreshMode: e.value });
}
render() {
const { refreshMode, ordersData } = this.state;
return (
<React.Fragment>
<DataGrid
id="grid"
showBorders={true}
dataSource={ordersData}
repaintChangesOnly={true}
>
<Editing
refreshMode={refreshMode}
mode="cell"
allowAdding={true}
allowDeleting={true}
allowUpdating={true}
/>
<Scrolling
mode="virtual"
/>
<Lookup dataSource={ordersData} valueExpr="Value" displayExpr="Text" />
<Summary>
{/* <TotalItem column="CustomerID" summaryType="count" />
<TotalItem column="Freight" summaryType="sum" valueFormat="#0.00" /> */}
</Summary>
</DataGrid>
<div className="options">
<div className="caption">Options</div>
<div className="option">
<span>Refresh Mode: </span>
<SelectBox
value={refreshMode}
items={REFRESH_MODES}
onValueChanged={this.handleRefreshModeChange}
/>
</div>
<div id="requests">
<div>
<div className="caption">Network Requests</div>
<Button id="clear" text="Clear" onClick={this.clearRequests} />
</div>
<ul>
{this.state.requests.map((request, index) => <li key={index}>{request}</li>)}
</ul>
</div>
</div>
</React.Fragment>
);
}
}
export default Grid;
This is the link to the docs for the module I'm trying to reference
I'm trying to not bite off more than I can chew and just start with retrieving the data before I even think about manipulating it or sending any in return. Any insight or guidance you can provide would be greatly appreciated. Thank you!! :)
Do not use fetch with the Facebook URL, it won't let it happen on the browser, instead, use the Facebook API for everything you need to do with it
For example, instead of fetching the page, use the api with the page
FB.api('/Feeds-Tester-170107151801959', function(response) {
// ...
});
If you need to fetch the page, then you have to do it outside the browser environment or use a proxy like cors anywhere, but you can avoid that by using the Facebook API
I was also getting these error. I found that the pageId, I was using was wrong🤦‍♀️. These errors come only when your pageId is wrong or the domain is not whitelisted properly(I even tried with a ngrok url and it worked😵).
So the steps which I followed were:
In buisness.facebook.com go to inbox from sidebar and select chat plugin. [https://i.stack.imgur.com/rDk5d.png]
Click on setup to add your domain. [https://i.stack.imgur.com/exOi2.png]
Pick a setup method(standard for react/nextjs) and setup chat plugin(add language, domain, copy code and paste it). [https://i.stack.imgur.com/hDArZ.png]
You can add multiple domains. [https://i.stack.imgur.com/zGdgx.png]
You will get pageId already embedded. [https://i.stack.imgur.com/iRT13.png]
Use this code and paste it in _document.js file in nextjs. and after deploying it will work perfectly. For any confusion please let me know. Thanks, Happy Coding ☺

react and axios POST throws an Uncaught (in promise) TypeError: parsed is undefined

I'm baffled what I'm doing wrong in my code. The GET call gets resolved, but when I try to do a POST call to the same server I get an error. My POST endpoint works fine with Postman.
apiConnection.js
function get(data){
return axios.get("http://localhost:8080/api/questions",
{
params:data.payload
}, {
headers: {
'accept': 'application/json',
}
})
}
function post(data){
console.log(data.payload) //my payload is received here
return axios.post("http://localhost:8080/api/answer", {
params:data.payload
}, {
headers: {
'accept': 'application/json',
}
}
)
}
export { get, post }
Here is the error I get in the console
And here is how I make the call in react
index.js
GET (Receives response normally)
import { get, post } from "apiConnection.js"
...
componentDidMount(){
const data = {
payload: {
linkId: getSlug()
}
}
get(data).then((result) => {
this.setState({reportId: result.data.report.id});
})
}
POST (Throws error)
vote(userVote){
const data = {
payload: {
reportId: this.state.reportId,
}
}
post(data).then((result)=>{
this.state.questions[this.state.currentQuestion].vote = userVote
});
}
I have found the culprit of the issue but if someone can add more information about it, it might be helpful for others.
In my question, for brevity, I changed the request URL from imported constants to hardcoded links.
In my code, I have a variable for both GET and POST
return axios.post(apiEndpoints[data.ep], data.payload)
I import the endpoint variables like so
import * as apiEndpoints from './apiEndpoints';
apiEndpoints.js
const server = 'http://localhost:8080/'
const api_version = 'api/'
const base_url = server+api_version;
export const EP_QUESTIONS = base_url+'questions';
export const EP_ANSWER = base_url+'answer';
For some unknown reason EP_ANSWER throws the error even though I'm not making a typo when I define data.ep (data.ep has EP_ANSWER, which
I checked a million times)
The solution was to just change EP_ANSWER to EP_ANS and everything worked as expected.
No idea why this is the case. It might be some global variable or a reserved word.
Just came across this and noted #Ando's response.
So, knowing that I first tried a hard coded URL, it worked.
I then successfully did url.toString() and it worked.
Not sure why but Javascript seems to treat a an object string differently than a true string.

callApi with Login to access .json File - vuejs

i want to access a .json file via link.
when i type in the link to my json file in my browser, it asks for credentials (username + password) which i know.
i want to write the credentials in the code, so i dont have to log in manually anymore,
OR
get a message to log in with my credentials when the website is trying to fetch the data from the json file.
of course if there are other possibilities to access the json other than a callApi method you're welcome. :)
present code without authentication and with a local file:
<script>
import jsonData from '../../static/json/test.json'
export default {
name: 'dash',
data() {
return {
data: ''
}
},
mounted() {
this.fetchData()
},
methods: {
fetchData() {
this.callApi()
.then((responseData) => {
this.data = responseData;
})
},
callApi() {
return Promise.resolve(jsonData)
}
}
}
</script>
In case you are using basic authentication you can add your username and password in the beginning of the url separated by a colon. So an example url would be https://username:password#www.example.com/
Note that this is not a good practice and should not be used in production.

Categories

Resources