I have a spring boot application with basic spring security enabled. And I have a web application written in Angular JS
When I make a rest call, I can clearly see the Authorization header being passed. But in the server, it displays the header as Null.
P.S This happens only in my machine ( yeh the same old story ) but appears to be working everywhere else.
Request Header
Accept: application/json, text/plain, */*
Authorization: Basic YWRtaW5Ac211LmVkdS5zZzpleUXXXXXXXXXXXSmhaRzFwYmtCemJYVXVaV1IxTG5ObkXXXXXXXXXXXXTmpReGZRLnXXXXXXOExJNF80MjBjMTZMUTFWX2JLR1p1VjM5SmZ3dllXbkxVTmc4LWhEeGJhdXhlMjljc3l5dWVka0w=
Content-Type: application/json
Origin: http://localhost:9000
Referer: http://localhost:9000/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36
Response Header
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Access-Control-Allow-Origin,Access-Control-Allow-Credentials
Connection: Keep-Alive
Content-Length: 68
Content-Type: application/json;charset=UTF-8
Date: Fri, 22 Mar 2019 05:38:23 GMT
Server: NA
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Server Copmonent
The server component is built using camel and maven restlet.
from(reslet://routeName)
.log("${in.headers}"; // the auth header is completely ignored.
The app is deployed in tomcat and the web.xml has filters as below
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,PUT,DELETE</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization, Cache-Control</param-value>
</init-param>
<init-param>
<param-name>cors.exposed.headers</param-name>
<param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
</init-param>
<init-param>
<param-name>cors.preflight.maxage</param-name>
<param-value>10</param-value>
</init-param>
</filter>
<filter>
<filter-name>httpHeaderSecurity</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter>
<filter-name>envHttpHeaders</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>envHttpHeaders</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>httpHeaderSecurity</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Am also behind a Corporate proxy. Does it rip off Auth header
The solution is the last line in my question
Am also behind a Corporate proxy. Does it rip off Auth header
After testing the same application in a personal computer with open internet connection, am convinced the, the corporate proxy is actually removing few headers for security reasons.
on the server side I have the following filter in apache which allow all methods and all origins by defaults
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Using angular $http One post is working, but another fail failed. The request that fails talks to another app on the same apache.
Cross-Origin Request Blocked: The Same Origin Policy disallows
reading the remote resource at http://localhost:..
(Reason: CORS header 'Access-Control-Allow-Origin'
does not match 'http://localhost:8100, http://localhost:8100').
But the response header does contain the ACAO
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
access-control-allow-credentials: true, true
access-control-allow-origin: http://localhost:8100, http://localhost:8100
Vary: Origin
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 22 Oct 2015 04:35:29 GMT
Where did the ' http://localhost:8100, http://localhost:8100' come from ? Do you think it is angular $http or Apache problem ?
Access-Control-Allow-Origin accepts either '*' or a single origin for its value. You can't put a comma-separated list there.
The browser is matching the origin (http://localhost:8100 against http://localhost:8100, http://localhost:8100 and not getting a match.
You have a similar problem on the line before. It looks like you are running the code to insert your CORS headers twice.
I've been ripping my hair out over this issue. Im attempting to enable CORS between an Angular App and a Jersey Server. Basically I've implemented a filter for jersey that should allow angular access to the server:
public class SimpleCORSFilter implements ContainerResponseFilter {
/**
* Add the cross domain data to the output if needed
*
* #param creq The container request (input)
* #param cres The container request (output)
* #return The output request with cross domain if needed
*/
#Override
public ContainerResponse filter(ContainerRequest creq, ContainerResponse cres) {
cres.getHttpHeaders().add("Access-Control-Allow-Origin", "*");
cres.getHttpHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization");
cres.getHttpHeaders().add("Access-Control-Allow-Credentials", "true");
cres.getHttpHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
cres.getHttpHeaders().add("Access-Control-Max-Age", "1209600");
return cres;
}
}
I've then added this as an init param to my web.xml.
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
<param-value>com.complaints.security.SimpleCORSFilter</param-value>
</init-param>
When I hit the URL - mysite:8080/ComplaintService/service/user/authenticate from postman with a post containing user details it returns fine (as is expected from postman) and the header contains all the correct CORS related headers. When I try to make the call from angular for some reason none of the CORS headers are being returned and it fails. Even if I just hit the URL from the browser as a GET the CORS headers are being returned. This is my angular call:
$http.post('http://mysite:8080/ComplaintService/service/user/authenticate', user).then(function(data) {
alert(JSON.stringify(data));
});
Basically I'm just wondering am I missing something simple? Or perhaps could it be related to the spring security filter? I was thinking the application could potentially be blocked from reaching the jersey filter. Here's the spring filter:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Angular is currently deployed on jersey - mysite:8081 and the server is deployed on mysite:8080. Any help would be greatly appreciated!
I overcame this issue using a library - com.thetransactioncompany:cors-filter:1.3.2 and adding some config to my web.xml.
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.allowOrigin</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>origin, content-type, accept</param-value>
</init-param>
<init-param>
<param-name>cors.allowGenericHttpRequests</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET, POST, HEAD, PUT, DELETE</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I think the issue was because the spring security filter was being called first, this seemed to resolve the issue.
I'm deep in the rabbit hole with this. I'm creating a simple app that uses SOLR 4 as a NoSQL datastore and AngularJS v1.2.2 for the interface. I've loaded a bunch of documents from the command line and AngularJS makes it very easy to search/view these. I want to permit document editing but can't get the POST working. Chrome console shows 400 errors and the Network tab shows it's failing on OPTIONS method.
Network Headers:
Request URL:http://localhost:8983/solr/mrm_assay/update
Request Method:OPTIONS
Status Code:400 Bad Request
Request Headers
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,es;q=0.6
Access-Control-Request-Headers:accept, content-type
Access-Control-Request-Method:POST
Cache-Control:no-cache
Connection:keep-alive
Host:localhost:8983
Origin:http://localhost:63342
Pragma:no-cache
Referer:http://localhost:63342/angular-solr2/app/index.html
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36
Response Headers
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:origin, content-type, cache-control, accept, options
Access-Control-Allow-Methods:GET,POST,DELETE,PUT,HEAD,OPTIONS
Access-Control-Allow-Origin:http://localhost:63342
Access-Control-Max-Age:1800
Content-Type:application/xml; charset=UTF-8
Transfer-Encoding:chunked
Quick overview of architecture:
Both SOLR and AngularJS apps are running on my Mac.
SOLR is using the default Jetty instance and the Angular app runs within the server from WebStorm's IDE. CORS is enabled and includes GET,POST,DELETE,PUT,HEAD,OPTIONS.
Updates work when:
Using SOLR's dashboard
Using command line (example)
$ curl http://localhost:8983/solr/mrm_assay/update -H 'Content-type:application/json' -d '[ {
"keep_in_assay" {"set" : "N",
"detected_endog": "N",
"problems_w_is": "removed b/c requires addition post-Oasis",
"onc_std_set": "set1",
"fraction_id": "7",
"onclistgene": "UBL3",
"geneid": "UBL3_IS6",
"taxonid": "9606",
"peptide": "SSNVPADMINLR",
"degen_human": "1",
"gene_degeneracy": "1",
"percnt_id": "66.7",
"uuid": "6d20eb03-d3ee-4eb2-bc16-27cfaabab989"
} ]'
My Angular controller code looks like this:
assayControllers.controller('AssayUpdateController', ['$scope', '$http',
function($scope, $http){
$scope.processForm = function(){
console.log($scope.assay);
$http({
method:'POST',
url:'http://localhost:8983/solr/mrm_assay/update',
data : $scope.assay,
headers : {'Content-Type': 'application/json' }
})
.success(function(data, status, headers){
console.log(data.message);
})
.error(function(data, status, headers, config){
console.log(status);
});
};
}
]);
Data is successfully sent from the form as I can see it on the console (although the JSON object isn't packaged in an array, which SOLR seems to expect...I also tried to push JSON-formatted data to an array and POST that but no luck)
I appreciate your help - even if it's just to direct my troubleshooting!
The answer on how to update an individual document to SOLR v4.7 using AngularJS v1.2.2 is multi-part. This has only been tested on my localhost!
I. Configure CORS on Jetty server that ships with SOLRsolr-4.7.0/example/solr-webapp/webapp/WEB-INF/web.xml
Notes: CrossOriginFilter has a parameter, chainPreflight, that is set to true by default. This needs to be set to false. This was the key to CORS forwarding POST instead of OPTIONS to SOLR.. Also, order matters!
<filter>
<filter-name>cross-origin</filter-name>
<filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
<init-param>
<param-name>allowedOrigins</param-name>
<param-value>http://localhost*</param-value>
</init-param>
<init-param>
<param-name>allowedMethods</param-name>
<param-value>GET,POST,DELETE,PUT,HEAD,OPTIONS</param-value>
</init-param>
<init-param>
<param-name>allowedHeaders</param-name>
<param-value>origin, content-type, cache-control, accept, options, authorization, x-requested-with</param-value>
</init-param>
<init-param>
<param-name>supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>chainPreflight</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>cross-origin</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
II. SOLR expects payload in array format, so you need to push Angular object into one. Basically, $scope.data becomes [$scope.data]
assayControllers.controller('AssayUpdateController', ['$scope', '$http', '$location',
function($scope, $http, $location){
$scope.processForm = function(){
$http.post("http://localhost:8983/solr/mrm_assay/update?commit=true", [$scope.assay])
.success(function(data, status, headers){
console.log(data.message);
$location.path("/assays")
})
.error(function(data, status, headers, config){
console.log(status);
});
};
}
]);
III. SOLR documents contain version field that can cause "conflict" errors on POST. This is due to a cache issue I wasn't able to track down (curl showed current value but browsers had old one; even on force refresh). Anyway, this is of more use to SOLR than me so the best bet is to not return it to the client in the first place. I don't think field exclusion is an option so I whitelisted all the fields I wanted to return in solrconfig.xml
<!-- A request handler that returns indented JSON by default -->
<requestHandler name="/query" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicit</str>
<str name="wt">json</str>
<str name="indent">true</str>
<str name="df">text</str>
<str name="fl">uuid,keep_in_assay,detected_endog,problems_w_is,onc_std_set,fraction_id,detected_by_orbi_experiments,onclistgene,geneid,taxonid,peptide,\
degen_human,degen_mouse,gene_degeneracy,department,protein_ac,pepid,protid,percnt_id,peptide_ordered</str>
Now the app works like a charm!
If you are failing on OPTIONS request then it is CORS that's causing problems. Most likely because the jetty that comes with Solr does not support (or is not configured) with one. The latest version of Jetty has one, but it still needs to be configured.
So, you can disable CORS on Solr requests or enable it in Jetty. Upgrading Jetty if the version shipped does not support it.
However, you also have a second problem. Solr should not be exposed directly to the internet but is supposed to run behind a middleware client or - worst case - a heavily restricting proxy. Otherwise, anybody can connect directly to your instance and delete the data or do other damage. Solr is not even security tested for direct internet access. So keep that in mind before you get too far down 'Solr-Angular' direct bridge.
I'm trying to run the GWT 2.4 sample app "MobileWebApp". I get a 500 "No Realm" error when I try to run the app in dev mode through Eclipse.
I understand this is an authentication problem.
I'm not familiar with Google App Engine or Jetty but from looking at the web.xml I can see there is a servlet filter where it is using the appengine UserService to presumably redirect the user to Google for authentication.
I'm using:
Eclipse 3.7 (Indigo SR1)
Google Plugin for Eclipse 2.4
m2eclipse
I'm including an excerpt from the web.xml below. I'm not sure what other info would be helpful in diagnosing this problem.
<security-constraint>
<display-name>
Redirect to the login page if needed before showing
the host html page.
</display-name>
<web-resource-collection>
<web-resource-name>Login required</web-resource-name>
<url-pattern>/MobileWebApp.html</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<filter>
<filter-name>GaeAuthFilter</filter-name>
<!--
This filter demonstrates making GAE authentication
services visible to a RequestFactory client.
-->
<filter-class>com.google.gwt.sample.gaerequest.server.GaeAuthFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>GaeAuthFilter</filter-name>
<url-pattern>/gwtRequest/*</url-pattern>
</filter-mapping>
Below is the output in the Eclipse console:
[WARN] Request /MobileWebApp.html failed - no realm
[ERROR] 500 - GET /MobileWebApp.html?gwt.codesvr=127.0.0.1:9997 (127.0.0.1) 1401 bytes
Request headers
Host: 127.0.0.1:8888
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:7.0.1) Gecko/20100101 Firefox/7.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Response headers
Content-Type: text/html; charset=iso-8859-1
Content-Length: 1401
Many thanks for any helpful advice!
Edit on 11/11/11: I added Jetty tag since it seems relevant to this problem.
If your very first request fails, just getting the /MobileWebApp.html page, then it probably isn't an authentication problem. Do you have GAE enabled for that project (not only GWT)? That might be one issue.
I read somewhere that there's two ways of debugging an app in Eclipse, one is with run as/webapp, and forgot which was the other one (I don't use Eclipse). One of them works and another doesn't.
If that doesn't work, you can try replacing the built-in jetty:
add a GWT param: -server com.google.appengine.tools.development.gwt.AppEngineLauncher
VM param: -javaagent:/path_to/appengine-agent.jar
And the last option is with -noserver, but then you wont be able to debug the server-side code, just the client-side GWT stuff: first start jetty with mvn jetty:run and then debug in Eclipse with -noserver GWT param.
I had the same problem. Finally I noticed that when I switched to a newer version of Appengine, the older Appengine libraries remained in the WEB-INF/lib along with the new ones.
Removing them solved the problem.