2

I am implementing RESTful API using javax.ws.rs. The response of the calls that I need to implement requires knowing which user is logged in currently. I tried making a separate call for the user login:

api.myapi.co.uk/authenticate?username=xxxx&password=xxxx

where I basically save the user information is a global variable and then tried to make another call to retrieve information from the database based on the user that has been saved earlier but I find the value as null during the second call. What am I missing? Is my approach wrong? do you have any suggestions please?

Zuzu JH
  • 607
  • 2
  • 10
  • 22

1 Answers1

3

Your code probably looks like this, right?

@Path("/")
public class MyResource{
  private String username;
  private String password;
  @Path("authenticate")
  public String authenticate(@QueryParam("username") username, @QueryParam("password") password) {
    if(!username.equals("zainab") || !password.equals("letmein"))
      return "Incorrect username or password";
    this.username=username;
    this.password=password;
    return "Sucessfully authenticated";
  }
  @Path("secret")
  public String secret() {
    if(username == null || password == null)
      return "Sorry, not authorized";
    return "You are authorized: "+username;
  }
}

If so, the problem is that JAX-RS creates a new Resource object for each request. A request to "/secret" then uses a new instance of MyResource, which has username and password as null.

Then, you might think, I'll just make it static! Then, your resource can't handle concurrent requests. What if Person A calls "/authenticate", then "/secret". Then Person B calls "/secret" without authenticating. He can then access "/secret" without authenticating!

Anyways, this violates the idea of RESTful services. The S in RESTful stands for "Stateless". This means that the server should store no state per client, and possibly give the user a token to pass with concurrent requests.

One possibility is to accept the username and password for every request to secret ("/secret?username=zainab&password=letmein"). Or you could implement token-based authentication, where the user calls "/authenticate" to get a token, and they pass that token on all later requests. Here is a link to help with that.

Also, note that username and password is usually not send in the URL as a query param, but instead in the Authorization HTTP header as such Authorization: base64encode("USERNAME:PASSWORD")

Kalana
  • 5,631
  • 7
  • 30
  • 51
vikarjramun
  • 1,042
  • 12
  • 30