I store identifier claims only (userid, etc.) (encrypted) in my jwt.
Then when I get the token on the server (API) I can do a lookup server side (db,redis, or local network api call) and retrieve all the associations to the userid (apps,roles, etc.)
However if you want to stuff more unencrypted claims into the jwt just be careful with the size since it will likely be sent on each request, but make sure to encrypt sensitive claim data.
Is this approach secure? Specifically:
- Is sending the username and password through JSON safe if done over HTTPS?
Yes. Headers, request params and request body are encrypted during the communication.
Once on the server-side, do not log the request body :-)
- How would I prevent unauthorised domains from making calls to this endpoint?
You can not. Basically, once the API is on the WWW, it's automatically exposed to all sort of malice. The best you can do is to be prepared and to be aware of the threats. At least about those that concern you. Take a look here.
A possible approach to the problem could be implementing (or contracting) an API Manager.
On-premise API Managers can reduce the attack surface because all the endpoints behind the AM are not necessarily public.
You could achieve the same result with some products in the cloud, but they are absurdly expensive for the mainstream.
Anyways, the API Management endpoints will remain exposed to attacks.
- Furthermore, how would I prevent programmatic logins?
If by programmatic logins you mean attacks by brute force, a threshold (max number of allowed requests per second) and a black list should be enough to deter the attacker's insistence. For further information, take a look here.
Many of the API Managers provide out of the box API Rate Limit configurations and Whitelists.
If you are familiar with the Google API Console, then you can guess what an API Manager can do.
- Should the refresh tokens be hashed before storing them in the
database, or am I just being paranoid?
Whether the refresh token is a plain UUID or anything else, I don't like to expose this sort of implementation detail. So I would suggest to hash it. To me, the more opaque are the implementation details of the security layer, the better.
Regarding the JWT security, take a look here.
- If the client were a web browser, how would I securely store the
refresh token on the client?
You might be interested in JSON Web Token (JWT) - Storage on client side.
Best Answer
I agree that the naming of the different concepts is confusing. When talking about authentication in a web context, there are several aspects to consider.
What information does the client send when authenticating?
How does the client send the authentication information?
What is the format of the authentication information?
Bonus: How does the client store the information locally
What do people mean when they say...