Search code examples
javaauthenticationplayframeworklogicapi-design

How to authenticate an user with token in an api call?


I am developing an API using PlayFramework and some endpoints need to be secured with authentication. In these reqs the client pass in the HTTP headers the user id and the auth token and the server validates.

I am using this logic with annotations, so I just put the annotation in the method that I want to be secured.

So I was using this logic, until I realized a mistake. Let's say we have user A and B. If user A sends in the Headers its id and auth token, but in the json body it sends the user B information, user A can make calls in the name of user B.

So I need to check if what is passed in the headers makes sense with it is passed in the json body (probably validating if the ids are the same).

My doubt is how to achieve this. Do I need to create different annotations for my methods to accept the different kinds of json and validate if the header is the same?

I tought about putting some code, but I think it is more a logical question.

Thanks!


Solution

  • If I understand your problem, I would say it is an authorization issue.

    Authentication versus Authorization

    Authentication is the process of ascertaining that somebody really is who they claim to be.

    Authorization refers to rules that determine who is allowed to do what. E.g. Adam may be authorized to create and delete databases, while Usama is only authorized to read.

    I am not familiar with Play Framework but it probably has the same features as other popular frameworks.

    In your case, you should somehow identify that is the user allowed to change some resources. I don’t know what kind of API or content you have so I just need to suggest one solution.

    I hope this answer helps you going forward and try something that could work. If I missed some critical information, just ask more.

    Lets assume we have following resources:

    /user/1001/address
    /user/1002/address
    

    1001 is ID for user A. 1002 is ID for user B.

    Now, if user A calls /user/1002/address and try to post some new data, it should not be allowed. So now we have a few choices to authorize the action.

    First way

    You said that user ID is part of the header. Then in your action, before accessing the resource, you could check if resource URL user_id match to the header user_id. If not, the user is not allowed to modify content.

    Of course, we can have a use case where admin user should be able to do that. Play Framework probably has some kind role-based access control feature that can help.

    In this way, there can be a security issue. If the header contains user A ID, it can be modified by the caller and pretend to be user B.

    Second way

    Almost similar like the first one. If you can have user_id in your JSON content, then you can try similar logic. The same security issue rises because the client can change the content etc.

    Third way (I prefer this)

    If you use token that can carry data, then you can use this logic. I mean that you have JWT token or similar implementation

    With that token, you don’t need to add user id in the header. User id can be inside the token. On the server side, you can read the content from token.

    Now, if user A calls resource /user/1002/address and try to modify data, it should not be issue anymore. You can just read the user_id from the token and compare it to user_id int the url address, for example.

    Client can’t change the token content because it is generated on the server side and contains only data you want.