class_docstr: Abstract implementation of OpenID and Attribute Exchange.
  
  Class attributes:
  
  * ``_OPENID_ENDPOINT``: the identity provider's URI.
class_docstr_tok: ["Abstract","implementation","of","OpenID","and","Attribute","Exchange",".","Class","attributes",":","*","``","_OPENID_ENDPOINT","``",":","the","identity","provider","'s","URI","."]
code: def _on_authentication_verified(self, future, response):
      if response.error or b"is_valid:true" not in response.body:
          future.set_exception(
              AuthError(
                  "Invalid OpenID response: %s"
                  % (response.error or response.body)
              )
          )
          return
  
      # Make sure we got back at least an email from attribute exchange
      ax_ns = None
      for name in self.request.arguments:
          if (
              name.startswith("openid.ns.")
              and self.get_argument(name)
              == "http://openid.net/srv/ax/1.0"
          ):
              ax_ns = name[10:]
              break
  
      def get_ax_arg(uri):
          if not ax_ns:
              return ""
          prefix = "openid." + ax_ns + ".type."
          ax_name = None
          for name in self.request.arguments.keys():
              if self.get_argument(name) == uri and name.startswith(
                  prefix
              ):
                  part = name[len(prefix) :]
                  ax_name = "openid." + ax_ns + ".value." + part
                  break
          if not ax_name:
              return ""
          return self.get_argument(ax_name, "")
  
      email = get_ax_arg("http://axschema.org/contact/email")
      name = get_ax_arg("http://axschema.org/namePerson")
      first_name = get_ax_arg("http://axschema.org/namePerson/first")
      last_name = get_ax_arg("http://axschema.org/namePerson/last")
      username = get_ax_arg("http://axschema.org/namePerson/friendly")
      locale = get_ax_arg("http://axschema.org/pref/language").lower()
      user = dict()
      name_parts = []
      if first_name:
          user["first_name"] = first_name
          name_parts.append(first_name)
      if last_name:
          user["last_name"] = last_name
          name_parts.append(last_name)
      if name:
          user["name"] = name
      elif name_parts:
          user["name"] = " ".join(name_parts)
      elif email:
          user["name"] = email.split("@")[0]
      if email:
          user["email"] = email
      if locale:
          user["locale"] = locale
      if username:
          user["username"] = username
      claimed_id = self.get_argument("openid.claimed_id", None)
      if claimed_id:
          user["claimed_id"] = claimed_id
      future.set_result(user)
  
imports: from __future__ import absolute_import, division, print_function
  import base64
  import binascii
  import functools
  import hashlib
  import hmac
  import time
  import uuid
  from tornado.concurrent import TracebackFuture, return_future, chain_future
  from tornado import gen
  from tornado import httpclient
  from tornado import escape
  from tornado.httputil import url_concat
  from tornado.log import gen_log
  from tornado.stack_context import ExceptionStackContext
  from tornado.util import unicode_type, ArgReplacer, PY3
label_desc: Use image node_id 4 for calling the OpenIdMixin obj's underlying member method code with example usage: obj._on_authentication_verified(future, response) and returns: self, str, str