Spring Cloud Data Flow behind a web proxy - java

I want to put SCDF's dashboard behind zuul (or just assume any proxy, really), but when I do that, Spring Cloud Data Flow will redirect to what it thinks it's actual host is.
Example:
Zuul is http://zuul/. It's configured to route any /dashboard requests to http://scdf/host
In a browser, I go to http://zuul/dashboard.
As soon as the request routes through zuul, and then hits SCDF, SCDF will redirect to http://scdfhost/dashboard, which won't work in a locked down environment. (scdfhost will not be visible through the outside)
I've looked for any properties that would work here, but I can't figure it out.
Anyone tried this? Or tips?

Thanks for your question! The issue is the redirect 302 from http://localhost:9393/dashboard to the absolute URI of the dashboard (http://localhost:9393/dashboard/index.html). If you are running Spring Cloud Data Flow Server behind a proxy server, such as Zuul, you will have to specify the property
server.use-forward-headers and set it to true. That way Spring Boot is aware of the HTTP forward headers from the proxy. See also the Spring Boot reference guide ("Running Behind a Front-end Proxy Server").
You can find a basic example at:
https://github.com/spring-cloud/spring-cloud-dataflow-samples/tree/master/dataflow-zuul
In order to clarify the reference documentation, I have created a follow-up issue:
https://github.com/spring-cloud/spring-cloud-dataflow/issues/2929

Related

AADAuthenticationFilter called only Once

I downloaded the Azure AD with spring boot from https://github.com/microsoft/azure-spring-boot. Its all nice and works well as long as I run theazure-active-directory-spring-boot-sample using
mvn spring-boot:run
as shown in the README file.
I am trying just a basic real-life scenario where the angular/react app is running separately on a separate port using npm. The moment I separated them out the main Filter AADAuthenticationFilter is only invoked once on the first request where it does token verification and never again for subsequent requests.
I went around and configured an nginx proxy so that the domains of these two are now same
localhost:9999 and I redirect based on the next path like web for the npm and app for the Spring boot. This enabled the cookies to be available at every request.
This helps because what I learned is that Spring uses cookies to maintain a session. But ideally, the AAD filter should revalidate the token every request.
But if I add a property of azure.activedirectory.session-stateless=true to my application.properties, as mentioned in the filter's code to make it stateless and validate on every request. It expects roles as a different attribute in AD instead of it being a group of the user.
I also don't understand get the behaviour, when the js files are embedded within the spring app and run all this works perfectly fine and the filter is invoked at every request. But when I separate them out it just doesn't work.
Any help or pointers would be appreciated.
I realize that a lot more info may be required for someone to debug the above problem. But I was just able to solve this - at least found the problem that was causing it. Like I mentioned earlier the problem started when I separated the client and spring APIs. And since the client was not able to send back the cookies set by server, due to change in domains I had to put a proxy server.
What I found out later was that every GET request was always invoking the AAD filter. Even multiple requests. But other requests like POST, PUT were failing. I tried disabling the csrf config in spring WebSecurityConfig.java -->> http.csrf().disable();
This solved my problem and now I receive a request and all works as expected. Now I am trying to figure out how not to disable csrf completely.
Thanks

Cross Domain WebSocket Connection [Spring Boot]

I have two instances of spring boot services running. let's say 'app1:8080' and another instance 'app2:7070'. Where as 'app1:8080' is hosting a html page , which tries to connect a web-socket connection with 'app2:7070', whenever it get launched.
Something like this :
var webSocket = new WebSocket("ws://app2:7070/socket-endpoint");
But i am always getting 403 error message. I have read about the cross-domain and have tried to register the 'app1:8080' in 'app2:7070'.
But couldn't find any solution.
Server technology : spring boot
client technology : HTML5
Most probably this results from cross origin calls. You have different options to solve this:
put a load balancer like nginx in front of both applications and serve them with the same base URL
serve the html from the same application (the easiest solution if its a small application)
or allow cross origin calls in app2 from app1 in your case, like documented here

Don't REST control a URL in Spring Boot? Exclude url?

I am using some angular ui routing in some places, and I wanted the java server to not control some of the urls.
Perhaps it makes more sense to run the java app elsewhere? The reason I have the angularJS in the same url is because there are some authentication checks for my springboot app. So I want most URLs controlled.
But there's a few where I may want to control the authentication----but not the templating.
I think my problem is my Spring Boot code is trying to use velocity, when some of those URLs should just forward to AngularJS routing.
So a URL=/myreport/
--> goes to Java 404 error, instead of just forwarding to Angular UI Routing
--> But in some cases, Java should return 404/500/403 et al
Is there a way to do like a RestController that just forwards to AngularJS after authenticating? or to disable velocity??
This would probably be more straightforward if you limit your Spring Boot code to just doing authentication and providing an API, and implement all of your UI in the Angular app.
You can then still use Spring Security to control access to the API.
On the Angular side, you can use AuthGuards in your routes to control access to parts of your UI based on the user's role.
To get a nice, clean separation, it is helpful to use token-based authentication instead of, say, Form-Based or Basic authentication. That way, the Angular app can present the login UI, and make a REST call to the Spring Boot app to log in, and get a token back, which is used on subsequent calls.
If you use JWT, you can have the back-end produce a token that includes the users' role, and then read that in the Angular app.
I recently wrote a 2-part blog post showing how to create an Angular 2 app with a Spring Boot back-end using JWT.
See http://chariotsolutions.com/blog/post/angular-2-spring-boot-jwt-cors_part1 and http://chariotsolutions.com/blog/post/angular-2-spring-boot-jwt-cors_part2

OAuth2 with Spring Security - InsufficientAuthenticationException

i am currently working on a project involving spring security (for OAuth2).
We are using the authorization_code flow.
However when the client hits the AuthorizationEndpoint (/oauth/authorize)
we get an "InsufficientAuthenticationException".
This may be due to an external system which is also involved in this flow which performs a redirect for the client, sending him to the /oauth/authorize endpoint.
From what I understand by looking through the debug logfile and from reading the source code, the principal is null which is used in the AuthorizationEndpoint.authorize method (specifically line 138, we are using spring-security-oauth2-2.0.7.RELEASE).
I understand what spring's problem is at this point (it does not "know" the user who is already authenticated with the system) but I do not understand which information specifically spring uses to identify the user (I guess this would be my central question)
I tried performing a GET against /oauth/authorize with the correct parameters and sending with the request the authorization header containing the bearer access token but spring always throws the InsufficientAuthenticationException. I'm hoping somebody can help me with this.
Best regards
p.s.
I am going to answer my own question here for the sake of documentation.
TJ basically pointed me in the right direction.
In my case, the InsufficientAuthenticationException stems from a slightly wrong setup of the whole stack. For delivering the content to users an apache is used which also serves as a reverse proxy, truncating the root context of the application deployed on the tomcat behind it.
The answer which finally solved my problem can be found here.
The problem actually was, that the session cookie contained an invalid path (the path attribute still contained the rootcontext, because tomcat has not been made aware that the apache in front of it is truncating the rootcontext to just "/".) So setting the path on tomcat side via setSessionCookie="/" in tomcat's context.xml did the trick.
So, when a redirect hit spring's oauth/authorize endpoint it did so with a session cookie containing the wrong path. because of this, for spring the request seemed to originate from an unauthenticated source, thus leaving me scratching my head about the InsufficientAuthenticationException.

Spring Security example

I am learning Spring and trying to implement Springs Security. I am not able to understand how it works. I read tutorials from which I understood the following:
we have to configure web.xml for delegating proxy and pattern
we need to add intercepts to dispatcher-servlet.xml
When request is made it triggers intercepts but after that I am unable to understand how it works. It would be helpful if somebody could provide a list of steps to be followed. I am using Hibernate and Spring (both with annotations), I want to authenticate users using Hibernate.
A detailed article can be found here: Code Project Or a tutorial with MVC and Spring Security here.
I tried to illustrate the process a little bit:
The user sends a HTTP-Request to the server
The server processes the request according to the web.xml
The web.xml contains a filter (AKA interceptor) and passes the request through this filter.
Because the user is unknown/not authenticated, Spring Security does its best to get more details.Depending on the config, it
sends an HTTP header, so that a login popup pops up in the browser (client side).
redirects to a form where you can enter username and password.
does a lot of hidden interaction between server and browser to guarantee a "Single-Sign-On" (SSO)
Except for SSO the user enters her/his/its credentials and create an additional request.
Spring Security realizes the login attempt and authenticates the user against a
file with user and passwords
a built-in XML structure in a spring config file
a database
an LDAP
When the access is granted, it assignes the necessary roles...
...and redirects to hard-coded "home page". (Spring Security let's you adjust this behaviour.)
In your application you can check the authorization for certain actions
.....
The user clicks on "logout" or the session expires. With the next request the process starts again.
Annotations
I found a tutorial here (Link).
I understood/assume the following facts:
The filters still must be defined in the web.xml.
You can annotate your classes/methods with
#Controller (API)
#Secured (API)
#RequestMapping (API)
I admit that I only gave you a rough overview, because your question is not that specific.
Please let me know what you want to learn in detail (re-recognize users, authenticate against different resources, do a SSO, create a secured area on your webpage,...)
Spring uses a dispatcher servlet for delegating the request. Spring security filters the request and checks if a valid security context is established. If so the request is passed to the dispatcher and it passes the request forward to the corresponding controller. If no security context is established, Spring security intercepts the request which means he could manipulate the request before the diespatcher servlet could process it. During this interception the request dispatcher (Servlet Specification) will be assigned to forward the request to a login page.
I think you don't have to bother with xml anymore. Now you can use Spring Boot + annotation based configuration. One of the best tutorial I found is this one: A good spring security tutorial
There are some good step-by-step tutorials on how to integrate spring security. For example:
For Java config: http://jtuts.com/2016/03/03/spring-security-login-form-integration-example-with-java-configuration/
For XML config: http://jtuts.com/2016/03/02/spring-security-login-form-integration-example-with-xml-configuration/

Categories

Resources