I've been inspired by a question over on Code Review, which boils down to: What is the proper way to authenticate a user without a database?

Would it be the exact same process if you stored credentials in an array, or an XML file, or even just a plain ol' text file?

For example, let's examine the following PHP code:

$credentials = array(
    'UserA' => '$2y$10$PassForA',
    'UserB' => '$2y$10$PassForB'

$username = $_POST['username'];
$password = $_POST['password'];

if (isset($credentials[$username]) && password_verify($password, $credentials[$username])) {
    // Successfully authenticated
} else {
    // Permission denied

Is this a perfectly acceptable way to store credentials? If we were to grab the username and hashed password from an external file (XML/txt), would things need to be treated any differently?

  • 1
    ssl-client-certs we use here – that guy from over there Jun 26 '14 at 5:09
  • 4
    The obvious answer is: Use a database? I don't see a clear motivation for building a web service without a database or any other persistent data store. – D.W. Jun 26 '14 at 15:01
  • 2
    @D.W. is right -- in fact, any method for storing credentials is, once you start scaling it to real world uses and real world potential issues, going to boil down to "use something that behaves like a database would" – Shadur Jun 27 '14 at 9:36
  • If you want a small service for few users and want to avoid a database server, I strongly recommend SQLite. It is a small library and the data are in a single file, but still provides ACID and is generally pretty fast. The disadvantage is database-wide lock for write, but if you only have a few users and do just handful updates a day, it is appropriate. And it is easy to switch to a database server if you scale up. – Jan Hudec Jun 27 '14 at 9:37
  • And then there is FireBird, that can run either as server or embedded, so you can start with embedded and switch to server as you scale up. It's still heavier than sqlite in embedded mode, but you won't have to do any tweaks to the SQL at all. – Jan Hudec Jun 27 '14 at 9:42

An XML file holding user credentials is a database. The definition of a database isn't limited to MySQL (or whatever it is you had in mind).

How users are authenticated and where exactly their credentials are stored are two entirely separate concerns. A bcrypt hash is a bcrypt hash, regardless of whether it's stored in a plaintext file, a MySQL table or a MongoDB document.

Of course different types of database systems work differently and required different ways of updating and loading data, but this has nothing to do with user authentication specifically. Those are general issues of data storage.

| improve this answer | |

authenticating without a database

I'm going to interpret this as meaning

Is it possible to design a challenge-response system which lets a principal prove that they are who they say they are without using an amount of storage that scales with the number of principals? I.e. using storage that is O(1) w.r.t. the number of principals.

One way to authenticate a principal is to have them present something only they or you could know. If someone knows it, and that someone isn't you, then it's them :)

Cryptographic signing allows you to generate strings (tokens) that

  1. you can give it to someone
  2. you can forget it
  3. they can give it back and you can verify that it really was given by you

If you trust the authenticating principal not to leak secrets that gate access to their account you can give them a signed output, and use signature checking to authenticate them.

If you can't trust them not to leak secrets, then you can't trust them not to leak a password that you've hashed into your database anyway, so the possibility of naive users leaking a secret that can be replayed is not a reason to prefer passwords over signing.

Simple signature checking doesn't provide for fine-grained revocation but that's an authorization problem, not strictly an authentication problem.

| improve this answer | |
  • 2
    +1 Great answer to the question the title suggests though the asker clearly didn't have it in mind. – Jan Hudec Jun 27 '14 at 9:39
  • @Jan, Yeah. I just read the link from the OP closely. What's the usual protocol? Delete the answer or leave it so searchers who interpret the question differently can find it? – Mike Samuel Jun 27 '14 at 11:54
  • Definitely leave it here. It is interesting and Google can still find it. – Jan Hudec Jun 27 '14 at 12:53

Authenticating that way is fine, but the real trick is doing your credential management and updates. How do users change their passwords? Are you rewriting your source to do that?

I've certainly seen authentication credentials stored in XML, JSON, and CSV files. You need to take steps like acquiring a lock when modifying the file, handling crashes, etc, which are normally taken care of with a database.

| improve this answer | |
  • I think it's assumed these creds would not be changing. Could you elaborate "acquiring a lock when modifying the file"? – Alex L Jun 26 '14 at 1:18
  • 4
    Well, having credentials that don't change is problematic... As far as acquiring a lock, you don't want two processes changing the same file... – David Jun 26 '14 at 2:10
  • 4
    Actually, you DO want two processes accessing the same file. What you don't want is two processes accessing the same file and changing it without proper arbitration. When you deal with file-based data, things like vertionizing and transaction management starts to be problematic. – Stephane Jun 26 '14 at 7:20
  • @Stephane Not so much "problematic" -- but you've basically just described the point of using a database. – Shadur Jun 27 '14 at 9:35

For reference, the unix password system by default authenticates to a flat file that isn't a "database" (/etc/passwd and /etc/shadow). Having a DB is not about security but about performance. When you have to look through millions of lines to find user JohnDoe, performance suffers. On the other hand, a well indexed DB can find the same user almost instantly.

This also applies to storing the user credentials directly into an array - how will you persist the data and how will update records if it is all hard coded?

Since you are asking on the security page, I assume you are asking what are the best practices for storing a password on a flat file system. Well, the answer is the same as if it was a DB. You should salt and hash your passwords so that if the file is ever compromised, nobody can reverse engineer everyone's passwords.

| improve this answer | |
  • /etc/passwd and /etc/shadow are referred to as "password database" by most documentation. Because, well, they are "database". Flat file one, but database nevertheless. – Jan Hudec Jun 27 '14 at 9:33

Encapsulating the passwords using OOP concept is better when implementing on small scale where the username and salted password is fed to member function of class holding the array of user credentials for the purpose of authentication.

| improve this answer | |
  • 1
    That array is filled somewhere. So this means that either the array is filled from some persistent storage anyway, or the user credentials are hard-coded. I sure hope nobody intends to hard-code the user credentials. – S.L. Barth - Reinstate Monica Oct 3 '17 at 11:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.