We are using Spring Security with the SAML2 extension in our project. Currently we want to upgrade from version 1.0.0 to 1.0.3 but ran into a problem.
Our application is running in a Tomcat which has an Apache webserver in front of it. The webserver performs URL rewrites, which means that the requests reaching Tomcat have different URLs than the ones on the webserver (e.g. on the webserver it is "/saml/SSO", but in Tomcat it is "/ctx/saml/SSO").
I tracked down the problem to the checks done in
SAMLUtil.getEndpoint(...), which expect exact equality of the incoming
and the configured endpoint URL, but this is not the case for us
because of the rewriting. (Actually, the behaviour of this method has
changed between 1.0.0 and 1.0.3.)
I am thinking about some work-arounds to solve this problem, but I wonder if we are the only ones having it. Rewriting URLs in the webserver is not that uncommon, I would expect. Is there an easy solution for this which I am not aware of?
try to provide an instance of SAMLContextProviderLB Bean instead of SAMLContextProviderImpl:
java config example (adapt it to xml if you need):
#Bean
public SAMLContextProviderImpl contextProvider() {
SAMLContextProviderLB samlContextProviderLB = new SAMLContextProviderLB();
samlContextProviderLB.setScheme("https");
samlContextProviderLB.setServerName("myserver.com");
samlContextProviderLB.setServerPort(443);
samlContextProviderLB.setIncludeServerPortInRequestURL(false);
samlContextProviderLB.setContextPath("/mycontextpath");
return samlContextProviderLB;
}
And set the servername according to your Reverse Proxy virtual host server name.
Related
Setup:
I am using the Java library springdoc-openapi-ui in version 1.4.0 (via Maven) without any customization in a simple spring-boot project.
The Swagger page is generated under
https://my-url.com/my-context-path/swagger-ui/index.html
and the api-docs under
https://my-url.com/my-context-path/v3/api-docs/
both of these work and I can reach them. So far so good!
Now the problem:
When simply navigating to https://my-url.com/my-context-path/swagger-ui.html I am getting a HTTP Status 302 and a location attribute set in the response header that is supposed to redirect me to the swagger page from above (I assume).
However, the URL in the location attribute misses the context path! It looks like this:
https://my-url.com/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config
It redirects to a page that does not exist and I am getting a 404 error code. Note, that the configUrl also seems to be missing the context-path.
Any ideas why this occurs and how it can be fixed?
This Github Issue seemed to be the same problem, but in the end it is stated that the problem is fixed: https://github.com/springdoc/springdoc-openapi/issues/37 and that is for a previous version than mine.
Okay so the issue is that springdoc-openapi-ui is unaware of your app context path unless it is defined in spring boot, which may not be possible for everybody.
Hopefull it does support the non-standard header X-Forwarded-Prefix that can be sent by your gateway.
I my case (Kubernetes), the Ingress can be configured in your chart by simply adding nginx.ingress.kubernetes.io/x-forwarded-prefix: "true"
And in your application config you also need to specify
server:
forward-headers-strategy: framework
to use Spring's support for handling forwarded headers.
Sources:
https://github.com/kubernetes/ingress-nginx/issues/3670
https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#x-forwarded-prefix-header
https://github.com/springdoc/springdoc-openapi/issues/607
There are no know issues about context-path usage. As you can #37 is resolved and that reported it has confirmed that!
Just make sure you follow the instructions of setting context-path on standard spring-boot application.
You can test the configuration of your context path, in the different demos samples:
https://github.com/springdoc/springdoc-openapi-demos
If you have any problem, you can log an issue by provinding a minimal/reproducible sample or with unit tests that reproduces the problem.
In order to configure a swagger-ui correctly when an external context-path is configured use the follow configuration.
springdoc.swagger-ui.config-url=/context-path/api-docs/swagger-config
springdoc.swagger-ui.url=/context-path/api-docs
springdoc.api-docs.path=/api-docs
I have an app in facebook developer.
This app is configured with a "Valid OAuth redirect URIs"-value with a URL with https.
But when I click on the Login with facebook button on my page facebook redirects me to the http version of the URI. This seems like a facebook bug in their OAuth module?
I had exactly this issue when I deployed to an AWS Elastic Beanstalk environment with SSL terminated at the load-balancer. In this case, the request received from the load-balancer by the server looks like the client is connecting with HTTP, and the OWIN providers incorrectly infer that the URL Facebook/Twitter/Google needs to connect back into your site should use HTTP instead of HTTPS on the public side of the load-balancer.
I couldn't find a simple solution to this, there didn't seem to be any parameters to override the URI protocol which gets stored in the IOwinRequest.Scheme property. In the end, I grabbed the source code for the Katana project, and the source code for the ASP.NET Identity project, and I hacked it around a bit so that I had local projects in my solutions for:
Microsoft.AspNet.Identity.Core
Microsoft.AspNet.Identity.EntityFramework
Microsoft.AspNet.Identity.Owin
Microsoft.Owin.Security.Cookies
Microsoft.Owin.Security.Facebook
Microsoft.Owin.Security.Google
Microsoft.Owin.Security.OAuth
Microsoft.Owin.Security.Twitter
There was 50 or so other projects within Katana that I left out - I made all of these other dependencies Nuget package references to the official versions.
Then I found every reference to IOwinRequest.Scheme, and I replaced it with a snippet of code that also looked for the X-Forwarded-Proto header that is injected by the load-balancer when using SSL offloading.
Something like this:
var scheme = Request.Scheme;
if (string.Equals(Request.Headers["X-Forwarded-Proto"], "https", StringComparison.InvariantCultureIgnoreCase))
{
scheme = "https";
}
// Use the scheme in the construction of a URI...
If your load-balancer or proxy server doesn't provide the X-Forwarded-Proto header, then your options are pretty limited. You could re-encrypt the traffic and send it on to your server using the same protocol it came in on.
We've developed a Grails application that uses redirects.
Beacuse of external reasons, we are just recently using reverse-proxy, to split some traffic to domains:
From:
demo1.company.local (the server itself)
To:
tomcat.company.local (for all java applications, including our grails app)
lotus.company.local (for all Domino applications)
Since tomcat is only configured in the hosts file on the demo1 server, the redirects do not work when I access the application from anywhere else then the demo1 server itself.
I've tried to solve this using "absolute" and/or "base" parameter in Grails' redirect(), but if I understand correctly, this is Grails 2+ only and we're using Grails 1.3.4.
Are there other ways to redirect to a specified host?
Am I misusing things?
Thanks,
Bram
If you define grails.serverURL in Config.groovy, redirects with absolute:true will use that value for the URL.
Grails 2.0 changed with the way it uses grails.serverURL for development and test environments (as described in the manual). However, I've had several problems with serverURL in regard to production deployment on Tomcat. There seem to be several options for serverURL (production mode):
(Added) this setting is just "smoke and mirrors", because Tomcat and Jetty have methods to control how the URL is handled for the App, down to the "App" level.
Use it to specify the server (as is pointed out as a "TODO" in Config.groovy)
Don't use it as indicated here by one of the Grails contributors, i.e. "It should always be safe to remove the serverURL property and let Grails generate urls relative to the current running app." It's not clear if this extends to production or not (when not generating emails).
Use another method instead, namely grails.app.context, which is not documented in Grails 2.0 manual, but is described in certain references, here and here.
Can you please clarify the correct use of serverURL and app.context, both for Jetty and Tomcat (production mode)?
Thanks
Good question! I was just looking for the correct way to get the actual serverURL without explicitly needing to configure it in Config.groovy (in a Grails 2.1 application).
Since Grails 2.0, there is a super-useful class called LinkGenerator that you can use virtually anywhere, for example in a Service:
import org.codehaus.groovy.grails.web.mapping.LinkGenerator
Class MyService {
LinkGenerator grailsLinkGenerator
String serverUrl() {
// Generate: http://localhost:8080/link-generator
grailsLinkGenerator.serverBaseURL
}
}
Thanks to Mr. Haki for blogging about this!
So the basic idea of the grails.serverURL configuration parameter is to allow the createLink method to know what URL you want when creating absolute links. If no grails.serverURL configuration parameter is specified, it will default to http://localhost:8080 (unless server.port is specified, then 8080 will be whatever) ...
The application context tells Jetty/Tomcat to run the application in a different root. For example, specifying
grails.app.context="/myApp"
will set your application root to "/myApp". In production mode, the application context is handled by the web container and this directive is ignored. The choice to configure your production jetty or tomcat instances to run your application in a different context is entirely dependent on what your technical requirements are.
So the real thing to consider is, in your application are you creating a lot of absolute links in your GSPs where you need to define a "production" serverURL? If not, then you don't need to specify it; if you are, then you'll need to specify it.
As a personal preference, the first thing that I always do after creating a new grails project is go into the config and change the grails.app.context to "/" ... It makes mirroring a production environment much easier for me.
Hope this clears things up!
My problem is closely related to this one: How can I use .NET web services from non-standard ports?. My web service runs behind a port-forwarding firewall, so the port numbers reported in the WSDL document contain the internal high-numbered port. I wrote a SoapExtensionReflector class which is able to rewrite the WSDL document. So a request like example.com/path/loginservice?wsdl is handled correctly.
However, this doesn't handle the "disco" request: example.com/path/loginservice?disco. This returns an XML document like this:
<discovery>
<contractRef ref="http://example.com:10092/loginservice.asmx?wsdl" docRef="http://example.com:10092/loginservice.asmx"/>
<soap address="http://example.com/path/loginservice.asmx" binding="q1:LoginServiceSoap"/>
<soap address="http://example.com/path/loginservice.asmx" binding="q2:LoginServiceSoap12"/>
</discovery>
While the soap bindings have been properly re-written by the SoapExtensionReflector, the contractRef and docRef URLs have the high-numbered port. How can I rewrite them as well?
Finally figured something out. Created proxy classes manually using svcutil after migrating everything to WCF. I figure you could probably do the same thing using the wsdl tool that came with the old asp.net web services, but I haven't tried that.