Open Source Content Management Framework

mRFC 0045: (Mjölnir) Midgard authentication system

  1. Revision History
  2. Background
    1. References
  3. Needs
  4. Implementation
    1. midgard_user
      1. Properties of an object
      2. Methods
      3. Query object(s)
  5. Authentication
  6. Authentication state stack
  7. MgdSchema objects and metadata
  8. Legacy authentication
  9. Midgard root and Midgard domain 0 (SG0)

Revision History

  • 2009-06-14, created by Alexey Zakhlestin
  • 2009-07-06, major updates by Piotr Pokora
  • 2009-07-23, major updates which include ideas from developers forum by Piotr Pokora

Background

Current Midgard's authentication system uses several hardcoded scenarios and doesn't reflect needs of modern web-world. This mRFC focuses mostly on implementation part, as it's impossible to describe idea for any single authentication mechanism.

References

  • http://trac.midgard-project.org/ticket/1199
  • http://trac.midgard-project.org/ticket/1037
  • http://trac.midgard-project.org/ticket/1036
  • http://www.midgard-project.org/discussion/developer-forum/midgard_authentication_implementation_proposal/
  • http://www.midgard-project.org/discussion/developer-forum/new_auth-system_mrfc/

Needs

Midgard needs modular authentication system which would allow developers to implement various authentication schemes for their needs. Midgard core shall provide abstraction layer API for any authentication type provided on any level and written with any language for which Midgard core provides bindings. Any new authentication type shall not require additional routines to be written in core or on language bindings level.

It should be possible to use it for implementing at least the following:

  • Username and password stored in Midgard itself
  • Username in Midgard, password via PAM
  • Apache-based authentication where Apache gives us the username (Kerberos for instance)
  • Apache-based authentication where Apache passes us a token we must authenticate with (http://www.gpgauth.com/ for instance)
  • Delegated authentication and/or registration (Shibboleth, Facebook Connect, OpenID)
  • Token-based authentication (OAuth)

Implementation

Basic idea is to provide routines which would be very similar to already known Midgard "Trusted" auth type. Midgard core shall implement midgard_auth and midgard_user classes.

midgard_user

Properties of an object

  • guid/uuid - read only object's identifier guid/uuid property should be unique per table and mandatory for proper authentication.

  • login - string which identifies user (username/nick) non unique string with allowed empty one

  • password - stored in text/blob column so any data can be written to non unique string with allowed empty one

  • person - guid/uuid, a reference to midgard_person object non unique guid or uuid

  • is_admin - admin flag boolean value which marks user as admin

  • type - user defined field which holds integer value

    If more properties are needed, a new MgdSchema class which extends midgard_user should be created.

Methods

  • array query(array properties) Fetch midgard_user object(s) using given properties as query constraints. If all properties match, object(s) is(are) returned from database.

    Example, get all particular user accounts:

    $tokens = array("login" => "john", "type" => MYAPP_AUTH_TYPE_CONST); $objects = midgard_user::query($tokens);

    if (empty($objects)) print "No account for user 'john'";

  • boolean register(void) Creates new midgard_user objects' record in database.

  • boolean update(void) Updates midgard_user object's record in database.

    Example:

    $user = new midgard_user(); $user->login = "john"; $user->password = "";

    if ($user->register()) print "Created new account for user 'john'";

  • midgard_person get_person(void); Returns midgard_person object associated (if any) with midgard_user instance.

  • boolean login(void) Login shall associate midgard_user object with midgard_connection, which shall emit 'auth-changed' signal and set proper access error code. User without guid set shall be considered invalid, 'auth-changed' signal shall not be emited and proper access error code shall be set. Only midgard_connection shall be responsible for setting error codes and signal emission.

  • boolean logout(void) Logout shall unset already associated midgard_user object. midgard_connection shall emit 'auth-changed' signal if associated with any midgard_user. No error code shall be set by midgard_connection.

Query object(s)

By default midgard_user should not be accesible with query builder, however if new MgdSchema class which extends midgard_user is defined, it should be queryable with query builder or collector.

Authentication

Authentication should be done with 'login' and 'logout' methods of midgard_user class. Midgard core will accept any midgard_user which logs in as long as it's fetched from database. It's up to the application if given midgard_user is valid or not. Read only guid/uuid property will be always set internally by core and used as "fetched from database" marker.

Once object is fetched from database, it can be stored (serialized) in file or as memcached key for later reuse. midgard_connection's get_user() method will provide pointer to actually logged in user.

Authentication state stack

midgard_connection shall hold authenticated users in a stack. Every successful login method invoked by midgard_user object shall add new user to the top of the stack, while its logout method shall remove user from the top of the stack.

midgard_user can be removed from top of the stack in two cases:

  • midgard_user logout method is invoked explicitly
  • midgard_user object is destroyed

In latter case, Midgard core will invoke logout method in user's destructor.

It's application specific to logout users in proper order. Midgard core will return false for logout method, and will throw unconditional warning if there's attempt to logout a user which hasn't been logged in recently (it's not on top of the stack). Midgard language bindings should raise exception in such case, if it's only possible.

MgdSchema objects and metadata

It's up to the application if user holds a reference to midgard_person object. If current user doesn't have a reference to midgard_person object (via guid or uuid), core won't raise any warning or error. In such case empty string will be used instead of person's identifier for MgdSchema objects' metadata properties like creator or revisor.

Legacy authentication

Legacy authentication will be implemented as class which extends midgard_user. To avoid bulk updates of legacy accounts, this class will register any account using midgard_user routines on the fly. Which means, new user account will be created (for legacy one) as soon as first authentication attempt is made. This could also clear username and password from midgard_person record transparently.

Midgard root and Midgard domain 0 (SG0)

Implementation shall not allow any midgard_auth derived class to login in as Midgard root user or into sitegroup 0.

Back

Designed by Nemein, hosted by Anykey