Reputation:
I'm trying to make a JWT-based authentication process.
/users/login
Authorization: Bearer ${jwt}
header to /users/profile
jwt
, by signature, is valid, the user information is returned, else respond with Unauthorized
Now, I just realized; how is this safe? Can't any user simply read the cookie from the browser and curl request to /users/profile
and it will be valid?
I'm really still a newbie in this, so could you please explain? Here's some simple test code
@Path("users")
public class UserResources {
@Path("login")
@POST
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response loginUser(UserInput userInput) {
String compactJws = Jwts.builder().setSubject(userInput.getUsername()).claim("name", userInput.getName())
.signWith(SignatureAlgorithm.HS256, Server.SECRECT_KEY).compact();
return Response.status(Status.OK).cookie(new NewCookie("jwt", compactJws)).entity(compactJws).build();
}
@Path("profile")
@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response getUser(@HeaderParam("Authorization") String compactJws) {
try {
if (compactJws == null || compactJws.trim().isEmpty() || !compactJws.startsWith("Bearer ")) {
throw new SignatureException("Invalid access token");
}
Jws<Claims> claims = Jwts.parser().setSigningKey(Server.SECRECT_KEY)
.parseClaimsJws(compactJws.substring("Bearer ".length()));
return Response.ok(new String("Subject: " + claims.getBody().getSubject() + "\nName: " + claims.getBody().get("name"))).build();
} catch (SignatureException e) {
return Response.status(Status.UNAUTHORIZED).entity(e.getMessage()).build();
}
}
}
Upvotes: 9
Views: 1469
Reputation: 53600
Validating the signature guarantees that the JWT hasn't been forged or tampered with. As you guessed, the JWT can still be stolen. If someone steals the token, they can make impersonate your user and make requests.
There are three important things to do:
Use HTTPS - end-to-end TLS prevents someone intercepting or sniffing the requests on the wire and stealing the token.
Store tokens securely on the client - If you store your token in a cookie, make sure to use the HttpOnly flag to prevent theft via XSS, and use CSRF protection on all your forms. See Cookies vs. HTML5 Web Storage for a deeper explanation.
Expire the tokens - if all else fails, and a token does get stolen, a sensible expiration (exp
claim) will ensure that there's only a limited window of time that the token can be used to cause damage.
Upvotes: 10