I am building my application in Angular 2 and Laravel 5.4. Angular2 is for client side and laravel 5.4 is for server side. I created APIs in laravel and requesting those APIs from Angular2.
In Laravel, I configured Oauth 2 passport service which is authenticating all APIs. In each API call I am sending below headers.
'Content-Type', 'Authorization'
The way how I am calling APIs with headers.
private headers = new Headers({'Content-Type': 'application/json', 'Authorization': 'Bearer ' + localStorage.getItem('access_token') });
let body = JSON.stringify({ user_id, company_id });
console.log(this.headers);
this.http.post(this.BuyerCostSetting, body, {headers:this.headers} )
.subscribe(
response => {
console.log('here');
console.log(response);
},
error => {
console.log(error.text());
}
);
When I am hitting this API from Angular2, it is showing the below error:
Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response
The errormessage is clear, 'Authorization' header is not allowed by your backend.
In your backend Laravel application you have to set a response header containing:
Access-Control-Allow-Headers : 'Content-Type', 'Authorization'
see further documentation here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
Related
I searched a lot on the Internet, but I didn't find anything helpful for my problem.
I have a java server and a react client. My server is using jwt for authentication and returns a token to my client.
When I try to send data with a post method, my client does not send the headers, so my server returns an "Unauthorized" message. I tried to send the same request from Postman and ARC(Advanced Rest Client) and it works.
Here is my client code:
fetch(url, {
method: 'POST',
crossDomain: true,
mode: 'no-cors',
body: JSON.stringify(data),
headers: {
'Authorization': 'Bearer ' + 'token generated from fiddler after running auth',
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(responseJson => {
console.log(responseJson);
});
I tried using axios too and I have the same problem.
Also my server has #CrossOrigin(origins = {"*"}) annotation in all controller classes.
I don't know if my problem is with the client or with the server and why is working using Postman and ARC.
You are using mode: no-cors which basically strips out all headers which are not simple headers: https://developer.mozilla.org/en-US/docs/Web/API/Request/mode
You should enable CORS and allow your domain on the server.
The error message
error : use 'application/json' Content-Type and raw POST with json
data
is being appeared from cyclos application inside plivo console which a third API that need to be integrated in cyclos through
Gateway URL: https://api.plivo.com/v1/Account/auth-id/Message/
HTTP username:xxx
HTTP password: ****
HTTP headers
{
'content-type': 'application/json',
}
HTTP request type: POST
HTTP request POST body
{
"src":"+xxxx",
"dst":"+xxx",
"text":"some test"
}
Can you try sending header as 'Content-Type' instead of 'content-type'.
There are some implementations where field-names are case-sensitive (Like an age-old bug in PHP!).
I'm using Angular 6 in the frontend and Java Spring Boot in the backend.
I want my login page to make request to server. Server redirects to dashboard page.
I have http://localhost:4200/login angular page which makes a POST request to server http://localhost:8080/login
The .ts file contains:
onLoginClickPost() {
console.log('redirect request clicked');
this.data.getUserInfoPost().subscribe(
data => {
console.log(data);
this.userInfo = data;
}
);
}
getUserInfoPost() {
return this.http.post('http://localhost:8080/login', {nextUrl: 'http://localhost:4200/dashboard'});
}
The server has #RestController with a method mapping to incoming POST request, which should redirect to http://localhost:4200/dashboard :
#CrossOrigin(origins = "http://localhost:4200")
#RequestMapping(value = "/login", method = RequestMethod.POST)
public ResponseEntity<?> login_post(#RequestBody LoginReqPostParam payload) {
HttpHeaders headers = new HttpHeaders();
try {
headers.setLocation(new URI(payload.getNextUrl()));
headers.add("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
} catch (URISyntaxException e) {
logger.error("URI Exception: ", e);
e.printStackTrace();
}
return new ResponseEntity<>(headers, HttpStatus.FOUND);
}
LoginReqPostParam is a simple class to have incoming JSON payload as object.
The login angular page is able to make POST request to the server. Now at the server, after returning the ResponseEntity from server, I'm getting following error in browser console:
Failed to load http://localhost:4200/dashboard: Request header field
Content-Type is not allowed by Access-Control-Allow-Headers in
preflight response.
How do I redirect to http://localhost:4200/dashboard page? Do I need to add something to angular dashboard component files?
You are using #CrossOrigin for POST request but Angular (in development) is sending a Preflight request using OPTIONS.
I recommend you to use a development profile that permit all origins (you must create a custom filter in a Bean for these profile)
Use Allow-Control-Allow-Origin: * extension for google chrome.
And enable cross origin resource sharing
https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en
I am new to Angular2. I have to create new Angular application and Need to use services from Liferay server.
But When I call the Service using below code, it is giving Cors error.
var headers = new Headers();
headers.append('Access-Control-Allow-Origin', '*');
headers.append("Content-Type", "application/x-www-form-urlencoded");
let params: URLSearchParams = new URLSearchParams();
this.http.get(localStorage.getItem('domainName')+'/service-name', {headers: headers})
.subscribe(response => {
// login successful if there's a jwt token in the response
console.log('Response'+response.json());
});
My backend method is GET and I have added Cors filter property in my /webapps/Root/web.xml file
BUt in browser console it is giving below error:
XMLHttpRequest cannot load http://localhost:9080/service-name. 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:4200' is therefore not allowed access. The response had HTTP status code 401.
This error comes up when the backend's response does not have the necessary Access-Control-Allow-Origin header. Please double check that the backend's headers are properly configured. Also, the frontend's request does not have to have the Access-Control-Allow-Origin header ever.
Question
When using the Google Plus Sign In Api with the Play Framework do you have to set headers in a different way? Is there something I am doing wrong here?
Background
I am using Play Framework(in Java) to use the Google Plus Sign in Api.
I am running into issues on the second leg of OAuth authentication, exchanging the Authorization Code for a Token.
Basic OAuth Flow
Pretty Picture
Redirect user to User login/Consent screen
This asks the user if they want to grant you application permission to the requested scopes
URL: https://accounts.google.com/o/oauth2/auth
Exchange Authorization Code for a Token
If the user gives your application permission then they will be redirected to a URL you specify, in that URL(As a GET param) will be an Authorization Code.
Your application can then use this Authoriztion Code to get a Token from the server
Your application does this by making a HTTP request to a endpoint on the Google Servers(Or whatever service you are using)
URL: https://accounts.google.com/o/oauth2/token
Use Token in API requests
The Issue
To Exchange the Authorization Code for a Token, with the Google Plus Sign In Api, you must make a POST request to https://accounts.google.com/o/oauth2/token with the following perimeters
{
"code": "Security Code Returned from Step 1",
"client_id": "Client Id that was given to you in GApi Console",
"client_secret": "Client Secret that was given to you in the GApi Console",
"redirect_uri": "Redirect Uri you specified in the GApi Console",
"grant_type": "authorization_code"
}
However when I make this request with all the correct parameters I get this error
{
"error" : "invalid_request",
"error_description" : "Required parameter is missing: grant_type"
}
From the Google Plus Sign in Api
To make HTTP requests in The Play Framework you use the WS Library. I make the request like this
public static F.Promise<Result> OAuthCallback(String state, String code){
/*
Note:
- The GoogleStrategy class is just a class that holds all my GApi credentials
- The parameters (String state, String code) are just GET params from Step 1, returned by the GApi
*/
//Make URL builder
WSRequestHolder requestHolder = WS.url(GoogleStrategy.getTokenUrl);
//Set headers
requestHolder.setHeader("code", code);
requestHolder.setHeader("client_id", GoogleStrategy.clientId);
requestHolder.setHeader("client_secret", GoogleStrategy.clientSecret);
requestHolder.setHeader("redirect_uri", GoogleStrategy.redirectUri);
requestHolder.setHeader("grant_type", GoogleStrategy.grantType);//GoogleStrategy.grantType = "authorization_code"
//Make HTTP request and tell program what to do once the HTTP request is finished
F.Promise<Result> getTokenPromise = requestHolder.post("").map(
new F.Function<WSResponse, Result>() {
public Result apply(WSResponse response){
return ok(response.asJson());//Returning result for debugging
}
}
);
return getTokenPromise;//Return promise, Play Framework will handle the Asynchronous stuff
}
As you can see, I set the header grant_type. Just to make sure setting headers was working I made a program that spits out the headers of a request in NodeJS(Source) and this was the result
{
"HEADERS": {
"host": "127.0.0.1:3000",
"code": "4/qazYoReIJZAYO9izlTjjJA.gihwUJ6zgoERgtL038sCVnsvSfAJkgI",
"grant_type": "authorization_code",
"client_secret": "XXXX-CENSORED FOR SECURITY PURPOSES-XXX",
"redirect_uri": "http://127.0.0.1:9000/api/users/auth/google/callback",
"client_id": "XXXX-CENSORED FOR SECURITY PURPOSES-XXX",
"content-type": "text/plain; charset=utf-8",
"connection": "keep-alive",
"accept": "*/*",
"user-agent": "NING/1.0",
"content-length": "14"
}
}
I think those are not to be sent as headers but as a body. In the link you provided there is an example:
POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded
code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=8819981768.apps.googleusercontent.com&
client_secret={client_secret}&
redirect_uri=https://oauth2-login-demo.appspot.com/code&
grant_type=authorization_code
So pass them to your post call:
StringBuilder sb = new StringBuilder();
sb.append("code=").append(code)
.append("&client_id=").append(GoogleStrategy.clientId)
.append("&client_secret=").append( GoogleStrategy.clientSecret)
.append("&redirect_uri=").append(GoogleStrategy.redirectUri)
.append("&grant_type=").append(GoogleStrategy.grantType)
requestHolder.setContentType("application/x-www-form-urlencoded")
.post(sb.toString());