I managed to get Reddit OAuth to work and it is getting redirected to my homepage.
And I am getting a URL like http://localhost:3000/?state=XEA12&code=6p4pAyle2EWGVwIBlFJ6ERXjxKg
Now, when I try other APIs like /api/me. I am not able to get it working. I have also set the scope of my app to identity.
Here is the code snippet that I wrote:
import axios from "axios";
import useSWR from "swr";
const link = "https://www.reddit.com/api/v1/me";
const config = {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: "bearer 6p4pAyle2EWGVwIBlFJ6ERXjxKg",
},
};
const fetcher = (url) => axios.get(url, config).then((res) => res);
export default function Home() {
const { data, error } = useSWR(link, fetcher);
if (error) return <div>failed to load </div>;
if (!data) return <div>loading...</div>;
return <div>{JSON.stringify(data)}</div>;
}
Can you please tell me what I am doing wrong? Is it because of the headers or do I need to pass something else?
According to the documentation you need to retrieve access_token first, by using code param. Here is how to do that: https://github.com/reddit-archive/reddit/wiki/OAuth2#retrieving-the-access-token
Then you can use that access_token in a bearer auth. There is another note: API requests with a bearer token should be made to https://oauth.reddit.com, NOT www.reddit.com. Hope it will help
Related
I am new to using Axios configuration. **So I am wondering if it is possible to set axios header dynamically?**
Because the end points I am calling right now need a Authentication and different authentication for different api, so I want make a change to the created axios instance’s header when token is expired and with different URL.
Here is my current code:
in config.js
import axios from 'axios'
// to get Authorization for api_1
const {access_token_1} = axios.get('url/access_token_1')
// to get Authorization for api_2
const {access_token_2} = axios.get('url/access_token_2')
export const instance = axios.create({
headers: { Authorization: `Bearer ${access_token_1}` },
})
My Api_1 and 2 call
//Api_1
export const getCountry = async (country: string) => {
const response = await instance.get(
`/sas/${country}`
)
return response.data
}
//Api_2
export const getCity = async (city: string) => {
const response = await instance.get(
`/sps/${city}`
)
return response.data
}
I know header can be set again by certain method, but how could I set it again only when it’s expired and set the instance with right authentication for certain Api
Have a look at this documentation, you can create/update headers and pass them to your axios instance. I think this examples might help a little
axios.defaults.baseURL = 'https://api.example.com';
// Important: If axios is used with multiple domains, the AUTH_TOKEN will be sent to all of them.
// See below for an example using Custom instance defaults instead.
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
const options = {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: qs.stringify(data),
url,
};
axios(options);
axios.get('https://example.com/getSomething', {
headers: {
Authorization: 'Bearer ' + token //the token is a variable which holds the token
}
})
I'm scratching my head at this problem, I'm implementing Instagrams basic display API using Wix's new editor-x. My code works if I run it on the client side, I get an access token, however it doesn't when I import the getAccessToken function from the server side, the function runs but I get an invalid auth code.
I think there maybe an issue passing the code variable?
frontend code:
import wixLocation from 'wix-location'
import {getAccessToken} from 'backend/instagram'
let query = wixLocation.query; //get auth code from URL param
let code = query.code
console.log(code) //check code is correct
if(code){
const token = await getAccessToken(code) //request accesstoken
console.log(token) //log token
}
backend code:
import {fetch} from 'wix-fetch'
export async function getAccessToken(code) {
const url = "https://api.instagram.com/oauth/access_token"
const options = {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: `client_id=id&client_secret=secret&grant_type=authorization_code&redirect_uri=uri&code=${code}`
}
try {
const data = await fetch(url,options)
const token = await data.json()
return token
} catch(error) {
return error
}
}
I have one api.js which exports by default an axios.create() instance:
import axios from 'axios'
import Cookies from 'js-cookie'
const api = axios.create({
baseURL: process.env.VUE_APP_API_URL,
timeout: 10000,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${Cookies.get('Token')}`,
Organization: Cookies.get('Organization'),
Company: Cookies.get('Company')
}
})
export default api
Then I import this in multiple files like this:
//api/users.js
import api from './api.js'
const methods = {
postUser (params) {
return api.post('/users', params)
},
getUser (id) {
return api.get('/users/' + id)
}
}
export default methods
However there will be some functions that should update the Cookies Organization and Company and I was wondering if is possible to update the default api instance and automatically update it in all imports that use it. I know a simple page refresh would work but I'm building a SPA and I would like to prevent screen to be manually refreshed.
You can add the headers dynamically, that way the cookies will be read on every request.
import axios from 'axios'
import Cookies from 'js-cookie'
const api = axios.create({
baseURL: process.env.VUE_APP_API_URL,
timeout: 10000,
// Static headers
headers: {
'Content-Type': 'application/json',
},
transformRequest: [function (data, headers) {
// You may modify the headers object here
headers['Authorization'] = `Bearer ${Cookies.get('Token')}`
headers['Organization'] = Cookies.get('Organization')
headers['Company'] = Cookies.get('Company')
// Do not change data
return data;
}],
})
export default api
I would suggest to read about interceptor for axios. (https://github.com/axios/axios#interceptors)
A very basic example would be the following.
Lets assume your webservice would return a response http status 401 header.
You'd intercept the response with the following:
// Add a response interceptor
axios.interceptors.response.use(function (response) {
// happy case its 2XX
return response;
}, async (error) => {
if (error.response.status === 401) {
// do some logic to retrieve a new JWT or Cookie.get()
const jwt = Cookies.get('Token');
const config = error.config;
config.headers['Authorization'] = `Bearer ${jwt}`;
}
return await axios.request(config);
});
The next request will then have an authorization header attached to the request header.
I am pretty new to CORS. I am building a React App which simply posts data to a backend API. According to the API documentation I have to send a BASIC Authentication Header along with the request which is exactly what I am doing. The request works just fine when I send it through POSTMAN. But when I make the same request from my APP it says Invalid API Key. Below is my code:
App.js:
import React from 'react';
class App extends React.Component{
state = {
data: 'data'
};
handleClick = async () =>{
const res = await fetch('https://myapi.com/post',{
method: 'POST',
body: JSON.stringify({tp:'0'}),
mode: 'cors',
headers: {
content-type:'application/x-www-form-urlencoded',
Authorization : 'Basic ' + new Buffer('username:password').toString(base64)
}
});
const data = await res.json();
this.setState({data});
}
render() {
return(
<div>
<p>{this.state.data}</p>
<button onClick={this.handleClick}>Post</button>
</div>
);
}
}
I looked into the issue and found out that the headers are not being set when sending the request. When further digging into it I found out that the above request is not a simple request and hence the browser makes a preflight OPTIONS request to server. I do not know how the server is handling the requests but I think the server is not configured to handle the preflight OPTIONS. I might be wrong. I do not have any access to the server code. The same request through CORS Anywhere proxy and POSTMAN client is working fine but not while using the actual app. I used create-react-app to setup the boilerplate.
All I get is an Invalid API Token Error while sending request through the app.
Any help on how to get the headers through to the server would be appreciated.
According to another post, you might want to wrap the Authorization header in a Headers-object. I guess you should not really pay attention to the OPTIONS-request, that request shouldn't contain any user credentials and the server shouldn't really look for any credentials on a OPTIONS-request, more info.
What happens if you make the following changes (don't forget to npm install base-64).
import React from 'react';
const base64 = require('base-64');
class App extends React.Component{
state = {
data: 'data'
};
handleClick = async () => {
const headers = new Headers();
headers.append("Authorization", "Basic " + base64.encode("user:password"));
const res = await fetch('https://myapi.com/post',{
method: 'POST',
body: JSON.stringify({tp:'0'}),
mode: 'cors',
headers: headers
});
const data = await res.json();
this.setState({data});
}
render() {
return(
<div>
<p>{this.state.data}</p>
<button onClick={this.handleClick}>Post</button>
</div>
);
}
}
I want to consume an Express REST API that requires a valid json web token for some routes. Due to the fact I have to pass the token from the localstorage everytime I wanted to create an "Axios config file".
My file http.js contains the following code
import Vue from "vue";
import axios from "axios";
const devInstance = createInstance("http://localhost:3000");
devInstance.interceptors.request.use(config => {
console.log(config);
return config;
}, err => {
console.log(err);
return Promise.reject(err);
});
devInstance.interceptors.response.use(res => {
console.log(res);
return res;
}, err => {
console.log(err);
return Promise.reject(err);
});
const productionInstance = createInstance("http://www.myApi.com");
function createInstance(baseURL){
return axios.create({
baseURL,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${localStorage.token}`
}
});
}
Vue.prototype.$http = devInstance; // Check debug/build mode
within my main.js I import this instance once
import http from "./http.js";
and from now on I can use this.$http to get the global axios instance without importing it.
When consuming the API localStorage.token returns undefined because it is not set when creating the instance.
How can I keep this Authorization attribute updated without passing in the token manually each time?
I think you should write a request interceptor that adds the Authorization header to all requests.
devInstance.interceptors.request.use((config) => {
config.headers.Authorization = `Bearer ${localStorage.token}`;
return config;
}, (error) => Promise.reject(error));
This way you will always get the currently stored token.
You should create a timer and an async update for that Authorization field. Either a separate component that handles that, or a timer and async method on that component (not sure if you can do this with Vue though).
Hope it helps.
Cheers