Angular 2 & ionic 2 http request with basic authentification error - rest

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

Related

How to Integrate Rest Api with GraphQL Gateway and send Context

I use GraphQL Gateway to integrate with GraphQL Federation Microservices .
but I use some Rest API code for some reason. like(refresh token , Upload Images with rest)
The Question is : how to communicate with Rest API for the other services from graphql gateway and how to send context to the controller(rest api) server.
import { IntrospectAndCompose, RemoteGraphQLDataSource } from '#apollo/gateway';
import { ApolloGatewayDriver, ApolloGatewayDriverConfig } from '#nestjs/apollo';
import { Module } from '#nestjs/common';
import { GraphQLModule } from '#nestjs/graphql';
import { AppController } from './app.controller';
#Module({
imports: [
GraphQLModule.forRoot<ApolloGatewayDriverConfig>({
driver: ApolloGatewayDriver,
server: {
// ... Apollo server options
context: ({ req, res }) => ({
authorization:req.headers.authorization,
req,
res,
url: req.protocol + '://' + req.headers.host,
}),
cors: true,
},
gateway: {
buildService({ name, url }) {
return new RemoteGraphQLDataSource({
url,
willSendRequest({ request, context }) {
request.http.headers.set('authorization',context['authorization'] );
}
});
},
supergraphSdl: new IntrospectAndCompose({
subgraphs: [
{ name: 'Service1', url: 'http://localhost:3001/graphql' },
{ name: 'Service2', url: 'http://localhost:3002/graphql' },
{ name: 'Service3' , url: 'http://localhost:3003/graphql' }
],
}),
},
}),
],controllers:[AppController]
})
export class AppModule { }
Note: if I removed '/graphql' from Url to access origin url , it gives me error[Couldn't load service definitions for service1] .
This code works fine with GraphQL but didn't work with Rest.
Server : NestJS.
Thanks..
Your question is not super clear but let me take a stab at it.
You can use a service like WunderGraph on top of your existing gateway or you can create a new gateway and ingest the GraphQL Federated Microservices. You can then introspect the REST API and ingest it into your gateway. .

Ionic CORS issue with JIRA API

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 !!

Can't set Authentication header for Apollo client

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

Angular2: Keep getting a 400 bad request error when posting to API but when using a RestClient I get a 200 Ok

I am busy with a small web app where I am trying to post to a API using a RestService but keep getting a 400 bad request. When I do the exact same post using the Insomnia Rest client I get a 200 Ok... Any idea what i'm doing wrong/what I can look at to find out what's going on?
Update:
It turns out the issue is a incorrect header, there's still a unresolved error i'm getting when trying to add the correct header...
Question continuation link Here
My error:
http://10.60.160.34/BRMServices/WebEnquiry/StockTake/AddToStockTake Failed to load resource: the server responded with a status of 400 (Bad Request)
stockTake:1 XMLHttpRequest cannot load http://10.60.160.34/BRMServices/WebEnquiry/StockTake/AddToStockTake. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 400.
main.bundle.js:47711 failure: server error
My code:
stock-take.component.ts:
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
import { RestService } from '../../services/rest.service';
import { StockTakeModel } from '../../models/stock-take.model';
#Component({
selector: 'stock-take',
templateUrl: './stock-take.component.html',
styleUrls: ['./stock-take.component.css']
})
export class StockTakeComponent implements OnInit {
stockTakeForm: FormGroup;
stockTakeModel: StockTakeModel;
constructor(private fb: FormBuilder, private restService: RestService) {
this.stockTakeForm = fb.group({
'SheetNo':['', Validators.required],
'BinNo':['', Validators.required],
'BarCode':['', Validators.required],
'Quantity':['', Validators.required]
});
}
doStockTake(val: any) {
//console.log("val:" + JSON.stringify(val));
//this.stockTakeModel = new StockTakeModel(0, 0, val[Object.keys(val)[2] '', val[Object.keys(val)[0]], val[Object.keys(val)[1]], val[Object.keys(val)[3]], 0);
this.stockTakeModel = val;
this.stockTakeModel.StockTakeID = '0';
this.stockTakeModel.IDKey = '0';
this.stockTakeModel.ProductCode = '';
this.stockTakeModel.PackSize = '0';
console.log(this.stockTakeModel);
console.log(JSON.stringify(this.stockTakeModel));
this.submitStockTake(this.stockTakeModel);
}
submitStockTake(stockTakeModel: StockTakeModel) {
//console.log(stockTakeModel);
this.restService.postStockTake(stockTakeModel)
.subscribe(
(res) => {
console.log(res);
},
(res) => {
console.log("failure: " + res);
}
);
this.stockTakeForm.reset();
}
ngOnInit() {
}
}
submitStockTake function from rest.service.ts:
postStockTake(stockTakeModel: StockTakeModel) : Observable<Response> {
console.log(JSON.stringify(stockTakeModel));
return this.http.post(this.API_URL + "StockTake/AddToStockTake", JSON.stringify(stockTakeModel), this.headers)
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'server error'));
}
That indicates that you are not quite posting the same thing both ways - perhaps different request headers? Perhpas the browser running RestClient has authenticated? Inspect the actual requests in the network tab and check URL, headers, authentication etc - something has to be different.
Looking into things... here: angular.io http
it seems you aren't supposed to stringify (anymore), so try:
postStockTake(stockTakeModel: string) : Observable<Response> {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(this.API_URL + "StockTake/AddToStockTake", { stockTakeModel }, options)
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'server error'));
}
You should authorise the header "Authorization" on your server side
I have also faced this issue and resolved it by removing proxy. Please check if you have set any proxy.

Angular2 HTTP Request Providers

I want to make connection between my angular app and my REST API.
Here it returns JSON http://is.njn.mvm.bg/check. So my question is which providers do I need because I include in app.module, but it still doesn't work.
import { HttpModule} from '#angular/http';
I am using Angular2 HTTP tutorial
private heroesUrl = 'http://is.njn.mvm.bg/check'; // URL to web API
constructor (private http: Http) {}
getHeroes (): Observable<Hero[]> {
return this.http.get(this.heroesUrl)
.map(this.extractData)
.catch(this.handleError);
}
I am getting XMLHttpRequest cannot load http://localhost:8000/da. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
you are using the http request wrong. plz use following code.
app.component.ts
//our root app component
import { Component } from '#angular/core'
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
#Component({
selector: 'root',
template: `
<div>
{{people}}
{{ err}}
</div>
`
})
export class App {
people;
err;
constructor(http:Http) {
http.get('http://is.njn.mvm.bg/check').map(res => res.text()).subscribe(people => this.people = people,err=>this.err = err);
// Subscribe to the observable to get the parsed people object and attach it to the
// component
}
}
Also remember
Follow error occur in your console:
Access-control-allow-origin
For remove this error see:
chrome extension for access control
You need to put header parameter "Access-Control-Allow-Origin" in the server's HTTP response. You can't make this work from the client side only. I also had the same issue when trying to grab data from my Java JSON REST server. I am not sure what you use server side, but in Java it looks something like this:
return Response.ok() //200
.header("Access-Control-Allow-Origin", "*");
For information on this error (CORS), see this:
How does Access-Control-Allow-Origin header work?
You also need to add it to imports of #NgModule
#NgModule({
imports: [BrowserModule, HttpModule]
...
})
You module code will be like below:
#NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
],
declarations: [
AppComponent
],
providers: [
{provide: APP_BASE_HREF, useValue: '/'},
],
bootstrap: [AppComponent]
})
export class AppModule {
}
you service code need to similar to this
constructor(private http: Http) {
}
getCountriesByRegion(region: string) {
return this.http.get(this.countries_endpoint_url + region).map(res => res.json());
}
//you can also do like this
getHeroes(): Observable<any[]> {
return this.http.get(this.heroesUrl)
.map(this.extractData)
.catch(this.handleError);
}
You have the Angular app that's served by the server running on port 3000, but this app tries to make HTTP calls to the server running on another port 8000.
You have two options:
1. Deploy your Angular app under the server that runs on port 8000, in which case your Angular app will hit the same port it was served from.
2. Configure a proxy on the server that runs on port 3000 to allow access to port 8000.
For the second scenario, if you use Angular CLI with your project, create a file proxy-conf.json, for example:
{
 "/api": {
 "target": "http://localhost:8000",
 "secure": false
 }
}
Then sevre your Anglar app like this:
ng serve --proxy-config proxy-conf.json