I am building a web application where the front-end is a single-page-app and the back-end serves it through a RESTful API. I want to make sure I implement user authentication with the best security practices.
I am planning a system that will perform the following steps to ensure authentication security:
Signing up (or changing password):
- User sends username and password to server in plaintext via HTTPS
- Unique salt is generated with Python's
urandom
function (32 chars) - Salt prepended to password
- Salt + password is hashed with
bcrypt
- Salt and hash stored in database table (SQL database, slower than key-value but I'm not too concerned about superspeed for logging in)
- Random session id generated with
urandom
(32 chars) - Session id stored in key-value db (Redis? Key: session id, value: user id) and sent to client along with user object (obviously without salt and hash)
Logging in:
- When logging in, user sends username and password to server in plaintext via HTTPS
- Server retrieves salt and hash from users entry in SQL db
- Salt prepended to password and put through
bcrypt
- If both hashes match, session id generated with
urandom
and entered into key-value db - Session id sent to client with user object
Any other request to the server:
- Request and data sent via HTTPS including user id and session id
- Key-value db searched with user id, if session ids matching, return requested data along with user object
- If not matching, return error 401
Session handling:
- Allow more than one session for the same user
- Set expiration of session to 24 hours, when accessed, put back to 24 hours
- Allow persistent session which expires in 1 month, when accessed also put back to full expiration time
- On logout, remove session from Redis
Will this be a secure, scaleable and fast (when necessary) system? If not, where are the security flaws? What could I do to improve this process? Is this vulnerable to CSRF attacks? Does it improve security to add the client's IP address and USER_AGENT to the session or is this overkill?