This is a classic session management scenario. There are multiple angles though. Let's walk through your workflow.
The user authenticates their credentials to the server (Note: All passwords will be saved in a hypothetical users table and will be hashed + salted)
This is all good, assuming you are using a strong password hashing algorithm like Argon, bcrypt or PBKDF2.
-Assuming the credentials are correct and verified, the server then generates an authentication token which is created by concatenating the username, a timestamp and a random string of text. The concatenation will be hashed (the hash will be the token)
In this step, you are creating a self-describing token which is most commonly used in stateless-session management. If you really want to go stateless use JWTs. There is no reason to use a custom algorithm. Beware though going stateless has limitations (no "log-out", no single-session, no idle timeout, no one-true session state, etc.)
You also store the token in the DB which defeats the purpose of stateless tokens. Take your pick here. If you need a single-session setup go with a stateful approach with an opaque token. If you want statelessness, you need to sacrifice the single-session setup as that goes against the very definition of being stateless on server-side.
-This hash is then stored in the database and is transmitted back to the client (Using SSL), which will be stored and sent in the headers along with the username for every request the client makes.
With a self-describing token, there is no need to send the username along as it is already in the token, integrity protected. (Hint: JWT)
-The token and username are then verified by the server to match the ones in the database.
If you go stateful this would be a simple lookup: which user belongs to this session? If you go stateless this DB lookup is eliminated and you only need to verify the token integrity and expiration.
-Note: Every time a new successful login is made, a new token will be generated and then replaced in the database preventing multiple devices to be logged into the account at once.
As described above, if this is a must-have, go stateful with an opaque Bearer token.
Assuming all database queries are parameterized, what other types of hypothetical vulnerabilities could arise from using a system like this?
There is nothing wrong with your approach however, I recommend you decide how to handle sessions (stateful or stateless w/ JWT). Both routes work and they have trade-offs. A hybrid approach also works, but that needs to be justified by the use-case and from what I understand, your's doesn't seem to fit that.
Once you have that, follow standard security advice:
- choose strong keys
- limit secret exposure
- use well-built libraries instead of coding your own crypto
- use strong algorithms
- etc..
You can also check out the web API authentication guide I put together for alternatives.