-
Notifications
You must be signed in to change notification settings - Fork 873
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OrientDB authorization model can not be used as application level authorization #2229
Comments
just to reiterate how severe this is, it makes it impossible to use orient's permission model efficiently for most websites. It renders |
How about tackling this from a different method. I think this is actually two issues, the first is connection pooling and the second is session handling across the pool. To address connection pooling the application could have its own account (typical setup) and allow it to "switch user" to the actual user's account. This could be implemented as an additional privilege with a role restriction. The application in this case would be responsible for validating credentials initially and it could be given a ticket for future requests. The tickets could be infinite lifespan (tied into their session record), max lifespan, or have a max inactive lifespan. This approach could also be used to allow external authentication (to Active Directory or some external service) and OrientDB would have to "trust" the application in its switch user capacity. PostgreSQL supports a portion of this workflow through SET ROLE. To handle the session state issue OrientDB could just store session data in a cluster (either memory or disk based) with each user having one record (and record level permissions in-place). A plugin could be written to handle purging old session. |
@ruckc I agree that this is two issues, but I don't really like your proposed solution - why do we need a special role and "user switching" when global sessions, ala HTTP, could easily solve the problem without having to introduce a greater degree of trust for the client app? I think it's brittle and a lot of overhead if the application has to do a I agree we could create a new |
Copied / pasted from another issue:
|
So, the solutions to this type of problem across other databases/software:
I think the easiest/lightest method is using Unix's switch user ( One hinderance to the connection pool above would be implementing scrypt/bcrypt hashing due to the time requirements to validate the credentials over and over. This could potentially be mitigated by having a in-memory cache of sha256 hashes of recently validated passwords. Something to keep the model flexible enough would be overriding openDatabase(String user,String pass) to openDatabase(Credentials creds), which would support user/pass authentication along with PKI or any other two factor authentication. |
@ruckc the point of The binary protocol already has a thing called a |
@phpnode so generating a random long could be good enough for you? What else is missing? |
@enisher exactly, that's the only remaining issue I think |
@lvca @enisher on second thoughts, there's a remaining problem - AFAIK sessionIds are not shared between orientdb servers, which makes working with server clusters awkward. This is another reason to go with a new |
Hi guys, |
@giastfader totally agree, in fact I meant that the session key itself should be long (i.e. unguessable), not that it should be a |
@phpnode and @giastfader Thanks for your suggestions. I don't know if writing the record to the database could be a good idea because we've Hazelcast under the hood and creating a clustered Map with sessions it's straightforward. The problem could be: how many sessions could we have? thousands or millions? |
@lvca potentially millions for the largest of sites. Without the record approach, how would we expire an existing session? how would we find the active sessions for a given user etc? Presumably via new SQL commands? |
@lvca however I think that you should pay attention if you try to solve a problem that maybe, and I mean maybe, should not be solved by the database engine. Trying to solve this problem could lead you in scalability issues, and sessions (and stateful machine in general) IMHO cause the biggest concerns in scalable systems.
PRO: the db engine does not need to store anything, clients don't need to store username/password, just the tokens WDYT? |
By using Hazelcast it's vert easy: we have such Map to manage and all the nodes see the same map. So all the lookups works in distributed fashion. Current background task that purges all the expired sessions would work in the same way. WDYT? |
@lvca sounds reasonable I think, but I'd imagine it won't be possible to query, e.g. there'll be no way to do the equivalent of this: SELECT COUNT(DISTINCT(user.name)) FROM OSession; to retrieve the number of currently online users. |
@phpnode No, but we could create a "memory" cluster (non-persistent) and in case of distributed architecture the cluster would be replicated among servers. |
@lvca this would be ideal i think! |
Hi, so speaking with the @phpnode the blocking issue is just the "migration" of the session cross connection/server, so we thought to two possible easy solutions: the first one is a random generated uuid, to use a key of a distributed map, where in the value we have the detail of the session, this uuid will replace the current sessionId, but will be used also for new connections.
disadvantages:
The second solution can be generate a token as described by @giastfader
disadvantages:
all the other features, like the possibility to query the active session, are more a nice to have and not blocking right now ;) shall we choose one of the two ?!?! |
Ok, so we don't need concurrent request processing in the same session for now, that is much easier. The second proposed solution seems more sophisticated as for me. |
Definitely think that the first option is much easier and faster. All we'd need is to store a map of UUIDs to user ids. Since we can reliably assume that user ids fit in integers, this can be as little as 20 bytes per user (plus a little more if we want to do TTLs). Doing this doesn't really make the server any more stateful than it is at the moment - the server already keeps a map of sessionIds to userIds, we'd just be making that map shared rather than being per connection. If we go with the second option, I don't think it's possible for the server to expire a key, so we'd have no way of revoking session ids for users that have been deactivated etc. |
is this a 2.0 thing now? |
If a decision to use OUser as an authorization entity is made it is important to add more security into its model. I suggest not just encrypting password with SHA-256 but also adding a 'salt' field into OUser class and using it during encryption. What do you think? |
@young-druid there's another issue for that - #2242 |
Oh, right. Thanks for that. I put my comment with a link about hashing in Java there. |
@lvca can this be part of 2.0? IMHO it's really essential and blocking one of Orient's most useful features. |
Emanuele will continue documentation and tests in #3155 |
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
Issues with concurrent requests
ODatabaseDocumentTx
is not thread safe. And in binary network protocol each client session holds its instance ofODatabaseDocumentTx
.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.
The text was updated successfully, but these errors were encountered: