0

I'm building a U2F-compliant client that simply needs to send a JSON object with the following structure to a POST URL:

{
  challenge: [Base64-encoded String of 32 bytes],
  registrationData: [Base64-encoded String of variable bytes]
}

Here is an excerpt of my code, which runs fine and throws no errors:

import okhttp3.FormBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;

public interface Registration {
  @POST("register")
  Call<ResponseBody> register(@Body RequestBody body);
}

private void sendRegistrationResponse(String baseURL, String challenge, String data) {
  RequestBody data = new FormBody.Builder()
                    .add("challenge", challengeB64)
                    .add("registrationData", data)
                    .build();

  Retrofit retro = new Retrofit.Builder()
                    .baseUrl(info.getString("baseURL"))
                    .build();

  U2FServices.Registration reg = retro.create(U2FServices.Registration.class);
  Call<ResponseBody> regCall = reg.register(data);
  regCall.enqueue(this);
}

The debugging server is built with Node, and its POST "register" route is successfully called by the client every time. The issue is, the body of the request is always empty.

exports.register = function (req, res) {
  var body = req.body; // {}
}

I imagine the issue lies with the FormBody.Builder(), but I can't find any documentation or code giving a clear example on how it works. Any help is greatly appreciated!

Robby Cornelissen
  • 91,784
  • 22
  • 134
  • 156
Sam Claus
  • 1,807
  • 23
  • 39
  • 2 questions. Is your node server expecting "application/x-www-form-urlencoded"? Any reason that you want to use RequestBody instead of converter? Also you may want to add "retrofit2" tag as this is for Retrofit2. – Emma Jun 22 '16 at 23:26
  • @Emma I just don't see the point of using a converter. All I need to do is send a simple JSON with the properties "challenge" and "registrationData". Also, I didn't specify any settings for the POST on the server. I'm actually new to web programming, and not familiar with headers, etc. I have been told that by default the request will be read as octet-encoded and should just work if I send a Java String to the server. – Sam Claus Jun 23 '16 at 14:29
  • I see. That is fair not to use converter. – Emma Jun 23 '16 at 18:36

1 Answers1

3

Let's try this - (hope your node server is expecting application/json) or else we need to change that part.

RequestBody data = RequestBody.create(MediaType.parse("application/json"), stringJson);

Apparently, FormBody's default media type is "application/x-www-form-urlencoded" and if your node server is not expecting this request type, it might fail.

If you can look up your node's config, it is good to check it up to make sure what media type that a request should form with.

This is an example of node with express server's config.

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

This node server can expect both json and form url encoded.

Let me know if this works or not.

Emma
  • 8,518
  • 1
  • 18
  • 35
  • Figured out that my Mac is blocking the server port for some reason, even though Firewall isn't even enabled, and it wasn't blocking before. Won't be able to check if the body parsing options help until I fix that, so there might be a little delay in the debugging. Thanks so far though. – Sam Claus Jun 24 '16 at 12:44
  • I fixed my other issues and tried out your solution. The app communicates perfectly with the server now. Thanks! – Sam Claus Jun 24 '16 at 16:11