Login once with client once to the REST remote app - spring-boot

I am developing a REST client (A) that talks to the another rest based application (B).
Now B is a secure application and has login url. When I hit the url using RestTemplate I get nothing in response but headers. But after that if I ask for any other resource using RestTemplate to app B it says unauthorized.
Below image shows the headers. How can I login once and then use this headers to talk with application B using RestTemplate.
thank you
I also don't have any login code for my rest client app A. As it will completely depend on app B. So I will not have any local user database for app A.

Request: POST /login username=user&password=password
Response: 302 Set-Cookie: JSESSIONID=xxxxxxx
Request: GET /protected-endpoint Cookie: JSESSIONID=xxxxxxx
Response: 200 Stuff...
A successful POST request to the /login endpoint should return a JSESSIONID Cookie. This is what you'll need to pass along in subsequent requests as this is your session token.
Depending on your Security Configuration you may need to make some modifications but that is the gist of it.

Related

Spring Security + Keycloak - setting no bearer token to REST request leads to an response with HTML content

I'm using a SpringBoot 2 (2.7.0) application (including Spring security 5.7.1) to secure REST endpoints with Keycloak for authentication and authorization. Everything works fine but the only thing which bothers me is when I don't set the bearer token I get a HTTP 400 response. The response itself is correct but the body of the response contains HTML (Keycloak login page).
Is there a way to avoid that the body of the response contains the login page? I would like to set a custom response body.
That is an expected default behavior. If you want to instead get relevant 4xx error instead, you can try setting the the "bearer-only" in your "keycloak.json" file so that it would not redirect API calls (i.e. AJAX calls from browser) to the login page:
{
...
"bearer-only": true
}

Spring Security Oauth2 Swagger

I am attempting to configure Swagger Authentication on my resource server, so that I can authenticate against my authorization server.
I have the resource and authorization servers separated. They are both starting up on my localhost with different ports.
Resource Server on port 8083
Authorization Server on port 8081
Whenever I attempt to "Authorize", there is a CORS issues.
I forked a project from another website to use as my testing grounds. Below is the forked project.
https://github.com/cbriarnold/oauth2-spring-boot-2.0.2
To test, once both the authorization server and resource server are started, do the following:
Go to http://localhost:8083/swagger-ui.html
Click on "Authorize" button
Click on "Authorize" button in dialog
If you have the developer tools open, you will see that there is the CORS error
Access to fetch at 'http://localhost:8081/oauth/token/' from origin 'http://localhost:8083' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
The http status code associated with the above CORS error was 302.
So, I modify the source to try to permitAll (I know this is undesired from a security perspective, but I am just trying to figure out what is going on). I will receive the same CORS error, but with the https status code of 403. Code is found on the following branch.
https://github.com/cbriarnold/oauth2-spring-boot-2.0.2/tree/permitAll
Any suggestions?
I think you need to add #CrossOrigin(/*your hitting server*/) on your controllers
it's a chrome security check to see if your are permitted to talk with that server or not it sends an option request at first and if you're permitted it send your original request which is accessing swagger
if you want to make sure if that is a cross origin problem or not try to send that request via postman because postman send your request direct without option request at first

How to secure web api with Identity Server 3

I'm building an MVC web app that uses the openID Connect hybrid flow to authenticate with Identity Server 3. The MVC web app contains jQuery scripts to get async JSON data from een ApiController. That ApiController is part of the same MVC web app.
I don't want that everyone is able to access the data from the API, so I want to secure the API as well. I added an [authorize] attribute to the ApiController. When requesting the API with a JQuery ajax request I get the following error message:
XMLHttpRequest cannot load
https://localhost:44371/identity/connect/authorize?....etc.
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:13079' is therefore not allowed
access. The response had HTTP status code 405.
But, when I do a request to the API method directly in browser, I will be correct redirected to the Login page of Identity Server..
So, what's exactly the problem here? I read something about that requesting the /authorize endpoint is not allowed via 'back-channel', but I don't understand what's the difference between 'front-channel' and 'back-channel'. Is it possible that I mixed up the wrong OAuth flows? Is the Hybrid flow not the correct one maybe?
I also find out that the API is often a seperate app, but is it always neccessary / best-practice to build a seperate API app that for example requires a bearer token?
Please point me in the right direction about this.
The authorize method on your identity server does not allow ajax calls. Even specifying CORS headers is not going to help you in this particular case. Perhaps you could return a forbidden response instead of a redirect and manually redirect the client to the desired location via window.location
You need to allow your IdentityServer to be accessed from other domains, this is done by allowing "Cross Origin Resource Sharing" or CORS for short. In IdentityServer the simplest way to allow this is in your Client configuration for your Javascript Client, see this from the IdentityServer docs on CORS:
One approach to configuing CORS is to use the AllowedCorsOrigins collection on the client configuration. Simply add the origin of the client to the collection and the default configuration in IdentityServer will consult these values to allow cross-origin calls from the origins.
The error you're seeing is the browser telling you that when it asked IdentityServer if it allows requests from your Javscript client, it returned a response basically saying no, because the origin (http://localhost:13079) was not specified in the "Access-Control-Allow-Origin" response header. In fact that header wasn't in the response at all meaning CORS is not enabled.
If you follow the quickstart for adding a JavaScript client from the docs here all the necessary code is detailed there that you need for the Client config and to setup IdentityServer to allow CORS.

JASIG CAS CORS what should happen when Origin == "null"?

I am using a CAS server to secure my Spring applications which includes REST and HttpInvoker APIs.
When an application redirects to a CAS server in a different domain we get CORS
'issues'. I have added the eBay Cors-Filter https://github.com/eBay/cors-filter to the applications and the CAS server.
However...
when the application redirects to the CAS server for authentication, the Origin header is changed to 'null'. This is due to a "privacy-sensitive" context noted in the CORS spec (page 14, section 7.3).
...and, now at last...the question!
If the server receives an Origin header of 'null' can it proceed as normal, just returning 'null' in the Access-Control-Allow-Origin header?
Does this break anything?
Is it unsafe?
Cheers
Allowing null origins is unsafe. This blog post does a pretty good job of breaking down why. The short version is, it enables a form of CSRF. An allowed origin of null means "any page that redirects to me" (or any code running from a file:/// URL, but that's another topic).
Let's say your app at app.example.com uses a service at service.example.com, protected with CAS on auth.example.com. Also, let's assume you set up service with Access-Control-Allow-Origin: null so that you can make a fetch from app that points to auth with a redirect to service. Got all that? Good, you make a fetch for auth.example.com/cas/login?service=service.example.com, login happens (session cookie set on auth.example.com), redirect happens (session cookie set on service.example.com), app gets data from service. Because of your Access-Control headers, the browser lets your app read the response.
Now, imagine that you visit a malicious page (evil.com/hello) that knows about your service. They run a 302 page on evil.com/redir that points to service.example.com. Now, this malicious code can fetch evil.com/redir with credentials="include". The browser will request the redirect page, getting a 302 with ACA-Origin=https://evil.com and ACA-Credentials=true, Location of service.example.com. The browser follows the 302, requesting service.example.com and including the relevant session cookie. In this request, Origin is set to null but you've whitelisted that value, so your service sends an ACA-Origin value of null and the browser lets the (malicious) requesting code see the response. You just leaked authenticated data from your service to the injected script, which can send it home to the attacker.
Yes, I believe you can return null or the wildcard * to allow any origin.
Does this break anything?
If you're only returning null when Origin: null is received then it shouldn't affect anything else.
Is it unsafe?
I'm not familiar with CAS, however as long as you aren't sending Access-Control-Allow-Credentials too, and your CAS isn't restricted by IP or on the local network only, then this doesn't open up your system any more than anonymous access does. See this answer for technical details.
If you are, then setting Access-Control-Allow-Origin will allow other domains and origins to read data from CORS that the user visits, using their cookies for CAS.

Why Jersey client does not handle redirects for HTTP POST requests?

I have configured Jersey client to automatically follow HTTP 302 redirects:
DefaultApacheHttpClientConfig config = new DefaultApacheHttpClientConfig();
config.getProperties().put(ClientConfig.PROPERTY_FOLLOW_REDIRECTS, true);
Client client = ApacheHttpClient.create(config);
This works perfectly fine when I receive HTTP 302 for HTTP GET request: the client redirects me automatically and the last response I got from client is HTTP 202.
However, when submitting HTTP POST request that results in HTTP 302, the client does not redirects me automatically. I.e., the last response from the client is HTTP 302 and I need to follow redirects manually. This behavior seems counter-intuitive for me, as Web browsers are handling such redirects automatically. The use case also seems quite common, for instance, when trying to login with HTTP POST, you often get redirected to a new page.
Why is it so? And is there a way to handle it automatically, in a same way Web browser does it?

Resources