I have implemented OAuth2 in Spring boot. It works well when testing it in JUnit but I always get unauthorized when I try the API in postman.
test function in JUnit:
private String obtainAccessToken(String username, String password) throws Exception {
final MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("grant_type", "password");
params.add("client_id", CLIENT_ID);
params.add("username", username);
params.add("password", password);
ResultActions result = mockMvc.perform(post("/oauth/token")
.params(params)
.with(httpBasic(CLIENT_ID, CLIENT_SECRET))
.accept(CONTENT_TYPE))
.andExpect(status().isOk())
.andExpect(content().contentType(CONTENT_TYPE));
String resultString = result.andReturn().getResponse().getContentAsString();
JacksonJsonParser jsonParser = new JacksonJsonParser();
return jsonParser.parseMap(resultString).get("access_token").toString();
}
I tried following APIs in postman:
POST type http://localhost:8080/oauth/token with content type application/json
in Body section I selected raw and JSON :
{
"grant_type":"password",
"client_id":"clientIdPassword",
"username":"a",
"password":"a"
}
It showed 401 Unauthorized. Then I also tried like this :
Post type with content type application/json, http://localhost:8080/oauth/token?grant_type=password&client_id=clientIdPassword&username=a&password=a. This also showed 401 Unauthorized.
My question is how can I set MultiValueMap as parameter in Postman?
you should use authorization tab of postman to send auth headers along with request body however you like.
PFA sample image
When you send the request via POSTMAN tool, select the type of HTTP method (POST, PUT, DELETE), then select the "raw" option in "Body" tab and then just add the JSON of the Map in it. Make sure you have selected "Content-type" as "application/json" in "Headers" .
Related
I have a REST API and a WEB-app that makes request for that API. Both in Spring Boot.
I followed one of the many guides on this and testing the API in postman worked fine.
I also tested the API from my webapp and it also worked.
But when i run my API in docker with Traefik i get an error, but only from the webapp. Postman still works fine.
2020-10-27T13:31:10.334026053Z at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na],
2020-10-27T13:32:34.827929610Z java.lang.RuntimeException: Could not read
requestcom.fasterxml.jackson.core.JsonParseException: Unrecognized token 'ssword': was expecting
(JSON String, Number, Array, Object or token 'null', 'true' or 'false')
In the request i post username and password as json in the body like this:
{
"username" : "user",
"password" : "dfgdhghdhdhfd"
}
This is the code that generates the request from the webapp:
JsonObject j = new JsonObject();
j.addProperty("username", API_USER);
j.addProperty("password", API_PASSWORD);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://myapi.local/login"))
.header("Content-Type", "application/json")
.POST(BodyPublishers.ofString(j.toString()))
.timeout(Duration.ofSeconds(2L))
.build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
return response.headers().firstValue("Authorization").get();
Is there any chance it gets truncated somehow as it refers to the latter half of the 'password' key? I'm unsure of even where to begin getting information to assist you in helping me.
To summarize:
Localhost webapp and postman to localhost API: Works
Localhost postman to Docker API: Works
Localhost webapp to Docker API: Does not work
What is the difference with UniRest and Spring RestTemplate which is giving back a 400 Bad Request with apparently the same header and body sent ?
I try to reach the HubSpot API to create a BlogPost, but using RestTemplate I have a 400 Bad Request error, and using UniRest works alright (returns an OK response). However, I do not want to include a library just to make one REST call: I'd rather stick to RestTemplate.
The request data I need to send
HttpMethod: POST
URL: https://api.hubapi.com/content/api/v2/blog-posts?hapikey=*****************
Header: Content-Type: application/json
Body: (represented by a class instance as blogpostSendPost further down)
{
"name": "My first API blog post!",
"content_group_id": 351076997
}
Using RestTemplate
Setting up the request:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<BlogpostSendPost> request = new HttpEntity<>(blogpostSendPost, headers);
log(request.toString());
//LOG PRINT: <BlogpostSendPost(name=My first API blog post!, content_group_id=351076997),[Content-Type:"application/json"]>
OR in JSON
The .json() method converts my object in Json like you can see in the logs
HttpEntity<String> request = new HttpEntity<>(blogpostSendPost.toJson(), headers);
log(request.toString());
//LOG PRINT: <{"name":"My first API blog post!","content_group_id":"351076997"},[Content-Type:"application/json"]>
With .postForObject(): 400 Bad Request
BlogpostResponsePost answer = restTemplate.postForObject(
"https://api.hubapi.com/content/api/v2/blog-posts?hapikey=***********",
request,
BlogpostResponsePost.class);
With .exchange(): 400 Bad Request
BlogpostResponsePost answer = restTemplate.exchange(
"https://api.hubapi.com/content/api/v2/blog-posts?hapikey=**********",
HttpMethod.POST,
request,
BlogpostResponsePost.class);
Using UniRest: OK
HttpResponse<JsonNode> resp = Unirest
.post("https://api.hubapi.com/content/api/v2/blog-posts?hapikey=**********")
.header("Content-Type", "application/json")
.body(blogpostSendPost)
.asJson();
I am using PostMan to call my REST SpringBoot Application which is using theses Services : when I am calling the HubSpot API directly from PostMan it works fine, just like with UniRest lib.
Thanks for your help guys !!
Please refer https://community.hubspot.com/t5/APIs-Integrations/Getting-400-Bad-Request-when-trying-to-add-a-Blog-Post/td-p/306532
Instead of converting request object to json, pass request object directly. It worked for me.
// TRY 1: CONTACTS - RestTemplate - OK - contact is created (API V1)
HttpEntity request1 = new HttpEntity<>(contactSendList, headers);
ContactResponseInformations answer1 = restTemplate
.postForObject(
HubSpotConfiguration.URL_CREATE_CONTACT,
request1,
ContactResponseInformations.class);
log.info(answer1.toString()); // OK
I have the following Java Spring REST API method:
#RequestMapping(value = "/login", method = RequestMethod.POST)
public ResponseEntity login(#RequestBody LoginRequest request) {
request.getSession(true);
LoginResponse res = this.authService.login(request);
return new ResponseEntity<>(res, HttpStatus.OK);
}
When called using Postman or from a FireFox browser, I can clearly see the "Set-Cookie" header:
Yet, when I'm using console.log to print the response in Angular, I don't see this header:
This is the REST call in Angular:
this.http.post<Login>(this.url, this.loginRequest, {
headers: AuthService.getHeaders(),
observe: 'response',
withCredentials: true
}).subscribe(
response => {
console.log(response);
});
I did add withCredentials: true and observe: 'response' to the request call as suggested, and I do get the whole response, but without the cookie.
What I want to do is to get a cookie after a successful login, which will be delivered with any request afterwards for authentication in the server.
Thanks for the help!
Seems that browsers do not share the cookies to the client if it's not https. I had to follow this guide in order to serve the application in https mode, and then I was able to see the cookie in the server side.
Performing any request, I need to perform Authentication with POST request with body {username:"somename", password:"somepass"},
header Content-Type:application.json which gives me a response with generated token, which I need to paste as a second header, smth like Authorization:generated-tokenkjhsdkjfvjbwjbQ== for further requests.
Could you help me with it, please.
Variant which worked for me:
String token = given()
.contentType("application/json")
.body(new User("someuser" , "123"))
.when()
.post(RestConfig.baseUrl+"/authentication-url")
.then().extract().response().as(TokenResponse.class).getToken();
given()
.contentType("application/json")
.header("Authorization", token)
.get(RestConfig.baseUrl+"/some-path")
.then()
.statusCode(200)...
I had a similar requirement, where I had to pass the auth token back and forth, but this was spring rest template not rest assured. For that purpose, I used client filter, which captured the token on response and set it as a header on request. You can search if there is something similar in rest assured, which can do the job.
Here is a sample, https://github.com/rest-assured/rest-assured/wiki/Usage
Custom Authentication
Rest Assured allows you to create custom authentication providers. You do this by implementing the io.restassured.spi.AuthFilter interface (preferably) and apply it as a filter. For example let's say that your security consists of adding together two headers together in a new header called "AUTH" (this is of course not secure). Then you can do that like this (Java 8 syntax):
given().
filter((requestSpec, responseSpec, ctx) -> {
String header1 = requestSpec.getHeaders().getValue("header1");
String header2 = requestSpec.getHeaders().getValue("header2");
requestSpec.header("AUTH", header1 + header2);
return ctx.next(requestSpec, responseSpec);
}).
when().
get("/customAuth").
then().
statusCode(200);
The reason why you want to use a AuthFilter and not Filter is that AuthFilters are automatically removed when doing given().auth().none(). ...
I could be misunderstanding the question, but from what I am getting from it, I think something like this should work:
String token =
given().
header("Content-Type", "application/json").
body(/* body content goes here */).
when().
post(/* route goes here */).
then().
extract().path("token").toString()
// the above path arg depends on the response you get from the call.
Then the next call would be something like:
given().
header("Content-Type", "application/json").
header("Authorization", token).
when()...etc.
Some of the specifics will depend on the API, but I use this format all the time. Often getting a response of a user ID, or a token, etc. and using it for future calls.
More info on extracting in the rest assured docs: https://github.com/rest-assured/rest-assured/wiki/Usage#extracting-values-from-the-response-after-validation
If you want to extract one parameter from response then this should work:
String jsonBody= ( enter request payload here )
ValidatableResponse response = RestAssured.given().baseUri(baseURL)
.accept("application/json")
.header("Content-Type","application/json")
.body(jsonBody).when().post("/auth")
.then().assertThat().statusCode(200)
.log().all();
String token=response.extract().path("token");
I am trying to retrieve entities from body response of a POST request
Client client = ClientBuilder.newClient(new ClientConfig());
Response response = client.target(url)
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(form,MediaType.APPLICATION_JSON), Response.class);
Log.trackingResponse(url, response);`
request is 200 OK, parameters I want to retrieve exist, I can see them while debugging:
My problem is I can not access these parameters.
I tried the following solution but it was not successful:
Map<String, Object> jsonResponse = clientResponse.readEntity(Map.class);
MessageBodyProviderNotFoundException
Order order = response.readEntity(Order.class);
Order being a custom class with Jacksonannotation, MessageBodyProviderNotFoundException
String jsonResponse = clientResponse.readEntity(String.class);
returns < ! DOCTYPE html PUBLIC ....
the whote html code, but not my parameters
My maven has the correc jackson depedency.
Any idea ?
Thanks
These parameters are part of the request you sent, not the response.
They are members of the form you sent in the request entity:
.post(Entity.entity(form,MediaType.APPLICATION_JSON), Response.class);