# File lib/openid/consumer/associationmanager.rb, line 284
      def extract_association(assoc_response, assoc_session)
        # Extract the common fields from the response, raising an
        # exception if they are not found
        assoc_type = assoc_response.get_arg(OPENID_NS, 'assoc_type',
                                            NO_DEFAULT)
        assoc_handle = assoc_response.get_arg(OPENID_NS, 'assoc_handle',
                                              NO_DEFAULT)
        expires_in = self.class.extract_expires_in(assoc_response)

        # OpenID 1 has funny association session behaviour.
        if assoc_response.is_openid1
            session_type = get_openid1_session_type(assoc_response)
        else
          session_type = assoc_response.get_arg(OPENID2_NS, 'session_type',
                                                NO_DEFAULT)
        end

        # Session type mismatch
        if assoc_session.class.session_type != session_type
          if (assoc_response.is_openid1 and session_type == 'no-encryption')
            # In OpenID 1, any association request can result in a
            # 'no-encryption' association response. Setting
            # assoc_session to a new no-encryption session should
            # make the rest of this function work properly for
            # that case.
            assoc_session = NoEncryptionSession.new
          else
            # Any other mismatch, regardless of protocol version
            # results in the failure of the association session
            # altogether.
            raise ProtocolError, "Session type mismatch. Expected "\
                                 "#{assoc_session.class.session_type}, got "\
                                 "#{session_type}"
          end
        end

        # Make sure assoc_type is valid for session_type
        if !assoc_session.class.allowed_assoc_types.member?(assoc_type)
          raise ProtocolError, "Unsupported assoc_type for session "\
                               "#{assoc_session.class.session_type} "\
                               "returned: #{assoc_type}"
        end

        # Delegate to the association session to extract the secret
        # from the response, however is appropriate for that session
        # type.
        begin
          secret = assoc_session.extract_secret(assoc_response)
        rescue Message::KeyNotFound, ArgumentError => why
          raise ProtocolError, "Malformed response for "\
                               "#{assoc_session.class.session_type} "\
                               "session: #{why.message}"
        end


        return Association.from_expires_in(expires_in, assoc_handle, secret,
                                           assoc_type)
      end