Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Multi authentication: Difference between revisions

From MoodleDocs
m (Multi Authentication moved to Development:Multi authentication)
(Minor corrections and 'enabled' field addition to prefix_auth_instance)
Line 8: Line 8:


* Multiple simultaneous sources for authentication
* Multiple simultaneous sources for authentication
* Multiples sources of the same type (LDAP, database, etc)
* Multiples authentication instances (instances for short) of the same source type (LDAP, database, etc)
* Each source has its own configuration
* Each instance has its own configuration
* The order in which we try the sources is configurable
* The order in which we try the instances is configurable


=== How it works ===
=== How it works ===


* Each source has at least the auth_user_login function (like now).
* Each source (and thus each instance) has at least the auth_user_login function, like now. (this may change to class function user_login() once Jonathan Harker and Martin Langhoff work in multi-authentication is merged).
* This function can return one of the following values:
* This function can return one of the following values:
** AUTH_OK: the user and the password are valid
** AUTH_OK: the user and the password are valid
Line 20: Line 20:
** AUTH_DENIED: This user cannot login, even if the username and password are valid
** AUTH_DENIED: This user cannot login, even if the username and password are valid
** AUTH_ERROR: The source found and error during user and password validation and can't say wether they are valid or not.
** AUTH_ERROR: The source found and error during user and password validation and can't say wether they are valid or not.
* We try each source in the configured order.
* We try each instance in the configured order.
* For each order, we call auth_user_login with the user credentials and test the result.  
* For each instance, we call auth_user_login() (or user_login()) with the user credentials, and test the result.  
** if the result is AUTH_DENIED, we break out of the loop and deny the user login.
** if the result is AUTH_DENIED, we break out of the loop and deny the user login.
** if the result is AUTH_OK, we break out of the loop and allow the user login.
** if the result is AUTH_OK, we break out of the loop and allow the user login.
** in any other case, we continue the loop.
** in any other case, we continue the loop.
* If we finish the loop, we deny the user login (all the sources returned either AUTH_DECLINED or AUTH_ERROR, so we can't let the user log in).
* If we finish the loop, we deny the user login (all the instances returned either AUTH_DECLINED or AUTH_ERROR, so we can't let the user log in).


=== The (proposed) database tables ===
=== The (proposed) database tables ===


(MySQL syntax, Postgresql gurus please adjust definition ;-)
(MySQL syntax, Postgresql syntax omitted for shortness)


==== auth_type ====  
==== auth_type ====  
Line 45: Line 45:
</pre>
</pre>


This table stores the different authentication types present in this
This table stores the different authentication types (sources) present in this
Moodle installation: internal, none, ldap, db, cas, etc.
Moodle installation: internal, none, ldap, db, cas, etc.


Line 52: Line 52:


* 'id': the primary key of the record.
* 'id': the primary key of the record.
* 'name': The name of the autentication type: 'internal', 'none', 'ldap', 'db', etc. There can't be duplicated values in this field.
* 'name': The name of the autentication type: 'manual', 'none', 'ldap', 'db', etc. There can't be duplicated values in this field.
* 'isinternal' if this auth type is internal to Moodle (1) or not(0), i.e., if it doesn't depend on any external entity to provide authentication. Tipically this is for 'manual', 'email' and 'none'.
* 'isinternal' if this auth type is internal to Moodle (1) or not(0), i.e., if it doesn't depend on any external entity to provide authentication. Tipically this is for 'manual', 'email' and 'none'.
* 'multiple': if this auth type supports multiple instances (1) or not (0).
* 'multiple': if this auth type supports multiple instances (1) or not (0).
Line 58: Line 58:
* 'removable': if this auth type can be removed from the system (1) or not (0).
* 'removable': if this auth type can be removed from the system (1) or not (0).


If we decide that 'internal', 'none' and/or 'email' are special
If we decide that 'manual', 'none' and/or 'email' are special
authentication types and are handled separately form the rest, then
authentication types and are handled separately form the rest, then
this last field can be removed.
this last field can be removed.


'''BIG QUESTION HERE''': Can 'internal' be disabled? I'm not sure
'''BIG QUESTION HERE''': Can 'manual' be disabled? I'm not sure
about this, as all the admin users can be locked out of Moodle if we
about this, as all the admin users can be locked out of Moodle if we
mistakenly disable all the auth types needed for admin users.
mistakenly disable all the auth types needed for admin users.


'''BIG QUESTION HERE''': Should 'internal' auth type be handled
'''BIG QUESTION HERE''': Should 'manual' auth type be handled
separately from all this multi-auth mess? I guess there are some
separately from all this multi-auth mess? I guess there are some
benefits to it, but I'm not sure about it. For one, it would make the
benefits to it, but I'm not sure about it. For one, it would make the
Line 78: Line 78:
       `name` varchar(20) NOT NULL default '',  
       `name` varchar(20) NOT NULL default '',  
       `description` varchar(50) NOT NULL default '',  
       `description` varchar(50) NOT NULL default '',  
       `sortorder` integer(10) NOT NULL default '0'
       `sortorder` integer(10) NOT NULL default '0',
      `enabled` tinyint(1) NOT NULL default '1',
       PRIMARY_KEY(`id`),
       PRIMARY_KEY(`id`),
       UNIQUE KEY(`name`)       
       UNIQUE KEY(`name`)       
Line 87: Line 88:
type. It's managed from the authentication setup page, using
type. It's managed from the authentication setup page, using
the add/modify/delete functionality available there. We can also
the add/modify/delete functionality available there. We can also
specify the order in which we want to user each auth-instance when
specify the order in which we want to use each auth-instance when
authenticating users.
authenticating users.


Line 97: Line 98:
* 'description': a short description text for this instance (e.g., 'UK Students LDAP server').
* 'description': a short description text for this instance (e.g., 'UK Students LDAP server').
* 'sortorder': the order in which we use each auth instance when trying to authenticate users.
* 'sortorder': the order in which we use each auth instance when trying to authenticate users.
* 'enabled': if this instance is enabled (1) or not (0).


'''BIG QUESTION HERE''': If we use 'id' to fill in the 'auth' field in
'''BIG QUESTION HERE''': If we use 'id' to fill in the 'auth' field in

Revision as of 21:04, 28 September 2006

Before starting to code anything about Multi Authentication support in Moodle, I would like to share what I have in mind, so others can see the flaws and everybody can spot the problems with this approach.

There are some big questions (see below) I don't know the answer for, so if others with more knowledge of Moodle internals (specially authentication internals) than me could answer them, that would be great.

Some random notes about multi-auth in Moodle

Goals

  • Multiple simultaneous sources for authentication
  • Multiples authentication instances (instances for short) of the same source type (LDAP, database, etc)
  • Each instance has its own configuration
  • The order in which we try the instances is configurable

How it works

  • Each source (and thus each instance) has at least the auth_user_login function, like now. (this may change to class function user_login() once Jonathan Harker and Martin Langhoff work in multi-authentication is merged).
  • This function can return one of the following values:
    • AUTH_OK: the user and the password are valid
    • AUTH_DECLINED: The user or the password are not correct or unknown to this source
    • AUTH_DENIED: This user cannot login, even if the username and password are valid
    • AUTH_ERROR: The source found and error during user and password validation and can't say wether they are valid or not.
  • We try each instance in the configured order.
  • For each instance, we call auth_user_login() (or user_login()) with the user credentials, and test the result.
    • if the result is AUTH_DENIED, we break out of the loop and deny the user login.
    • if the result is AUTH_OK, we break out of the loop and allow the user login.
    • in any other case, we continue the loop.
  • If we finish the loop, we deny the user login (all the instances returned either AUTH_DECLINED or AUTH_ERROR, so we can't let the user log in).

The (proposed) database tables

(MySQL syntax, Postgresql syntax omitted for shortness)

auth_type

  CREATE TABLE `prefix_auth_type` (
       `id` integer(10) NOT NULL auto_increment,
       `name` varchar(20) NOT NULL default '', 
       `isinternal` tinyint(1) NOT NULL default '0',
       `multiple` tinyint(1) NOT NULL default '0',
       `candisable` tinyint(1) NOT NULL default '0',
       `removable` tinyint(1) NOT NULL default '0',
       PRIMARY_KEY(`id`),
       UNIQUE KEY(`name`)
  )

This table stores the different authentication types (sources) present in this Moodle installation: internal, none, ldap, db, cas, etc.

Each auth type has to autoregister in this table when it's installed, specifying:

  • 'id': the primary key of the record.
  • 'name': The name of the autentication type: 'manual', 'none', 'ldap', 'db', etc. There can't be duplicated values in this field.
  • 'isinternal' if this auth type is internal to Moodle (1) or not(0), i.e., if it doesn't depend on any external entity to provide authentication. Tipically this is for 'manual', 'email' and 'none'.
  • 'multiple': if this auth type supports multiple instances (1) or not (0).
  • 'candisable': if this auth type can be temporarily disabled (1) or not (0)
  • 'removable': if this auth type can be removed from the system (1) or not (0).

If we decide that 'manual', 'none' and/or 'email' are special authentication types and are handled separately form the rest, then this last field can be removed.

BIG QUESTION HERE: Can 'manual' be disabled? I'm not sure about this, as all the admin users can be locked out of Moodle if we mistakenly disable all the auth types needed for admin users.

BIG QUESTION HERE: Should 'manual' auth type be handled separately from all this multi-auth mess? I guess there are some benefits to it, but I'm not sure about it. For one, it would make the above question irrelevant.

auth_instance

  CREATE TABLE `prefix_auth_instance` (
       `id` integer(10) NOT NULL auto_increment,
       `typeid` integer(10) NOT NULL default '0', 
       `name` varchar(20) NOT NULL default '', 
       `description` varchar(50) NOT NULL default '', 
       `sortorder` integer(10) NOT NULL default '0',
       `enabled` tinyint(1) NOT NULL default '1',
       PRIMARY_KEY(`id`),
       UNIQUE KEY(`name`)       
  )

This table stores the different auth instances available for each auth type. It's managed from the authentication setup page, using the add/modify/delete functionality available there. We can also specify the order in which we want to use each auth-instance when authenticating users.

The meaning of the fields are:

  • 'id': the primary key of the record. We will put this value into the 'auth' field in prefix_user table when we correctly authenticate a user using this auth instance (to later track where to update values from, where to check for password expiration, etc.)
  • 'typeid': the auth type id of this instance. It's a foreign key into the 'type' field of auth_type table. We need this to check if there is already an instance of a given auth type, in case that auth type doesn't allow for multiple instances.
  • 'name': the name of this instance. It's the text shown in the authentication setup page to refer to this instance.
  • 'description': a short description text for this instance (e.g., 'UK Students LDAP server').
  • 'sortorder': the order in which we use each auth instance when trying to authenticate users.
  • 'enabled': if this instance is enabled (1) or not (0).

BIG QUESTION HERE: If we use 'id' to fill in the 'auth' field in prefix_user, then we should only use 'sortorder' when the user has that field empty (i.e., we don't know where to authenticate this user so far). Otherwise we could directly authenticate with the known auth-instance. But this prevents users from "moving" between authentication instances (i.e, this user "was" in our UK student's LDAP server, but now "is" in our US staff database server). Is this good or bad?

ANSWER TO BIG QUESTION: After talking with Martin Langhoff at MoodleMoot Spain '06, this is clearly a Bad(tm) thing. If we allow users to "float" between authentication instances, things like auth_ldap_sync_users.php could break havoc, deleting users it doesn't know about in this auth_instance (but perfectly valid in other auth_instance's). So storing the auth_instance 'id' in prefix_user and using it accordingly is The Right Thing(tm).

auth_instance_settings

  CREATE TABLE `prefix_auth_instance_settings` (
       `id` integer(10) NOT NULL auto_increment,
       `instanceid` integer(10) NOT NULL default '0', 
       `name` varchar(255) NOT NULL default '', 
       `value` text NOT NULL
       PRIMARY_KEY(`id`),
       UNIQUE KEY `instancesetting` (`instanceid`,`name`)
  )

This table stores each auth instance configuration settings.

  • 'id': the primary key for the record.
  • 'instanceid': foreign key into the 'id' field of auth_instance table.
  • 'name': name of the setting.
  • 'value': value for that setting.

There can't be two (or more) identical 'name' values for the same 'instanceid'.

The questions

Some additional questions before starting to code all this mess

  1. If we store the 'prefix_auth_intance.id' value in the 'prefix_user.auth' field as suggested above, what should we do when we remove that auth instance from our system? Should we allow removal if any users are using that instance? Should we move those users to the default auth instance (internal)? Should we choose a new auth instance for those users as part of the removal? Or should we just ignore the 'prefix_user.auth' field during login and just proceed through the whole loop and try to find which new auth instance allows the user to login (if any)?
  2. Others?