extract_association (OpenID::Consumer::AssociationManager)

    # File lib/openid/consumer/associationmanager.rb, line 280
          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