Development:External services security: Difference between revisions
No edit summary |
|||
Line 19: | Line 19: | ||
The external API may be used from different places: | The external API may be used from different places: | ||
# directly from PHP - no authentication, current user session is used ($USER, $SESSION) | # directly from PHP - no authentication, current user session is used ($USER, $SESSION) | ||
# from web service layer - ws is responsible for faking of $USER and $SESSION object, no persistent session is maintained | # from web service layer - ws is responsible for faking of $USER and $SESSION object, no persistent session is maintained, webservice auth plugin is used for login/password authentication | ||
# when embedding external applications - external application receives unique token which is used instead of normal browser session cookie, the session is linked to the current user session in browser, the token is automatically invalidated after logout | # when embedding external applications - external application receives unique token which is used instead of normal browser session cookie, the session is linked to the current user session in browser, the token is automatically invalidated after logout | ||
# RSS feeds, iCals, etc. - token login, no permanent session | |||
==API layers== | ==API layers== |
Revision as of 21:04, 6 October 2009
NOTE: this page is obsolete and does not reflect latest development
Descriptions of security framework for web services, also used for RSS feeds, embedded application and similar parts that can not use normal HTTP cookies.
Overview
Current solutions:
- user keys for gradebook import and export - see require_user_key_login() and db table user_private_key
- open RSS feeds - no security at all
- chat_sid tokens - generated separately for each user in each chat
- calendar export - hash from user name, password and salt
- hacky cookie emulation in visual gradebook plugin
Design
Different uses
The external API may be used from different places:
- directly from PHP - no authentication, current user session is used ($USER, $SESSION)
- from web service layer - ws is responsible for faking of $USER and $SESSION object, no persistent session is maintained, webservice auth plugin is used for login/password authentication
- when embedding external applications - external application receives unique token which is used instead of normal browser session cookie, the session is linked to the current user session in browser, the token is automatically invalidated after logout
- RSS feeds, iCals, etc. - token login, no permanent session
API layers
Three layers:
- external server interface (SOAP, REST, RSS, etc.) - deals with tokens, emulates user session, parameter processing
- public PHP API - functions usable directly from PHP, list generated from inline PHP docs, need to verify all parameters and access control, may access $USER, should not manipulate $SESSION directly, must not read $_POST or $_GET
- low level internal API - as fast as possible, basic param validation, no access control, must not touch $USER, $SESSION, $_GET or $_POST, must not use has_capability() or require_login()!
Context restrictions
Context restriction of token validity should be effective against security problems in external applications interacting with Moodle. Some external applications do not have any access to http cookies, solution is to create temporary tokens. Context restrictions would allow us to grant external access to individual activities, courses ,etc..
Implementation
New database tables
external_functions
List of external functions. Created automatically by parsing of external files.
Field | Type | Default | Description |
---|---|---|---|
id | int(10) | auto-incrementing | |
component | varchar(100) | Component where function defined, needed for automatic updates. | |
name | varchar(150) | Name of function | |
enabled | int(1) | function enabled, functiosn might be disabled for security reasons | |
phpfile | varchar(255) | location where function defined | |
functionparams? | text | null | ?some form of param description? |
requireslogin | int(1) | extra information - some external functions may not require $USER | |
contextrestriction | int(1) | extra information - some functions may support context restrictions |
external_services
Service is defined as a group of functions.
Field | Type | Default | Description |
---|---|---|---|
id | int(10) | auto-incrementing | |
component | varchar(100) | Component where service defined, needed for automatic updates. | |
name | varchar(150) | Name of service (gradeexport/xml/export, mod/chat/export) | |
enabled | int(1) | service enabled, for security reasons some services may be disabled | |
version | varchar(10) | version string | |
requiredcapability | varchar(150) | null | Required capability (tested in security context or system context if no security context specified) |
custom | int(1) | 0 | Custom local service, created manually by admin or some other way == not parsed automatically. |
external_services_functions
Specifies functions used by services.
Field | Type | Default | Description |
---|---|---|---|
id | int(10) | auto-incrementing | |
externalserviceid | int(10) | foreign key, reference external_services.id | |
externalfunctionid | int(10) | foreign key, reference external_functions.id |
external_tokens
Stores tokens for cookieless access, script runs without real session, $USER and $SESSION is emulated. Use is relatively expensive because each scripts has to initialize accessdata in acceslib.php again. Existing data from user_private_key table are migrated here.
Field | Type | Default | Description |
---|---|---|---|
id | int(10) | auto-incrementing | |
userid | int(10) | foreign key, references user.id | |
token | varchar(128) | private access key value | |
restrictioncontextid | int(10) | security restriction, key usable only in this context, references context.id | |
externalserviceid | int(10) | foreign key, references external_services.id | |
itemid | int(10) | Service specific item id | |
iprestriction | varchar(255) | null | IP address restriction, list of allowed addresses |
validuntil | int(10) | null | timestampt - valid until date |
timecreated | int(10) | time when key created | |
lastaccess | int(10) | time when key last used for access |
Examples: gradebook exports, private RSS feeds, web services
external_sessions
Alternative session handling for scripts that are not allowed to access http cookies such as flex apps or external applications. The $SESSION is a true session which shares locking with the real http session. The token is automatically destroyed when http session ends (timeout, logout, login, etc.)
Field | Type | Default | Description |
---|---|---|---|
id | int(10) | auto-incrementing | |
userid | int(10) | foreign key, references user.id | |
token | varchar(128) | private access key value | |
restrictioncontextid | int(10) | security restriction, key usable only in this context, references context.id | |
externalserviceid | int(10) | foreign key, references external_services.id | |
itemid | int(10) | Service specific item id | |
sid | varchar(128) | PHP session id - links sessions table or files directly for legacy session types |
Examples: flex chat plugin
New capabilities
New capabilities for external services above. Each function could define capabilities too.
New auth plugin
Some external applications may require creation of new user account types that are not able to login interactively but only using login/pass or certificate. New authentication plugin could solve this problem.
The current design problem that any external actions such as role assign are carried out as nobody or root, it is later not possible to find out who changed what. Another problem is restrictions of external services to some contexts only.
User preferences may be also used for storage of extra data such as public certificates.
New functions
get_external_session_token($restrictioncontext, $service, $itemid, $version)
Returns user token which is used when embedding application or launching external applications. The other application has access to all functions specified in service definition in the restricted context or bellow until the end of current users session.
validate_context_restriction($currentcontext)
Each functions that supports restrictions must:
- find out context of request from function parameters - when enrolling user to course it is a course context, when add post to chat it is chat context, etc.
- call validate_context_restriction($currentcontext) - Moodle verifies $currentcontext is equal or child of restriction context, if not exception is thrown and script terminates.
The restriction context is stored in some global variable which is initialized in lib/setup.php using data from token tables.
New setup.php directives
EXTERNAL_SESSION_TOKEN
Defined before require 'config.php'. PHP session is initialised without the http cookie, URL token used instead. User must be already logged in at the same time.
EXTERNAL_TOKEN_LOGIN
Defined before require 'config.php'. Private token is used instead of normal login with username/password.
Discovery of external functions and services
Service discovery
Has to be automatic, part of upgrade. Can be similar to access.php, events.php, etc. Multiple services and versions may be defined in one file. We might need a way to define services that include definitions from other files, such as creating service that includes functions from all enabled course activities.
Function discovery
At present parsing of external files is done automatically using Zend reflexion and inline php docs.
I am not sure this is the best way :-( Petr Škoda (škoďák)
Avalaible method for discovery
This paragraph exists only to define the way we'll descrive the web services. There are three possible ways to describe web services:
- a PHP array : this array will contains all params + return value. In this array we also need to make a difference between array and object. PHP Associative array has to be defined as object.
For the purpose to be compatible with many languages we should see array as list and Associative array as object. It makes me think that we should probably only deal with object, not associative array.
This "array" solution has been implemented till revision 1.10 of user/external.php (CVS Head). This solution is the fastest in term of performance and should be the easier to use in order to create the servers. The way to define array/object has not been really well fixed!
- Zend reflexion + phpdoc new annotation: in this solution we use new "Moodle phpdoc annotation" in order to describe the web services. Have a look to the last revision 1.17. This solution avoid all redundancy, however it's harder to implemente, lass faster, and more difficult to maintain
- a XML file : a XML should contains all web service description. This solution is probably the more human readable (if xml is well designed).
Another point to come to, all external function should return always the same type of object (no new or missing attribut). PHP Array should be considered as list.
PHP array description
$this->descriptions['function_name'] = array( 'params' => array('params_name'=> PARAM_STRING),
'optionalparams' => array( ),
'return' => array('list:param_1' =>
array('attribut_1' => PARAM_INT,
'attribut_2' => PARAM_STRING,
'attribut_3' => PARAM_INT)));
Explanation:
- base is:
$this->descriptions['function_name'] = array( 'params' => array(),
'optionalparams' => array( ),
'return' => array());
- when a param/return is a list so it should be called 'list:param_name'
- when a param/return is not a list so it's either a primary type (e.g. PARAM_STRING), either a object (e.g. array)
- params and optionalparams have to follow the exact order of the function
- PARAM_RAW has to be replaced by the correct type (cannot be array)
Way to fill the database tables
Fill the external_functions, external_services and external_services_functions tables from a XML file like xmldb install.
Potential problems
No context restrictions and no function grouping
All external embedded applications would have full access as the use viewing the page (flash in html works like this by default).
All functions available to all clients
One sloppy contrib module compromises the whole system. Admin can not disable that function even if he knows it is buggy. No way to whitelist functions if needed.