Still getting Access control exception

Still getting Access control exception

by J. Pablo Fernández -
Number of replies: 6

Hello,

I'm writing an application that should connect to a Moodle installation to create courses, users, enrollments, etc using the API.

I make this call:

<?xml version="1.0" ?>
<methodCall><methodName>moodle_course_get_courses</methodName><params/></methodCall>

to POST /moodle20/webservice/xmlrpc/server.php?token=5aff55bbd0b8d127415fc60d6292d47b I always get this reply:

<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<fault><value><struct>
<member><name>faultCode</name><value><int>0</int></value></member>
<member><name>faultString</name><value><string>Access control exception</string></value></member>
</struct></value></fault></methodResponse>

I've searched for that error and I've found several posts but I still couldn't get it to work after reading them and the related tutorials.

Let's see, I created an external service:

I enabled XML-RPC. I've also tried enabling all the protocols, made no difference:

I created a role with the access to the protocols and the web api:

I created two users, one is a normal user (manual auth) and the other is a web services user:

I ended up assigning all roles to all users

I created tokens for each user:

I also enabled web services:

and web services authentication:

Any ideas what am I missing?

Average of ratings: Useful (1)
In reply to J. Pablo Fernández

Re: Still getting Access control exception

by Jonas Asa. -

I am having exactly the same problem. Did you find the solution?

Additionally, can you explain why it is necessary the last step?

In reply to J. Pablo Fernández

Re: Still getting Access control exception

by Murad Jamal -

this exception happens for one or more of  the following reasons (every if statement is a reason):

 if (!is_enabled_auth('webservice')) {
                throw new webservice_access_exception(get_string('wsauthnotenabled', 'webservice'));
            }

            if (!$auth = get_auth_plugin('webservice')) {
                throw new webservice_access_exception(get_string('wsauthmissing', 'webservice'));
            }

            $this->restricted_context = get_context_instance(CONTEXT_SYSTEM);

            if (!$this->username) {
                throw new webservice_access_exception(get_string('missingusername', 'webservice'));
            }

            if (!$this->password) {
                throw new webservice_access_exception(get_string('missingpassword', 'webservice'));
            }

            if (!$auth->user_login_webservice($this->username, $this->password)) {
                // log failed login attempts
                add_to_log(SITEID, 'webservice', get_string('simpleauthlog', 'webservice'), '' , get_string('failedtolog', 'webservice').": ".$this->username."/".$this->password." - ".getremoteaddr() , 0);
                throw new webservice_access_exception(get_string('wrongusernamepassword', 'webservice'));
            }

 if ($this->authmethod != WEBSERVICE_AUTHMETHOD_SESSION_TOKEN && !has_capability("webservice/$this->wsname:use", $this->restricted_context)) {
            throw new webservice_access_exception(get_string('accessnotallowed', 'webservice'));
        }

 if (!$token = $DB->get_record('external_tokens', array('token'=>$this->token, 'tokentype'=>$tokentype))) {
            // log failed login attempts
            add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '' , get_string('failedtolog', 'webservice').": ".$this->token. " - ".getremoteaddr() , 0);
            throw new webservice_access_exception(get_string('invalidtoken', 'webservice'));
        }

if ($token->validuntil and $token->validuntil < time()) {
            $DB->delete_records('external_tokens', array('token'=>$this->token, 'tokentype'=>$tokentype));
            throw new webservice_access_exception(get_string('invalidtimedtoken', 'webservice'));
        }

if ($token->sid){//assumes that if sid is set then there must be a valid associated session no matter the token type
            $session = session_get_instance();
            if (!$session->session_exists($token->sid)){
                $DB->delete_records('external_tokens', array('sid'=>$token->sid));
                throw new webservice_access_exception(get_string('invalidtokensession', 'webservice'));
            }
        }

 if ($token->iprestriction and !address_in_subnet(getremoteaddr(), $token->iprestriction)) {
            add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '' , get_string('failedtolog', 'webservice').": ".getremoteaddr() , 0);
            throw new webservice_access_exception(get_string('invalidiptoken', 'webservice'));
        }

 

the last reason is little large:

 $sql = "SELECT s.*, NULL AS iprestriction
                  FROM {external_services} s
                  JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 0 AND sf.functionname = :name1)
                 WHERE s.enabled = 1 $wscond1

                 UNION

                SELECT s.*, su.iprestriction
                  FROM {external_services} s
                  JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 1 AND sf.functionname = :name2)
                  JOIN {external_services_users} su ON (su.externalserviceid = s.id AND su.userid = :userid)
                 WHERE s.enabled = 1 AND su.validuntil IS NULL OR su.validuntil < :now $wscond2";
        $params = array_merge($params, array('userid'=>$USER->id, 'name1'=>$function->name, 'name2'=>$function->name, 'now'=>time()));

        $rs = $DB->get_recordset_sql($sql, $params);
        // now make sure user may access at least one service
        $remoteaddr = getremoteaddr();
        $allowed = false;
        foreach ($rs as $service) {
            if ($service->requiredcapability and !has_capability($service->requiredcapability, $this->restricted_context)) {
                continue; // cap required, sorry
            }
            if ($service->iprestriction and !address_in_subnet($remoteaddr, $service->iprestriction)) {
                continue; // wrong request source ip, sorry
            }
            $allowed = true;
            break; // one service is enough, no need to continue
        }
        $rs->close();
        if (!$allowed) {
            throw new webservice_access_exception('Access to external function not allowed');
        }

 

 

In reply to Murad Jamal

Re: Still getting Access control exception

by oneil clacken -

I am still having that problem... did anyone get around it?

In reply to oneil clacken

Re: Still getting Access control exception

by Juergen Zimmer -

Hi,

just started first experiments with Web services on our Moodle 2.2 Testserver and I've got exactly the same problem.

I'm trying to access a simple webservice via the Java XMLRPC client and get the error. And even putting the corresponding URL (webservice/xmlrpc/server.php?token=....) into the browser gives me the Access control exception with no further error string. 

Has any of you solved this issue already? I've checked all the settings just like J. Pablo and it all seems fine.

Cheers

    jzimmer

In reply to Juergen Zimmer

Re: Still getting Access control exception

by Fábio Souto -

I had some problems with this at the beggining as well, unfortunately I can't remember how I solved it.

But I remember turning on the DEBUG mode for messages, because it shows more helpful error messages. Have you done it already?