orientechnologies / orientdb

OrientDB is the most versatile DBMS supporting Graph, Document, Reactive, Full-Text and Geospatial models in one Multi-Model product. OrientDB can run distributed (Multi-Master), supports SQL, ACID Transactions, Full-Text indexing and Reactive Queries.
https://orientdb.dev
Apache License 2.0
4.72k stars 870 forks source link

OrientDB authorization model can not be used as application level authorization #2229

Closed enisher closed 9 years ago

enisher commented 10 years ago

Such features as record level security encourage user to use OrientDB authorization as application level authorization. In other words, use OUser class as a main class for application user.

However there are some significant design issues in binary network protocol.

I suppose users would like to use approach similar to following

ODatabaseDocumentTx is not thread safe. And in binary network protocol each client session holds its instance of ODatabaseDocumentTx.

Thus session can not be used by several connections from different sockets because they can be handled in different server threads.

As a result we can not reuse session in different client threads.

This means that we have to open a new session for each user * each application thread. That leads to a need to reauthorize user in db for each thread. And as soon as user request can be handled by several application thread we have to store username and password at application layer.

Memory consumption

Having a thousands of active users may lead to thousands of opened connections in client connection manager. This could be memory consuming.

Possible memory leaks

If user is not logged out and socket was reused by other user, its session may remain in client connection manager forever. It won't be closed automatically as soon as socket still alive and used by application to handle another user sessions.

Session Id shouldn't be used as auth token

Session Id is serial, so it is not really safe to use it as a auth token.

No native way to make users rememberable

As soon as OrientDB supports only user/password authorization, "Remember me" feature could be implemented only by workarounds.

Automatic shutdown of session

Automatic shutdown of sessions that associated to broken connections are not designed for sessions that could be used by several connections.

So some session that is closed in such way may still be used by some other thread.

lvca commented 9 years ago

One question: if the client decode the token, change the RID from #5:3 to #5:1 and use this, what happens?

emrul commented 9 years ago

@rajohn96 I think the intent is to be able to share the connection across multiple users (per the use case that @phpnode talks about where each web-application user has a user in orientdb and can benefit from record-level security). In such scenarios it isn't workable to have one established socket connection per user so what's preferable is to re-use open sockets.

@lvca In this case the token will fail signature verification and the request will not be authenticated. This is true if the user changes any aspect of the token. The only way the user can circumvent this is if they can somehow obtain the signing key used to create the token.

phpnode commented 9 years ago

@lvca the sha1 should no longer be valid in this scenario so it cannot be forged.

@rajohn96 issue with binary protocol is that it currently relies on sessionIds being shared only amongst the same socket, I can't authenticate on connection A and then use that sessionId on connection B. Arguably it benefits from statelessness in the same way that the REST api does.

lvca commented 9 years ago

@phpnode + @emrul You're both right

About binary implementation we could do exactly the same. We can work on it after 2.0 ;-)

emrul commented 9 years ago

@lvca I will work a bit this weekend on this implementation. Do you know when you're planning to freeze development for 2.1? It might be a better thing to aim for and we would have time to perform decent security analysis, write tests and get HTTP and binary transports updated.

lvca commented 9 years ago

@emrul 2.1 is scheduler on end of the year. We could also provide it as additional method for a while (also to guarantee previous compatibility). No problem if we release it for 2.1, but if we could push something experimental for 2.0 we'd have more time to test and let users to test it.

gemmell commented 9 years ago

Is it going to make it into 2.0 (experimental or not)?!

lvca commented 9 years ago

@emrul did you have any progress on this?

emrul commented 9 years ago

@lvca I have written a clean implementation of JWT verifier and am working on a JWT signer. Once that's done I will be using it in my own product but am happy to release it to OrientDb under the Apache2 license. I don't think we'll make the 2.0 release but soon afterwards.

rajohn96 commented 9 years ago

@emrul this is outstanding; want to take a look at this ASAP. Now, (and not to get to far ahead of myself) on to the next challenge, external user management for Orient! @lvca, have you done anything with this as of yet, or know of anyone who has?

lvca commented 9 years ago

@emrul Awesome! I agree, OrientDB 2.0 final is very close (less then 10 days), but for 2.1 we have all he time to include and test it properly.

@rajohn96 I know ForgeRock uses OrientDB under the hood, but not as OAuth provider.

rajohn96 commented 9 years ago

@phpnode, now (after review of this approach and clearer thinking about the problem) I get the issue you are having; if there is some sort of interface that is NOT http based sitting between the user and the DB then this approach (or rather this implementation in its current form), while promising, doesn't get us over the line. In our case, we are looking at using Rexster as that intermediary component (with potentially others as well), for a variety of reasons, so we are presented with not only this problem but the same problem there (where a security related extension should do the trick nicely)

rajohn96 commented 9 years ago

@lvca, thanks for the update; what I was referring to is more to the point of OrientDB being able to support externally authenticated/authorized users; in Oracle (there I go again!) these users are called Enterprise Users, with credentials supplied from/maintained in an external OID/LDAP environment (such as ForgeRock provides), thereby simplifying database user management in the same way ForgeRock's OpenAM simplifies application user management. In my mind, this thread and that one go hand in hand WRT Orient's scalability

thecyman commented 9 years ago

Just wanted to add I've been thinking about this and speaking to @phpnode I think that JWT is the right solution. I hope we can get this done soon.

lvca commented 9 years ago

@emrul Did you publish anything on a public repository? This feature seems one of the most needed features now. We could help on it to put it in final 2.0. WDYT? But I don't want to push you :-)

a-unite commented 9 years ago

:+1: Luca, it will be really GREAT if will be available in 2.0.

emrul commented 9 years ago

Just an update, been discussing with @lvca and am currently working on an implementation that would see Jwt support available as a plugin. I will try to keep minimal any changes to OrientDb's codebase.

I do believe @rajohn96's requirement for external user auth can be met using this approach.

Just as a reminder for everyone, the work I am doing is limited to the HTTP protocol. The binary protocol will need to be updated separately.

emrul commented 9 years ago

Update:

I have completed the development (with a few missing bits) of token based authentication and have committed the changes to my GitHub: https://github.com/emrul/orientdb/commit/3d00fa50be5471c11f63efa238ecfd1b2e067766

Here are some details of what I've done:

  1. Everywhere in OrientDb that accepts a username/password in a method call now has an overloaded method which accepts an IToken. An IToken represents some type of authentication token that can be verified (e.g. cryptographic check), validated (e.g. check it hasn't expired) and used to obtain an OUser.
  2. I have created an OrientDb Handler (plugin) that implements an ITokenHandler interface. This interface is used to parse and generate tokens. The methods intentionally accept and return byte arrays so that a handler can be created for the binary protocol.
  3. When a user wants to obtain a token the getSignedToken() method is called. See the execute method of the class OServerCommandPostAuthToken. At the moment only the 'password' grant_type is supported but others can be added. One that we may want to add is a mechanism that allows users to generate tokens for other users.
  4. When a request is made with the token (e.g. by passing it as a 'Bearer' token in the Authorization header of an HTTP request it is parsed (and verified) and then validated. See the beforeExecute method of OServerCommandAuthenticatedDbAbstract. the validateToken method accepts a token, a command and a database name. It is possible to create tokens that restrict what type of commands can be executed by enhancing the validateToken() method. For example, if we did this you could generate tokens that only allowed SELECT queries.
  5. The token is passed through to the deepest layers of OrientDb and eventually ends up in the authenticate(final IToken authToken) of OSecurityShared. In here we call Token.getUser(). The token implementation can return an OUser (this is specifically to support @rajohn96's requirements of external auth - see below). If the token implementation isn't able to return an OUser then it MUST return the username - via IToken.getSubject().

Notes:

@rajohn96: For externally managed users I believe you will need to implement an ITokenHandler that encodes enough information to create an OUser instance (possibly syncing it from some external directory?). My current implementation creates an OUser instance from the user's RID contained in the token - yours may have to do some syncing with your user source.

.... In summary, I believe I've created a very flexible and fully externalised method to support token based authentication for OrientDb.

mattaylor commented 9 years ago

Awesome! Any chance of a pull request to get this into 2 0?

lvca commented 9 years ago

@emrul Thanks so much for this contribution! @tglman will merge this and will implement the binary support in the next days.

@mattaylor this is definitely stuff for 2.0 (a client paid for this). That's why we're delaying the release a bit.

mmerdes commented 9 years ago

we are currently starting to evaluate orientdb and token-based auth as well as ldap-support definitely would be key benefits. any idea when 2.0 will be final?

lvca commented 9 years ago

@tglman is working to the Token based authentication. It should be ready in few days. After a test period we can release 2.0 final. Let's say 2 weeks.

lvca commented 9 years ago

Emanuele will continue documentation and tests in #3155