Trying to create a Keycloak user with spring rest client - java

Here's the error message:
400 Bad Request: [Unrecognized field "rep" (class org.keycloak.representations.idm.UserRepresentation), not marked as ignorable]
Here's some code:
public String createUser2() throws UnsupportedEncodingException, JSONException {
String adminToken = getAccessToken();
System.out.println("token: " + adminToken);
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");
headers.set("Authorization", "Bearer " + adminToken);
UserRepresentation userRepresentation = new UserRepresentation();
userRepresentation.setFirstName("some");
userRepresentation.setLastName("user");
userRepresentation.setUsername("Some.User#somewhere.com");
userRepresentation.setEmail("Some.User#somewhere.com");
// Gson gson = new Gson();
// String jsonString = gson.toJson(userRepresentation);
MultiValueMap<String, UserRepresentation> map = new LinkedMultiValueMap<String, UserRepresentation>();
map.add("rep", userRepresentation);
HttpEntity<MultiValueMap<String, UserRepresentation>> request = new HttpEntity<>(map, headers);
String uri = "http://10.127.2.46:31680/auth/admin/realms/12xDemo/users";
System.out.println("URI: " + uri);
UserRepresentation response = (new RestTemplate()).postForObject(uri, request, UserRepresentation.class);
//JSONObject obj = new JSONObject(response);
return (new Gson()).toJson(response);
}

Looks like you should send HttpEntity<UserRepresentation>as a request. Cause your server code waits for this type and receives "rep": "UserRepresentation", tries to map it on actual UserRepresentation.class

Related

How to sent Http POST request with application/x-www-form-urlencoded

I'm trying to generate a token from an external website, the post request must be application/x-www-form-urlencoded but I'm getting errors. I assume that I'm not making the right call for the content type application/x-www-form-urlencoded but I can't figuer out how!!
PS: I'm using springboot with java 8
here is the code:
public String getNewAccesToken() {
//Initilazing variabels
try {
JsonObject properties = new JsonObject();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.set("Cookie", cookie);
properties.addProperty("client_id", clientId);
properties.addProperty("client_secret", clientSecret);
properties.addProperty("grant_type", grantType);
HttpEntity<String> requestEntity = new HttpEntity<>(properties.toString(), headers);
log.debug(requestEntity);
ResponseEntity<String> response = restTemplate.exchange(requestUrl, HttpMethod.POST, requestEntity,
String.class);
log.debug("---------------------------------");
log.debug(response);
if (Util.isJSONValid(response.getBody())) {
JsonParser parser = new JsonParser();
JsonObject jsonString = (JsonObject) parser.parse(response.getBody());
return jsonString.get("accessToken").getAsString();
} else {
error.setCode(ConstantGateway.JSON_ERROR_CODE);
error.setMessage(ConstantGateway.JSON_ERROR_STATUS);
return error.toString();
}
} catch (HttpStatusCodeException e) {
error.setCode(String.valueOf(e.getStatusCode().value()));
error.setMessage(e.getResponseBodyAsString());
return error.toString();
} catch (Exception e) {
// TODO: handle exception
error.setCode(ConstantGateway.IL_INTERNAL_ERROR_CODE);
error.setMessage(e.getMessage());
return error.toString();
}
}
and here is what I get when calling this function:
org.zwz.vas.internal.api.model.ErrorModel#16dd359c
However when I make the call from Postman I get the right response which is :
{
"access_token": "RdWt3DNIfxmihnubGX0Fgfcb0KNHLZV79OfN9Y6Ky6Z3fxAfF_Pm7uP0jnFrG1fHplyBMZ74BIKleQ8jmswdGy4e87NV-uZsMzgS1nQAONc2nBxgU1_jkMBhL4vvIniJNd99oYNzGeanCYYki0yorrrlLrOGTncusv1BgFFHU_CBGuUtGmZYLfJAJW4XcZLhXMC9xpT2aWAvgRXZW69pOhfU1Fgs7aVwou85UVI2b4j1GfX0pCtJtluiTgXsuWqdck7_at1dqfopHpjWAywYrweStMXGm8T59nyQi_oXWmo",
"token_type": "bearer",
"expires_in": 1199
}
THANK YOU IN ADVANCE
I find the mistake I did, I was sending a wrong request format which is not compatibale with application/x-www-form-urlencoded type. The right code is below:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.set("Cookie", cookie);
MultiValueMap<String, String> properties= new LinkedMultiValueMap<String, String>();
properties.add("client_id", clientId);
properties.add("client_secret", clientSecret);
properties.add("grant_type", grantType);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(properties, headers);
ResponseEntity<String> response = restTemplate.postForEntity( requestUrl, request , String.class );

Token missing in the request

Here I'm trying to send the generated token from header to an API along with the data, but I'm getting an error:
Token missing in the request
Not sure what's wrong with my code, can someone please guide me resolve this, thanks in advance.
String url = "API_TO_GENERATE_TOKEN";
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("Content-Type", "application/json");
httpHeaders.set("CLIENT_ID", "VALUE_OF_CLIENTID");
httpHeaders.set("CLIENT_SECRET", "VALUE_OF_CLIENT_SECRET");
JSONObject json = new JSONObject();
HttpEntity <String> httpEntity = new HttpEntity <String> (json.toString(), httpHeaders);
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.postForObject(url, httpEntity, String.class);
JSONObject jsonObj = new JSONObject(response);
System.out.println("Json Obj is:"+jsonObj);
/*String balance = jsonObj.get("data").toString();
System.out.println("Response is:"+response);*/
JSONObject jsonObj1 = jsonObj.getJSONObject("data");
String token = jsonObj1.getString("token");
System.out.println("Token is " + token);
String url1=API_TO_ADD_USER";
HttpHeaders httpHeaders1=new HttpHeaders();
httpHeaders1.set("CLIENT_ID", "VALUE_OF_CLIENT_ID");
httpHeaders1.set("CLIENT_SECRET", "VALUE_OF_CLIENT_SECRET");
httpHeaders1.set("Content-Type","application/json");
httpHeaders1.set("Authorization","Bearer"+token);
// JSONObject json1 = new JSONObject();
Filter u= new Filter();
u.setName("my_name");
u.setPhone("123456789");
u.setVendorId("P1234");
u.setAddress1("my_address1");
u.setAddress2("my_address2");
u.setCity("my_city");
u.setState("my_state");
u.setEmail("myemail#abc.com");
HttpEntity<Filter> httpEntity1 = new HttpEntity<>(u, httpHeaders1);
RestTemplate restTemplate1 = new RestTemplate();
//String response1 = restTemplate1.postForObject(url1, httpEntity1, String.class);
ResponseEntity<String> response1 = restTemplate.postForEntity(url1, httpEntity1, String.class);
// JSONObject jsonObj2 = new JSONObject(response1);
System.out.println("Json Obj111 is:"+response1);
I have faced a similar issue while using RestClient by not separating "Bearer" & Token with space, so I would go httpHeaders1.set("Authorization","Bearer "+token) and you should be fine.

POST x-www-form-urlencoded

I've been reading the following and trying to send a POST request with Spring Boot, using RestTemplate.
HttpHeaders headers = new HttpHeaders();
headers.add("content-type", "application/x-www-form-urlencoded");
final String body = "clipmessage={ bridgeId: \"" + user.getBridgeId() + "\", clipCommand: { url: \"" + setLightState("3") + "\", method: \"PUT\", body: { \"on\": " + state.isOn() + " } } }";
final String url = API_ADDRESS + user.getAccessToken();
HttpEntity<String> entity = new HttpEntity<>(body, headers);
restTemplate.postForEntity(url, entity, String.class);
If I log the URL and the body and send the exact same in Postman, it succeeds. However, not when I send it from my Spring Boot application.
I'm guessing that special body has to be sent in some special way which that I am not aware off?
Anyone has any tips on what to try here next?
UPDATE 1:
I tried the MultiValueMap as suggested, but did not get that to work either.
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
final String body = "{ bridgeId: \"" + user.getBridgeId() + "\", clipCommand: { url: \"" + setLightState("3") + "\", method: \"PUT\", body: { \"on\": " + state.isOn() + " } } }";
map.add("clipmessage", body);
HttpEntity<String> entity = new HttpEntity<>(body, headers);
I have the same scenario. solved after using the following code :
restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
FormHttpMessageConverter formMessageConverter = new FormHttpMessageConverter();
messageConverters.add(formMessageConverter);
messageConverters.add(converter);
restTemplate.setMessageConverters(messageConverters);
Parameters and headerpart
...
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
parameters.add("signature", "signature");
//other parameters
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(parameters, headers);
ResponseEntity<ResponseMessage> responseEntity = restTemplate.postForEntity(url, requestEntity, ResponseMessage.class);
ResponseMessage respMsg =responseEntity.getBody();
logMsg.append(",HTTP STATUS=").append(responseEntity.getStatusCode()).append(", RES:").append(marshal(respMsg));

Authorization for Google Drive Push Notifications for Java

I am trying to get push notifications from a resource on Google Drive to my server. I have been looking at this example:
https://developers.google.com/drive/v3/web/push
And I have tried translating that to Java into something like this:
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("id", "36d00d08-000d-4723-91bc-a1a6ec302e59");
map.add("type", "web_hook");
map.add("address", "https://mydomain.appspot.com/rest/drive");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<String> response = restTemplate.postForEntity(uri, request, String.class);
I have previously been using Googles libs for Drive to access files. In those cases I didn't need to create the request in such a "manual" way. I have used the class GoogleAuthorizationCodeFlow with a token to authorize my requests. I'm not sure how I should do that with RestTemplate. I am guessing that I need to do something like:
headers.set("Authorization", X);
What should X be here? Is that even the right way to approach authorization?
Edit:
Here is my attempt by reading a secret. The result is HTTP 401:
#Override
public String startListening() throws IOException {
final String fileId = "omitted";
String uri = "https://www.googleapis.com/drive/v3/files/" + fileId + "/watch";
HttpHeaders headers = getHeaders(getSecret());
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(getProperties(), headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.postForEntity(uri, request, String.class);
return response.getStatusCode() + " " + response.getBody() + " " + response.getHeaders();
}
private static HttpHeaders getHeaders(String theString) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer " + theString);
return headers;
}
private static MultiValueMap<String, String> getProperties() {
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("id", "some uid");
map.add("type", "web_hook");
map.add("address", "https://mydomain.appspot.com/rest/drive");
return map;
}
private static String getSecret() throws IOException {
InputStream in =
ConcreteDriveListenerFactory.class.getResourceAsStream("/drive_secret.json");
StringWriter writer = new StringWriter();
IOUtils.copy(in, writer, "UTF-8");
return writer.toString();
}
As #DalmTo has mentioned, X is for token. With regard to sample POST request for Drive API try this code snippet from this SO thread. It also uses a POST method.
public static void main(String argv[]) throws Exception {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost(
"https://www.googleapis.com/drive/v2/files");
post.addHeader("Content-Type", "application/json");
post.addHeader("Authorization",
"Bearer XXXXXXXXXXXXXXXXXXXXXXXXX");
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("title", "Test folder");
jsonObject
.addProperty("mimeType", "application/vnd.google-apps.folder");
post.setEntity(new StringEntity(jsonObject.toString()));
httpClient.execute(post);
}

Force.com Apex code counter part or equivalent code to Java

I am not certain if I am on the right path. Since I am not getting any data with the HTTP Request. I needed to convert this java code into force.com apex for me to be able to use a WTS web service.
public static HttpEntity getRequestEntity()
{
JSONArray jsonArr = new JSONArray();
HttpEntity entity = null;
JSONObject jsonElement = new JSONObject();
JSONObject jsonObj = new JSONObject();
JSONObject jsonObj1 = new JSONObject();
jsonElement.put("tenant",jsonObj);
jsonObj.put("companyKey",companyName);
String json = jsonElement.toJSONString();
try {
entity = new StringEntity(json);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return entity;
}
private static void GetEnabledUsers(String responseContent) throws ParseException, ClientProtocolException, IOException {
String url = "<endpoint>/services/UserService1.svc/GetEnabledUsers";
// Create an http client to perform the http communication
CloseableHttpClient httpClient = HttpClients.createDefault();
// Http request to specific web service. Request will be given to client
HttpPost request = new HttpPost(url);
// Create credentials for the authentication
CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credential = new UsernamePasswordCredentials(companyName+'\\'+userName, password);
provider.setCredentials(AuthScope.ANY, credential);
HttpClientContext localContext = HttpClientContext.create();
localContext.setCredentialsProvider(provider);
// Make the actual http request
HttpPost httpRequest = new HttpPost(url);
HttpEntity requestEntity = getRequestEntity();
if(requestEntity != null) {
httpRequest.setHeader("Content-type", "application/json");
httpRequest.setEntity(requestEntity);
}
CloseableHttpResponse response = httpClient.execute(httpRequest, localContext);
HttpEntity entity = response.getEntity();
String responseContent1 = EntityUtils.toString(entity);
System.out.println(responseContent1);
}
This is what I have so far:
String userName= '<userName>';
String password= '<password>';
String companeyKey = '<companeyKey>';
JSONGenerator jsonGenerator = JSON.createGenerator(true);
jsonGenerator.writeStartObject();
jsonGenerator.writeFieldName('tenant');
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField('companeyKey', '<companeyKey>');
jsonGenerator.writeEndObject();
jsonGenerator.writeEndObject();
requestBody = jsonGenerator.getAsString();
Blob headerValue = Blob.valueOf(userName + ':' + password);
HttpRequest requestEntity = new HttpRequest();
String authHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue);
requestEntity.setMethod('POST');
requestEntity.setEndPoint('<endpoint>/services/UserService1.svc/GetEnabledUsers');
requestEntity.setHeader('Content-Type', 'application/json');
requestEntity.setHeader('Authorization', authHeader);
requestEntity.setBody(requestBody);
Http http = new Http();
HTTPResponse responseEntity = http.send(requestEntity);
system.debug(responseEntity);
On difference seems to be around how the username is constructed for the auth parameter, change
Blob headerValue = Blob.valueOf(userName + ':' + password);
to
Blob headerValue = Blob.valueOf(companyKey + '\\' + userName + ':' + password);

Categories

Resources