def authenticate(self, auth_delegate, callback):
        """
authenticate(auth_delegate, callback)
-------------------------------------

Description
    Validates the identity of a client after connecting to RTM
    with the Connection module. After the user authenticates with
    RTM, the operations that the client can perform depends on the role.

    Since the authentication process is an asynchronous operation, the callback
    function is required. The callback function processes the PDU response from
    RTM.

    For more information about authentication, see *Authentication and
    Authorization* in the online docs.

Parameters
    * auth_delegate {AuthDelegate | RoleSecretAuthDelegate} [required] - An
      authentication delegate object created with
      the `RoleSecretAuthDelegate(role, role_key)` method for
      the role-based authentication process.
    * callback {function} [required] - Function to execute after RTM
      returns a response.
        """

        with self._auth_lock:
            if self._next_auth_action:
                return callback(
                    auth.Error('Authentication is already in progress'))
            self._next_auth_action = auth_delegate.start()
            self._auth_callback = callback
            return self._handle_next_auth_action()
    def _handle_next_auth_action(self):
        with self._auth_lock:
            if type(self._next_auth_action) in [auth.Done, auth.Error]:
                self._auth_callback(self._next_auth_action)
                self._auth_callback = None
                self._next_auth_action = None
                return

            if type(self._next_auth_action) == auth.Handshake:
                action_id = next(self.action_id_iterator)
                payload = json.dumps({
                    'action': 'auth/handshake',
                    'body': {
                        'method': self._next_auth_action.method,
                        'data': self._next_auth_action.data},
                    'id': action_id
                    })
                return self.send(payload)
            elif type(self._next_auth_action) == auth.Authenticate:
                action_id = next(self.action_id_iterator)
                payload = json.dumps({
                    'action': 'auth/authenticate',
                    'body': {
                        'method': self._next_auth_action.method,
                        'credentials': self._next_auth_action.credentials},
                    'id': action_id
                    })
                return self.send(payload)

            self._auth_callback(auth.Error(
                'auth_delegate returned {0} instead of an auth action'.format(
                    self._next_auth_action)))
            self._auth_callback = None
 def convert(pdu):
     if pdu[u'action'] == u'auth/handshake/ok':
         return auth.HandshakeOK(pdu['body']['data'])
     if pdu[u'action'] == u'auth/authenticate/ok':
         return auth.AuthenticateOK()
     return auth.Error(pdu['body']['reason'])