XMLHttpRequest response doesn't return Authorization header - xmlhttprequest

I'm trying to get authorization token from server by using XMLHttpRequest, but only some headers are returned (without Authorization header).
Server is working on localhost:8080 but client application is on localhost:3000 so I tried to configure CORS.
On server site I created a CorsConfigurationSource bean:
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.applyPermitDefaultValues();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
configuration.setAllowedMethods(Arrays.asList("GET","POST","DELETE","PUT"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("Authorization, X-Content-Type-Options, " +
"X-XSS-Protection, Cache-Control, Pragma, Expires, X-Frame-Options, Content-Length, Date"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
and on client site I use XMLHttpRequest:
var httpRequest = new XMLHttpRequest();
httpRequest.open("POST", "http://localhost:8080/login", true);
httpRequest.setRequestHeader(
"Content-Type",
"application/json;charset=UTF-8"
);
httpRequest.setRequestHeader(
"Access-Control-Expose-Headers",
"Authorization"
);
httpRequest.onreadystatechange = function () {
console.log("RESPONSE HEADER : " + httpRequest.getAllResponseHeaders());
};
httpRequest.withCredentials = true;
httpRequest.send(userBody);
When I try to get all headers I only get some of them (like cache-control, content-length, expires, pragma) without Authorization header and other headers. What should I change to get all of them? Thank You for any help.
enter image description here

I managed to solve this by setting exposed headers on server site:
configuration.setExposedHeaders(Arrays.asList("Authorization, X-Content-Type-Options, " +
"X-XSS-Protection, Cache-Control, Pragma, Expires, X-Frame-Options, Content-Length, Date"));

Related

get CORS problem when ty to get a token in keycloak with vuejs and axios

I trying to access one keycloak with axios in my vuejs app, but I receive the cors error, can someone help me please? (If I make a post from POSTMAN to my keycloak works fine)
I using this code:
const params = new URLSearchParams();
params.append("grant_type", "password");
params.append("client_id", "notas-front");
params.append("username", usuario.value);
params.append("password", password.value);
console.log(params);
const config = {
// withCredentials: true,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
};
axios.defaults.headers.common["Access-Control-Allow-Origin"] =
"http://localhost:8080";
axios
.post(
"http://localhost:8082/auth/realms/lumera/protocol/openid-connect/token",
params,
config
)
.then((response) => {
console.log(response);
});
and get this error:
but when I look the request I can't find the error:
the OPTIONS returns 200
but the POST dont
Postman doesn't care about Same Origin Policy, browser do. That's why your request is working in Postman but not in the browser.
Access-Control-Allow-Origin is a response header, you can't set it on the client request. And as you can see from the OPTIONS response headers your server is returning: Access-Control-Allow-Origin: http://localhost:8080
In a development environment the best way to solve this is setting a proxy in your vue configuration. Otherwise you should configure the server to allow requests from localhost:8080
Configure Web Origins properly in the Keycloak notas-front client config.

Can't set authorization and token in headers with axios in VueJS

I'm trying to set a JWT token authentication on a VueJS client and PHP API (using Zend and firebase).
I manage to log an user in with the creation of a JWT token stored in LocalStorage. Now I would like to send back this token to the API (so as to the API decode the JWT and return associated infos). I try to set the "Authorisation: Bearer + token" in the header from VueJS using axios but I always have a problem.
Here is a code snippet :
function getInfos() {
return axios({
method: 'get',
url: MYURL,
headers: {
Authorization: 'Bearer ' + localStorage.getItem('user')
}
})
.catch(handleResponse)
}
First I got this error :
Access to XMLHttpRequest at 'MYURL' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
Then I don't have any Authorization in header when I want it in my PHP API :
header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Headers: *');
$request = new Request();
I know that I probably have to use
axios.defaults.headers.post or maybe axios.interceptors but I'm a beginner so I have no idea how to use it properly..
I hope someone will be able to help me ! Thank you
I think * doesn't work when setting custom headers you have to Type in header('Access-Control-Allow-Headers: Authorization') atleast that's an issue i had

Couchdb Vue.js authentication

I'm trying to move a node/express authentication application over to vue.js. I am able to successfully authenticate getting a 200 code. However, the response returned from couchdb does not contain the "set-cookie" header, which contains the much needed AuthSession token. The code that I am using in my Vue component is:
var reqBody = "name="+user+"&password="+pass;
var reqBodyLength = reqBody.length;
console.log(reqBodyLength);
this.$http.post('http://localhost:5984/_session/', reqBody, {headers: {'Content-Type' : 'application/x-www-form-urlencoded', 'Accept' : 'application/json'}}).then(response => {
console.log("response: " + JSON.stringify(response));
console.log("response.headers: " + JSON.stringify(response.headers));
console.log("response.headers.set-cookie: " + JSON.stringify(response.headers["set-cookie"]));
}, response => {
alert('you unauthorized, fool!')
})
Has anyone ever had an issue getting the "set-cookie" header?
Thanks, Tyler
Couch's AuthSession is HttpOnly cookie and therefore can't be accessed through a client side script. But the cookie itself should be set to a browser by that _session query, so all the consequent requests will be authorized.
BTW, /_session also accepts JSON payload, at least in CouchDB 1.6, so the query doesn't have to be in x-www-form-urlencoded form.

Redirect_URI error when using GoogleAuth.grantOfflineAccess to authenticate on server

I'm trying to use the authorization flow outlined at https://developers.google.com/identity/sign-in/web/server-side-flow.
I've created the credentials as indicated... with no Authorized redirect URIs specified as the doc indicates: "The Authorized redirect URI field does not require a value. Redirect URIs are not used with JavaScript APIs."
The code initiating the authorization is:
Client button and callback:
<script>
$('#signinButton').click(function() {
var auth2 = gapi.auth2.getAuthInstance();
auth2.grantOfflineAccess().then(signInCallback);
});
function signInCallback(authResult) {
console.log('sending to server');
if (authResult['code']) {
// Send the code to the server
$.ajax({
type: 'POST',
url: 'CheckAuth',
headers: {
'X-Requested-With': 'XMLHttpRequest'
},
contentType: 'application/octet-stream; charset=utf-8',
success: function(result) {
// Handle or verify the server response.
},
processData: false,
data: authResult['code']
});
} else {
// There was an error.
}
}
</script>
Server side (CheckAuth method to create credentials from auth code, which it receives correctly via the javascript callback):
private Credential authorize() throws Exception {
// load client secrets
InputStream is = new FileInputStream(clientSecretsPath_);
InputStreamReader isr = new InputStreamReader(is);
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, isr);
String redirect_URI = "";
GoogleTokenResponse tokenResponse =
new GoogleAuthorizationCodeTokenRequest(
httpTransport, JSON_FACTORY,
"https://www.googleapis.com/oauth2/v4/token",
clientSecrets.getDetails().getClientId(),
clientSecrets.getDetails().getClientSecret(),
token_,
redirect_URI)
.execute();
String accessToken = tokenResponse.getAccessToken();
// Use access token to call API
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
return credential;
}
The flow works correctly, up until the point my server attempts to exchange the authorization code for the token response (GoogleAuthorizationCodeTokenRequest.execute() )... the auth server returns:
400 Bad Request
{
"error" : "invalid_request",
"error_description" : "Missing parameter: redirect_uri"
}
Given the error, I looked in debug at the auth instance in javascript and noted what it indicated was the redirect_uri. I then updated my google credentials and specified that URI in the Authorized redirect URIs (it's the URL that accessed the javascript, as the auth server correctly returns to the specified javascript callback). With the updated credentials and the URI specified in the instantiation of GoogleAuthorizationCodeTokenRequest (String redirect_URI = "http://example.com:8080/JavascriptLocation";), the error then becomes:
400 Bad Request
{
"error" : "redirect_uri_mismatch",
"error_description" : "Bad Request"
}
I've tracked all the way through to the actual HttpRequest to the auth server (www.googleapis.com/oauth2/v4/token) and cannot tell what redirect_uri it is looking for.
Does anyone know what the value of redirect_uri should be in this case (when using grantOfflineAccess())? I'm happy to post more of the code, if that is at all helpful... just didn't want to flood the page. Thanks.
Found a reference to "postmessage" right after posting the question... using it as the redirect_URI on the server side seems to generate a successful response from the auth server. So... setting redirect_URI="postmessage" in the code below appears to work in this situation.
GoogleTokenResponse tokenResponse =
new GoogleAuthorizationCodeTokenRequest(
httpTransport, JSON_FACTORY,
"https://www.googleapis.com/oauth2/v4/token",
clientSecrets.getDetails().getClientId(),
clientSecrets.getDetails().getClientSecret(),
token_,
redirect_URI)
.execute();

Magento 2 API with Angular 2 Token authentication

This is integration issue. Your help is much appreciated (Hint || Guide)
I have both Angular2 and Magento2 (bitnami) installed locally. Magento conf was changed to have the right headers (See below) for CROS.
I'm calling Magento2 from Angular2 to get the token and I'm getting the following issue:
OPTIONS http://192.168.56.1:82/magento/index.php/rest/V1/integration/admin/token 400 (Bad Request)
XMLHttpRequest cannot load http://192.168.56.1:82/magento/index.php/rest/V1/integration/admin/token. Response for preflight has invalid HTTP status code 400
EXCEPTION: Response with status: 0 for URL: null
Angular 2 side:
let headers = new Headers({'Content-type': 'application/json'});
headers.append('Access-Control-Allow-Origin', '*');
headers.append('Access-Control-Allow-Methods', 'GET,POST,OPTIONS,PUT,DELETE');
headers.append('Access-Control-Allow-Headers', 'Origin,Authorization,X-Auth-Token,Accept,Content-Type');
headers.append('Access-Control-Allow-Credentials', 'true');
let options = new RequestOptions({ headers: headers });
return this.http.post( 'http://192.168.56.1:82/magento/index.php/rest/V1/integration/admin/token',
JSON.stringify('{"username":"angUser", "password":"angUser2017"}'),
options)
.map(res => res.json());
Magento2 API User
angUser / angUser2017
Consumer Key: 5bhvi7gjvyafcp35rajuxh0y4me2plga
Consumer secret: yh1nefyw1u80rd0ip1q6f8pijv9x72f1
Access Token: g5plfwth2rhlwtuwfhhqp7mg6sebrxc3
Access Token Secret: i1f4t7j65oo8ydtnteub9xr7wrswe99c
Magento headers:
Response Headers
Access-Control-Allow-Credentials: True
Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization
Access-Control-Allow-Methods: GET,POST,OPTIONS,PUT,DELETE
Access-Control-Allow-Origin: *
I had a similar issue before and I tracked it down to this method where there is no check for ->isOptions(). So every API call from another domain was triggering a Request method is invalid exception.
/**
* Retrieve current HTTP method.
*
* #return string
* #throws \Magento\Framework\Exception\InputException
*/
public function getHttpMethod()
{
if (!$this->isGet() && !$this->isPost() && !$this->isPut() && !$this->isDelete()) {
throw new \Magento\Framework\Exception\InputException(new Phrase('Request method is invalid.'));
}
return $this->getMethod();
}
You can find a possible workaround in the github forum if you are using apache.
In my specific case what I ended up doing was serving both front-end and api from the same domain to avoid problems with CORS (I use nginx).
An example of the configuration needed for this can be something like:
location ~ ^/(index.php/)?rest {
try_files $uri $uri/ /index.php?$args;
}
location / {
root /var/www/angular/public/;
index index.html;
}