This is a broken design because a GUID is not supposed to be secret, yet from what I understand it provides access identical to entering your username and password on the website.
In theory the design is solid. Protect the GUID as if it were the user's password and case closed.
In practice this introduces a lot of problems.
Example: I start working at your company today. I'm told to write a search feature so that you can find other users by email address. I would probably code the search results as a page showing a list of links to profiles, which contains something like <a href="/user/${user.id}">${user.name}</a>
. Upon checking which columns to use I discover that the id
field is called guid
and the name field is called fullName
. I test this. It works. I push the code.
Without realizing it, I just leaked the user's GUID which basically provides full account access. Now you can hijack any account of whom I know the email address.
Right now the programmer may constantly have in the back of his mind that knowing the GUID provides full account access, but in a few months it won't be something you think about a lot anymore. Since it is, I assume, the only unique way to point to an account, you need to use it in a lot of places. Especially for user interaction this might be a problem (perhaps users can form companies or groups, share folders, you name it).
A better way would be to separate identification and authentication. The GUID identifies a user whereas a security token authenticates a user. This completes the Identification, Authentication and Authorization (IAA) parts of a security system: the system decides the Authorization based on the Identification after verifying the Authentication. This is why, in addition to passwords, we also need to fill out a username on websites. Using only one or the other is generally a bad idea.
All places where the GUID is currently used should be replaced with the newly generated security tokens. For example a request might look like this: /API/2.0/doAction?GUID=${user.guid}&token=${some_security_token}
. Note that these tokens must be fully randomized (odds of guessing it must be around 1 in 2^128).
There are many ways of generating these security tokens. Many websites generate sessions, but you could also use an extra database field. Whenever API calls are made, the user is authenticated by this random field. The field should be called something that makes it clear it's not supposed to be known to others.
Again, in theory it doesn't really make a huge difference in the system's design whether you use a random GUID or another randomly generated field for authentication, but in practice I think it does prevent a lot of big security errors, especially when the site has any kind of user interaction (but also if it doesn't, e.g. a password reset feature might accidentally expose the GUID after entering a username or email address). It simply reduces the number of attack possibilities.