Authentication scheme using HMAC I have an authentication service, a client and an application service. 

The client needs to use the application, but they have to be authenticated first. I'm trying to create a simple scheme to do this and what I've come up with is:


The client contacts the authentication service, sends its metadata (e.g. license number)
The authentication service validates the client (i.e. checks the license against a database) and returns a token containing: some new metadata needed by the application, a timestamp telling when the token was created and a HMAC-SHA256 for the mentioned data.
The client uses this token to contact the application service and perform its tasks
The application service checks a client's token by validating the HMAC-SHA256 (thus confirming that the token was generated by the authentication server) and also checks the timestamp, confirming that the token is still valid. If the operations succeed, it will use the metadata from the token to perform the task required by the client.  


All communications between the authentication service and the client, as well as between the client and the application service are done over HTTPS. The secret key shared between the authentication service and the application service will be something large (e.g. at least 64 bytes)

My question is if anyone sees any flaw in this scheme. 

PS: I know OAuth 1/2 exist, but to be honest I'm horrified to look into those. What I need is something really simple, like that "JWT stateless session" everyone recommends against. Oh, and I don't want to use JWT or Paseto because I've done a benchmark and a simple HMAC is faster (than Paseto at least)
All communications between the authentication service and the client, as well as between the client and the application service are done over HTTPS. 


So at least the servers are authenticated to the client, and the communication channels are private.

This is not really an authentication problem. What you have is a capability-based access control while the license (and the token) serves as a capability list to authorise the user's operations. Your goal (I guess) is that only users who possess a valid license can access the application. The server's token is MAC protected so integrity should hold (assuming good a MAC scheme is used and good key management). The application server can be sure the token was generated by the authentication server, and not long ago (timestamp). 

The first problem is whether the client needs to prove it possesses the license. Presenting the license number is not enough for this, because the number is a string which can be stolen or even simply enumerated. If you need a proof of possessing, need the license needs to be linked to some verifiable secret only known to the owner e.g. a secret key, a password. This is similar to when spending bitcoin you need a private key for the account. In bitcoin, the account number is equivalent to license number in your case, and a signature verifiable using the public key associated with the account number is the proof of possession. If you don't care and anyone who has the license number can use your service, then this is not a problem and you have the next problem.

The next problem is to prevent multiple users from sharing one license. This is similar to the double spending problem in e-cash, and in your case it can be solved easily since you have a centralised system. For example, when issuing a token, the authentication server can keep a record of the license number and the token expiration time. If a user comes with a license number that already has a token issued and the token hasn't expired, then the server can reject issuing a new token. The application server can also link tokens to sessions to ensure each token can initialise only one session. Of course, there are practical issues like the user may lose his token because the computer is shut down unexpectedly etc., and the full solution needs to cover those.