RestTemplate postForObject return HttpClientErrorException: 401 null - spring

I am trying to send a post message to authentication server and I am usign postforobject. When I run the program, i am getting "Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 401 null" error
RestTemplate rest = new RestTemplate();
String responseEntity;
String uri = "http://...";
responseEntity = rest.postForObject(uri, null, String.class);
System.out.println(responseEntity);
Also I tried
responseEntity = rest.postForObject(uri, "", String.class);
Same result, it didn't work.
When I using Simple Rest Client it works
enter image description here
Any idea?

401 null probably means that the server expected some form of authentication but none was presented (i.e. no Authorization header in your request)
The most likely explanation is: the Simple REST Client (re)uses Chrome's cookies. If you previously authenticated against your service using a form login, the Simple Rest Client will reuse the JSESSIONID cookie. To detect that simply press F12 and open the network tab of your debugger. FYI there are other browser plugins, for example "Advanced REST Client", which give you more visibility over what's being sent to the server.
When you send a request using restTemplate, it doesn't have access to the session cookie (which is to be expected). You should either post to URI that allows anonymous access, or provide some form of authentication in the request. If you require additional help please post your security configuration.

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
}

How to send request data in post request using zuul filter

I am new to Zuul and I want to redirect to external url using zuul pre filter in spring boot application. I want to send request data to call external url (post method api in python).
When i try to send request data using below code, when i hit the url from postman,i get 405 The method is not allowed for the requested URL.
my code:
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
InputStream in = request.getInputStream();
String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
ctx.set(body);
when i hit the url like http://localhost:8080/customers/ passing request body in postman,it should redirect to external url (api method) by sending post data but i am getting getting 405 The method is not allowed for the requested URL.
Could any one please help me in solving this issue? I want to send request data in zuul and call external api. Thank you

Login once with client once to the REST remote app

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.

How to POST to a RESTful API on an ESP8266 using authentication?

I can enter this URL from a browser, and after entering my credentials this successfully calls my API http://172.16.0.40/rest/vars/set/1/12/666.
I'm trying to do this from an an ESP8266 using HTTPClient. My credentials are username:password, and I used an online conversion utility to get dXNlcm5hbWU6cGFzc3dvcmQ=.
When executed, the following returns error 701 (no idea what that is).
HTTPClient http;
http.begin("172.16.0.40", 80, "/");
http.addHeader("Content-Type", "text/plain");
http.addHeader("Authorization", "dXNlcm5hbWU6cGFzc3dvcmQ=");
auto httpCode = http.POST("rest/vars/set/1/12/999");
If I comment out the Authorization header, I get a 401, which is unauthorized access. What am I doing wrong?
You are trying to do a POST request to http://172.16.0.40/ with rest/vars/set/1/12/999 as payload.
HTTP status code 701 is not a standard code and is probably server specific.
You probably meant to do:
HTTPClient http;
http.begin("172.16.0.40", 80, "/rest/vars/set/1/12/999");
http.addHeader("Content-Type", "text/plain");
http.addHeader("Authorization", "Basic dXNlcm5hbWU6cGFzc3dvcmQ=");
auto httpCode = http.POST(payload);
If you want a GET request, call http.GET() instead of http.POST(payload) and you should get the same response as inside the browser.
Edit:
And as #MaximilianGerhardt already answered, you need to prepend Basic to your Authorization header.
The header of such an authorization must look like (Wikipedia):
Authorization: Basic d2lraTpwZWRpYQ==
In short, you're probably just missing the "Basic" part. And need do change your code to
http.addHeader("Authorization", "Basic dXNlcm5hbWU6cGFzc3dvcmQ=");

Appropriate unauthorized response when using form based authentication

I have a web app that uses form based authentication. When an AJAX request fails due to session timeout, I need to send an appropriate notification. It looks like I could send:
403 Forbidden, but that implies "authorization will not help", which is false.
401 Unauthorized, but responses "MUST include a WWW-Authenticate header field" and the information on what exactly the value should be when using form based authentication is limited.
When an AJAX request fails because the user is not authenticated, what then is the appropriate response?
I tend to interpret 403 as "HTTP authorization will not help", and use it instead of 401 when not using HTTP authentication.

Resources