I'm working on a Laravel application that uses React and Redux on the client side, with the React preset and Mix. I've decided to try out GraphQL for the API rather than the usual REST API approach and it's working OK so far. However, I've now got stuck.
I'm using Apollo as my HTTP client since it's built for working with GraphQL. In the past I've used JWT Auth for securing APIs, so naturally I've gone for that approach here too, since implementation is just a case of adding an appropriate header. I've followed the instruction on setting headers with Apollo, but the headers aren't getting set. Here's the JS file in question:
import LinkList from './components/LinkList';
import React from 'react';
import ReactDOM from 'react-dom';
import {Container} from './container';
import {createStore} from 'redux';
import reducer from './reducer';
import {Provider} from 'react-redux';
import {fromJS} from 'immutable';
import ApolloClient from 'apollo-boost';
import gql from 'graphql-tag';
import { createHttpLink } from 'apollo-link-http';
import { setContext } from 'apollo-link-context';
import { InMemoryCache } from 'apollo-cache-inmemory';
const httpLink = createHttpLink({
uri: window.initialData.graphql_route
});
const authLink = setContext((_, { headers }) => {
const token = window.initialData.jwt;
// return the headers to the context so httpLink can read them
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : "",
}
}
});
const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache()
});
client.query({
query: gql`{
links {
id
title
link
}}`
}).then(result => console.log(result));
const store = createStore(
reducer,
fromJS(window.initialData),
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
if (document.getElementById('list')) {
ReactDOM.render(
<Provider store={store}>
<Container />
</Provider>,
document.getElementById('list')
);
}
I populate window.initialData in the view, and that contains the necessary data, including the JWT token as window.initialData.jwt. Setting a breakpoint inside the definition of authLink does nothing, implying that it never gets called.
Any idea what's gone wrong? I've followed the examples in the documentation pretty closely, so all I can think of is that they might be put of date.
Info: Don't save your token in the localStorage Is it safe to store a JWT in localStorage with ReactJS?
You are using the ApolloClient from 'apollo-boost', but your token configuration is for another ApolloClient, the { ApolloClient } from 'apollo-client'.
If you want to save the token using the ApolloClient from apollo-boost:
const client = new ApolloClient({
uri: ...,
request: async operation => {
const token = localStorage.getItem('token');
operation.setContext({
headers: {
authorization: token ? `Bearer ${token}` : ''
}
});
}
});
Apollo Boost migration
Related
I'm working on my very first nextjs application. I'm using an axios instance to handle my calls to backend
export const httpClient = axios.create({
baseURL: `${process.env.BASE_URL}`,
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
});
I'm also using next-auth to handle my authentication and authorization
const callbacks = {
async jwt(token, user) {
if (user) {
token.accessToken = user.access_token;
}
return token;
},
async session(session, token) {
session.accessToken = token.accessToken;
return session;
},
};
The call to the authentication endpoint is working correctly. If I console.log() the api response I can see the returned JWT token.
I'm now trying to attach that JWT token to every axios request but the call await getSession() is always null. I wrote following request interceptor
httpClient.interceptors.request.use(
async (config) => {
const session = await getSession();
if (session) { // this never evaluates to true. Session is always `null`
console.log(session);
config.headers.Authorization = `Bearer ${session?.accessToken}`;
}
return config;
},
(error) => {
return Promise.reject(error);
},
);
Following the docs, I wrapped my _app.js <Component> with
<Provider session={pageProps.session}>
<Component {...pageProps} />
</Provider>
Any ideas what I could try next?
Edit:
I call const [session, loading] = useSession(); on another part of the code (in the nextjs frontend) and there everything seems to be working
The problem is that if the axios call is made on the server side, then the interceptor will also be executed on the server side.
If that is the case, when calling getSession() on the server side, you also have to pass it the request or the context (see the note at the bottom of the manual entry for getSession)
I have been fiddling with moving a tutorial I did in Vue to Nuxt. I have been able to get everything working, however I feel I'm not doing it the "proper way". I have added the Nuxt axios module, but wasnt able to get it working, so I ended up just using the usual axios npm module. Here is my store:
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(Vuex)
Vue.use(VueAxios, axios)
export const state = () => ({
events: []
})
export const mutations = {
setEvents: (state, events) => {
state.events = events
}
}
export const actions = {
loadEvents: async context => {
let uri = 'http://localhost:4000/events';
const response = await axios.get(uri)
context.commit('setEvents', response.data)
}
}
I would like to know how to re-write this store using the #nuxtjs/axios module. I also didnt think I'd need to import vuex here, but if I dont, my app doesn't work.
Thanks for any help!
Using the #nuxtjs/axios module, you can configure axios inside your nuxt.config.js:
// nuxt.config.js
export default {
modules: [
'#nuxtjs/axios',
],
axios: {
// proxy: true
}
}
You can use it inside your store (or components) with this.$axios
// In store
{
actions: {
async getIP ({ commit }) {
const ip = await this.$axios.$get('http://icanhazip.com')
commit('SET_IP', ip)
}
}
}
I have an API that has a JSON file, I gonna get information from that with Axios but it has Token and I don't know how can use it anybody can help me?
here it's API
https://api.nytimes.com/svc/movies/v2/reviews/picks.json
I try this but its didn't work and gave me error 401 and this
GET https://api.nytimes.com/svc/movies/v2/reviews/picks.json%E2%80%AC%E2%80%AC 401 (Unauthorized)
<script>
import axios from "axios";
export default {
data() {
return {};
},
methods: {
async getDataFromApi() {
const res=await axios.get("https://api.nytimes.com/svc/movies/v2/reviews/picks.json");
console.log(res.data)
},
},
};
</script>
please, someone helping me
401 Error means you not authenticated. you must add a token in axios authorization header and send it with your HTTP request.
const res = await axios.get('https://api.nytimes.com/svc/movies/v2/reviews/picks.json', {
headers: {
authorization: 'my secret token'
}
});
This is the hard code way, for more efficiency, you must define interceptors for axios to send the token with every HTTP request. see this: https://gist.github.com/srph/38f67a10e991b6cb2d83
Problem description : I have built a ionic app which uses JIRA rest api to fetch issue (GET data), create issue (POST data). I always get CORS error's like preflight request did not succeed or same origin policy which are expected when we use ionic serve but the same is not working when I build and release the signed apk.
My ionic server runs on localhost:8100 (ionic version -4) &
Jira server runs on localhost:8089 (JIRA version - core 7)
What I have done so far :
followed the proxy approach as mentioned in ionic blog --No success
enabled CORS filter plugin in JIRA server and whitelisted ionic server --No success
Added headers for Allow control origin -- No success
Build the apk file using --prod release signed and tried the same on device --No sucess
Here is my auth.ts file reference if any-one can help and advise here about what I am doing wrong here.
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { AuthProvider } from '../auth/auth';
import { Issue } from '../../models/issue'
#Injectable()
export class JiraProvider {
apiVersion: string = '2'; // The API version we want to use
jiraInstanceUrl: string = 'http://localhost:8089' // The Jira instance URL
urlString: string = `${this.jiraInstanceUrl}/rest/api/${this.apiVersion}`; // Concat those together
constructor(
public http: HttpClient,
public auth: AuthProvider
) {
}
// Authenticate the user against Jira's profile endpoint.
public authenticateUser(username: string, password: string): Observable<Object> {
return this.http.get(`${this.urlString}/myself`, {
headers: new HttpHeaders()
.append('Authorization', `Basic ${btoa(username + ':' + password)}`)
.append("Access-Control-Allow-Origin","*")
});
}
// Get issue details based on the provided key.
public getIssue(key: string): Observable<Issue> {
return this.http.get<Issue>(`${this.urlString}/issue/${key}`, {
headers: new HttpHeaders()
.append('Authorization', `Basic ${this.auth.getAuthString()}`)
.append("Access-Control-Allow-Origin","*")
});
}
public getAllIssue():Observable<any> {
return this.http.get(`${this.urlString}/search?jql=project=PM`,{
headers: new HttpHeaders()
.append('Authorization', `Basic ${this.auth.getAuthString()}`)
.append("Access-Control-Allow-Origin","*")
});
}
public postIssue(data):Observable<any>{
return this.http.post(`${this.urlString}/issue`,JSON.stringify(data),{
headers: new HttpHeaders()
.append('Authorization', `Basic ${this.auth.getAuthString()}`)
.append('Content-Type','application/json')
.append("X-Atlassian-Token", "no-check")
.append("User-Agent", "xx")
.append("Access-Control-Allow-Origin","*")
});
}
}
Added screenshot as per request(please not I changed the JIRA server intentionally to 8089 updated the question accordingly)
I soved this issue by using a CORS proxy in a container (Docker) for when you need to Access-Control-Allow-Origin: *`! this acts like a proxy https://github.com/imjacobclark/cors-container and now I am able to route the requests.
Hope it helps others !!
I have some problems with Angular 2 http get request in a ionic 2 application.
In fact I have a website (made with the Jalios CMS) which is running currently with an Apache tomcat on localhost:8080 and I want to access data from my ionic app with RESTful Web services. To access to this website the users need to log in, and their passwords can contain special charactere like #,#.:?
When I use the cURL command, I can access data without any problems. Data are returned in xml.
curl -u username:p#ssword http://localhost:8080/jcms/rest/data/Article
However in my ionic 2 application I have the following errors:
OPTIONS http:/ /localhost:8080/jcms/rest/data/Article 401 (Non-Autoris%E9). polyfills.js:3
XMLHttpRequest cannot load http:/ /localhost:8080/jcms/rest/data/Article. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http:/ /localhost:8100' is therefore not allowed access. The response had HTTP status code 401. (index):1
ERROR Response {_body: ProgressEvent, status: 0, ok: false, statusText: "", headers: Headers…}. core.es5.js:1084
my http provider: rest-service.ts
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class RestService {
constructor(public http: Http) {
console.log('Hello RestService Provider');
}
httpGet(username: string, password: string, resource: string){
let url = 'http://localhost:8080/jcms/rest/data/' + resource;
let headers: Headers = new Headers();
headers.append("Authorization", "Basic " + btoa(username + ":" + password));
return this.http.get(url, {headers: headers});
}
}
my Ionic page (component): home.ts
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import {RestService} from "../../providers/rest-service";
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
result: Array<any>;
constructor(public navCtrl: NavController, private restService: RestService) {
this.restServiceGet();
}
restServiceGet(){
this.restService.httpGet('username', 'p#ssword', 'Article')
.map(res => res.json())
.subscribe(data => this.result = data);
}
}
Normally all have been correctly imported in the app.module.ts file. I also try to change the special character by URL Encoding (%40 for #), and replace the btoa directly by the base 64 equivalence of username:p#assword.
Can you help me to correct this errors? Especially the 401 unauthorized because I d'ont understand why it happen whereas I implemented the headers with the basic authentification. Where are my mistakes?
Thank you