diff --git a/libpurple/connection.h b/libpurple/connection.h
--- a/libpurple/connection.h
+++ b/libpurple/connection.h
@@ -256,20 +256,6 @@
 	(purple_connection_get_state(gc) == PURPLE_CONNECTION_STATE_CONNECTED)
 
 /**
- * purple_connection_new:
- * @protocol: The [class@Purple.Protocol] to use to create the connection.
- * @account: The [class@Purple.Account] to create a connection for.
- * @password: (nullable): The password for this account.
- *
- * Creates a new [class@Purple.Connection] for @account.
- *
- * Returns: (transfer full): The new connection.
- *
- * Since: 3.0.0
- */
-PurpleConnection *purple_connection_new(PurpleProtocol *protocol, PurpleAccount *account, const char *password);
-
-/**
  * purple_connection_get_id:
  * @connection: The connection.
  *
# HG changeset patch
# Node ID 00d3bffbecfb
# Parent  86302ce7e3c1
diff --git a/libpurple/connection.c b/libpurple/connection.c
--- a/libpurple/connection.c
+++ b/libpurple/connection.c
@@ -881,6 +881,8 @@
 _purple_connection_new(PurpleAccount *account, gboolean is_registration,
                        const gchar *password)
 {
+	PurpleConnection *connection = NULL;
+	PurpleConnectionPrivate *priv = NULL;
 	PurpleProtocol *protocol = NULL;
 
 	g_return_if_fail(PURPLE_IS_ACCOUNT(account));
@@ -921,7 +923,32 @@
 		}
 	}
 
-	purple_protocol_login(protocol, account, password);
+	connection = g_object_new(
+		PURPLE_TYPE_CONNECTION,
+		"protocol", protocol,
+		"account", account,
+		"password", password,
+		NULL);
+
+	g_return_if_fail(connection != NULL);
+
+	priv = purple_connection_get_instance_private(connection);
+
+	if(is_registration) {
+		purple_debug_info("connection", "Registering.  connection = %p",
+		                  connection);
+
+		/* set this so we don't auto-reconnect after registering */
+		priv->wants_to_die = TRUE;
+
+		purple_protocol_server_register_user(PURPLE_PROTOCOL_SERVER(protocol),
+		                                     account);
+	} else {
+		purple_debug_info("connection", "Connecting. connection = %p",
+		                  connection);
+
+		purple_protocol_login(protocol, account);
+	}
 }
 
 void
@@ -979,21 +1006,6 @@
 	                                       account, cb, user_data);
 }
 
-PurpleConnection *
-purple_connection_new(PurpleProtocol *protocol, PurpleAccount *account,
-                      const char *password)
-{
-	g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), NULL);
-	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
-
-	return g_object_new(
-		PURPLE_TYPE_CONNECTION,
-		"protocol", protocol,
-		"account", account,
-		"password", password,
-		NULL);
-}
-
 /**************************************************************************
  * Connections API
  **************************************************************************/
diff --git a/libpurple/protocols/bonjour/bonjour.c b/libpurple/protocols/bonjour/bonjour.c
--- a/libpurple/protocols/bonjour/bonjour.c
+++ b/libpurple/protocols/bonjour/bonjour.c
@@ -94,23 +94,19 @@
 
 }
 
-static PurpleConnection *
-bonjour_login(PurpleProtocol *protocol, PurpleAccount *account,
-              const char *password)
-{
-	PurpleConnection *gc = NULL;
+static void
+bonjour_login(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleAccount *account) {
+	PurpleConnection *gc = purple_account_get_connection(account);
 	BonjourData *bd;
 	PurpleStatus *status;
 	PurplePresence *presence;
 
-	gc = purple_connection_new(protocol, account, password);
-
 	if (!mdns_available()) {
 		purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 				_("Unable to find Apple's \"Bonjour for Windows\" toolkit, see "
 				  "https://developer.pidgin.im/BonjourWindows for more information."));
-		return gc;
+		return;
 	}
 
 	purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_HTML |
@@ -128,7 +124,7 @@
 		purple_connection_error (gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("Unable to listen for incoming IM connections"));
-		return gc;
+		return;
 	}
 
 	/* Connect to the mDNS daemon looking for buddies in the LAN */
@@ -155,15 +151,13 @@
 		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Unable to establish connection with the local mDNS server.  Is it running?"));
-		return gc;
+		return;
 	}
 
 	bonjour_dns_sd_update_buddy_icon(bd->dns_sd_data);
 
 	/* Show the buddy list by telling Purple we have already connected */
 	purple_connection_set_state(gc, PURPLE_CONNECTION_STATE_CONNECTED);
-
-	return gc;
 }
 
 static void
diff --git a/libpurple/protocols/demo/purpledemoprotocol.c b/libpurple/protocols/demo/purpledemoprotocol.c
--- a/libpurple/protocols/demo/purpledemoprotocol.c
+++ b/libpurple/protocols/demo/purpledemoprotocol.c
@@ -35,19 +35,16 @@
 /******************************************************************************
  * PurpleProtocol Implementation
  *****************************************************************************/
-static PurpleConnection *
-purple_demo_protocol_login(PurpleProtocol *protocol, PurpleAccount *account,
-                           const char *password)
+static void
+purple_demo_protocol_login(G_GNUC_UNUSED PurpleProtocol *protocol,
+                           PurpleAccount *account)
 {
 	PurpleConnection *connection = NULL;
 
-	connection = purple_connection_new(protocol, account, password);
-
+	connection = purple_account_get_connection(account);
 	purple_connection_set_state(connection, PURPLE_CONNECTION_STATE_CONNECTED);
 
 	purple_demo_contacts_load(account);
-
-	return connection;
 }
 
 static GList *
diff --git a/libpurple/protocols/facebook/facebook.c b/libpurple/protocols/facebook/facebook.c
--- a/libpurple/protocols/facebook/facebook.c
+++ b/libpurple/protocols/facebook/facebook.c
@@ -1007,8 +1007,8 @@
 	return g_list_reverse(opts);
 }
 
-static PurpleConnection *
-fb_login(PurpleProtocol *protocol, PurpleAccount *acct, const char *password) {
+static void
+fb_login(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleAccount *acct) {
 	const gchar *pass;
 	const gchar *user;
 	FbApi *api;
@@ -1018,14 +1018,14 @@
 	GProxyResolver *resolver;
 	GError *error = NULL;
 
-	gc = purple_connection_new(protocol, acct, password);
+	gc = purple_account_get_connection(acct);
 
 	resolver = purple_proxy_get_proxy_resolver(acct, &error);
 	if (resolver == NULL) {
 		fb_util_debug_error("Unable to get account proxy resolver: %s",
 		                    error->message);
 		purple_connection_take_error(gc, error);
-		return gc;
+		return;
 	}
 
 	fata = fb_data_new(gc, resolver);
@@ -1105,12 +1105,10 @@
 		user = purple_account_get_username(acct);
 		pass = purple_connection_get_password(gc);
 		fb_api_auth(api, user, pass);
-		return gc;
+		return;
 	}
 
 	fb_api_contacts(api);
-
-	return gc;
 }
 
 static void
diff --git a/libpurple/protocols/gg/gg.c b/libpurple/protocols/gg/gg.c
--- a/libpurple/protocols/gg/gg.c
+++ b/libpurple/protocols/gg/gg.c
@@ -781,11 +781,9 @@
 	}
 }
 
-static PurpleConnection *
-ggp_login(PurpleProtocol *protocol, PurpleAccount *account,
-          const char *password)
-{
-	PurpleConnection *gc = NULL;
+static void
+ggp_login(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleAccount *account) {
+	PurpleConnection *gc = purple_account_get_connection(account);
 	struct gg_login_params *glp;
 	GGPInfo *info;
 	const char *address;
@@ -793,8 +791,6 @@
 	GProxyResolver *resolver;
 	GError *error = NULL;
 
-	gc = purple_connection_new(protocol, account, password);
-
 	purple_connection_set_flags(gc,
 		PURPLE_CONNECTION_FLAG_HTML |
 		PURPLE_CONNECTION_FLAG_NO_URLDESC);
@@ -804,7 +800,7 @@
 		purple_debug_error("gg", "Unable to get account proxy resolver: %s",
 		                   error->message);
 		purple_connection_take_error(gc, error);
-		return gc;
+		return;
 	}
 
 	glp = g_new0(struct gg_login_params, 1);
@@ -837,7 +833,7 @@
 			_("The username specified is invalid."));
 		purple_str_wipe(glp->password);
 		g_free(glp);
-		return gc;
+		return;
 	}
 
 	glp->image_size = 255;
@@ -868,7 +864,7 @@
 				_("SSL support unavailable"));
 			purple_str_wipe(glp->password);
 			g_free(glp);
-			return gc;
+			return;
 		}
 	}
 	else /* encryption_type == "none" */
@@ -900,15 +896,13 @@
 		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Connection failed"));
-		return gc;
+		return;
 	}
 
 	if (info->session->fd > 0) {
 		info->inpa = purple_input_add(info->session->fd,
 			PURPLE_INPUT_READ, ggp_async_login_handler, gc);
 	}
-
-	return gc;
 }
 
 static void
diff --git a/libpurple/protocols/irc/irc.c b/libpurple/protocols/irc/irc.c
--- a/libpurple/protocols/irc/irc.c
+++ b/libpurple/protocols/irc/irc.c
@@ -42,7 +42,7 @@
 
 static GList *irc_status_types(PurpleProtocol *protocol, PurpleAccount *account);
 /* static GList *irc_chat_info(PurpleConnection *gc); */
-static PurpleConnection *irc_login(PurpleProtocol *protocol, PurpleAccount *account, const char *password);
+static void irc_login(PurpleProtocol *protocol, PurpleAccount *account);
 static void irc_login_cb(GObject *source, GAsyncResult *res, gpointer user_data);
 static void irc_close(PurpleProtocol *protocol, PurpleConnection *gc);
 static int irc_im_send(PurpleProtocolIM *im, PurpleConnection *gc, PurpleMessage *msg);
@@ -524,10 +524,8 @@
 	return defaults;
 }
 
-static PurpleConnection *
-irc_login(PurpleProtocol *protocol, PurpleAccount *account,
-          const char *password)
-{
+static void
+irc_login(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleAccount *account) {
 	PurpleConnection *gc;
 	struct irc_conn *irc;
 	char **userparts;
@@ -535,7 +533,7 @@
 	GSocketClient *client;
 	GError *error = NULL;
 
-	gc = purple_connection_new(protocol, account, password);
+	gc = purple_account_get_connection(account);
 	purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_NO_NEWLINES |
 		PURPLE_CONNECTION_FLAG_NO_IMAGES);
 
@@ -544,7 +542,7 @@
 			PURPLE_CONNECTION_ERROR,
 			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
 			_("IRC nick and server may not contain whitespace")));
-		return gc;
+		return;
 	}
 
 	irc = g_new0(struct irc_conn, 1);
@@ -568,7 +566,7 @@
 
 	if (client == NULL) {
 		purple_connection_take_error(gc, error);
-		return gc;
+		return;
 	}
 
 	/* Optionally use TLS if it's set in the account settings */
@@ -582,8 +580,6 @@
 							IRC_DEFAULT_PORT),
 			irc->cancellable, irc_login_cb, gc);
 	g_object_unref(client);
-
-	return gc;
 }
 
 static gboolean do_login(PurpleConnection *gc) {
diff --git a/libpurple/protocols/ircv3/purpleircv3connection.h b/libpurple/protocols/ircv3/purpleircv3connection.h
--- a/libpurple/protocols/ircv3/purpleircv3connection.h
+++ b/libpurple/protocols/ircv3/purpleircv3connection.h
@@ -31,10 +31,14 @@
 
 #define PURPLE_IRCV3_TYPE_CONNECTION (purple_ircv3_connection_get_type())
 G_DECLARE_FINAL_TYPE(PurpleIRCv3Connection, purple_ircv3_connection,
-                     PURPLE_IRCV3, CONNECTION, PurpleConnection)
+                     PURPLE_IRCV3, CONNECTION, GObject)
 
 G_GNUC_INTERNAL void purple_ircv3_connection_register(GPluginNativePlugin *plugin);
 
+G_GNUC_INTERNAL PurpleIRCv3Connection *purple_ircv3_connection_new(PurpleAccount *account);
+
+G_GNUC_INTERNAL PurpleAccount *purple_ircv3_connection_get_account(PurpleIRCv3Connection *connection);
+
 G_GNUC_INTERNAL GCancellable *purple_ircv3_connection_get_cancellable(PurpleIRCv3Connection *connection);
 
 G_GNUC_INTERNAL gboolean purple_ircv3_connection_valid(PurpleIRCv3Connection *connection, GError **error);
diff --git a/libpurple/protocols/ircv3/purpleircv3connection.c b/libpurple/protocols/ircv3/purpleircv3connection.c
--- a/libpurple/protocols/ircv3/purpleircv3connection.c
+++ b/libpurple/protocols/ircv3/purpleircv3connection.c
@@ -25,6 +25,7 @@
 
 enum {
 	PROP_0,
+	PROP_ACCOUNT,
 	PROP_CANCELLABLE,
 	PROP_CAPABILITIES,
 	N_PROPERTIES,
@@ -32,9 +33,10 @@
 static GParamSpec *properties[N_PROPERTIES] = {NULL, };
 
 struct _PurpleIRCv3Connection {
-	PurpleConnection parent;
+	GObject parent;
 
 	GError *validate_error;
+	PurpleAccount *account;
 
 	GSocketConnection *connection;
 	GCancellable *cancellable;
@@ -50,30 +52,42 @@
 };
 
 G_DEFINE_DYNAMIC_TYPE(PurpleIRCv3Connection, purple_ircv3_connection,
-                      PURPLE_TYPE_CONNECTION)
+                      G_TYPE_OBJECT)
 
 /******************************************************************************
  * Helpers
  *****************************************************************************/
 static void
+purple_ircv3_connection_set_account(PurpleIRCv3Connection *connection,
+                                    PurpleAccount *account)
+{
+	g_return_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection));
+
+	if(g_set_object(&connection->account, account)) {
+		g_object_notify_by_pspec(G_OBJECT(connection),
+		                         properties[PROP_ACCOUNT]);
+	}
+}
+
+static void
 purple_ircv3_connection_send_user_command(PurpleIRCv3Connection *connection) {
-	PurpleAccount *account = NULL;
+	PurpleConnection *purple_connection = NULL;
 	const char *identname = NULL;
 	const char *nickname = NULL;
 	const char *realname = NULL;
 
-	account = purple_connection_get_account(PURPLE_CONNECTION(connection));
-	nickname = purple_connection_get_display_name(PURPLE_CONNECTION(connection));
+	purple_connection = purple_account_get_connection(connection->account);
+	nickname = purple_connection_get_display_name(purple_connection);
 
 	/* The stored value could be an empty string, so pass a default of empty
 	 * string and then if it was empty, set our correct fallback.
 	 */
-	identname = purple_account_get_string(account, "ident", "");
+	identname = purple_account_get_string(connection->account, "ident", "");
 	if(identname == NULL || *identname == '\0') {
 		identname = nickname;
 	}
 
-	realname = purple_account_get_string(account, "real-name", "");
+	realname = purple_account_get_string(connection->account, "real-name", "");
 	if(realname == NULL || *realname == '\0') {
 		realname = nickname;
 	}
@@ -84,9 +98,12 @@
 
 static void
 purple_ircv3_connection_send_nick_command(PurpleIRCv3Connection *connection) {
+	PurpleConnection *purple_connection = NULL;
 	const char *nickname = NULL;
 
-	nickname = purple_connection_get_display_name(PURPLE_CONNECTION(connection));
+	purple_connection = purple_account_get_connection(connection->account);
+
+	nickname = purple_connection_get_display_name(purple_connection);
 
 	purple_ircv3_connection_writef(connection, "NICK %s", nickname);
 }
@@ -98,7 +115,8 @@
 purple_ircv3_connection_read_cb(GObject *source, GAsyncResult *result,
                                 gpointer data)
 {
-	PurpleIRCv3Connection *connection = data;
+	PurpleIRCv3Connection *connection = NULL;
+	PurpleConnection *purple_connection = data;
 	GDataInputStream *istream = G_DATA_INPUT_STREAM(source);
 	GError *error = NULL;
 	gchar *line = NULL;
@@ -115,7 +133,7 @@
 			g_prefix_error(&error, "%s", _("Lost connection with server: "));
 		}
 
-		purple_connection_take_error(PURPLE_CONNECTION(connection), error);
+		purple_connection_take_error(purple_connection, error);
 
 		/* In the off chance that line was returned, make sure we free it. */
 		g_free(line);
@@ -123,6 +141,8 @@
 		return;
 	}
 
+	connection = g_object_get_data(G_OBJECT(purple_connection),
+	                               PURPLE_IRCV3_CONNECTION_KEY);
 	purple_ircv3_parser_parse(connection->parser, line, &error, connection);
 
 	g_free(line);
@@ -132,7 +152,7 @@
 	                                    G_PRIORITY_DEFAULT,
 	                                    connection->cancellable,
 	                                    purple_ircv3_connection_read_cb,
-	                                    connection);
+	                                    purple_connection);
 }
 
 static void
@@ -148,11 +168,14 @@
 	                                                        &error);
 
 	if(!success) {
+		PurpleConnection *purple_connection = NULL;
+		purple_connection = purple_account_get_connection(connection->account);
+
 		purple_queued_output_stream_clear_queue(stream);
 
 		g_prefix_error(&error, "%s", _("Lost connection with server: "));
 
-		purple_connection_take_error(PURPLE_CONNECTION(connection), error);
+		purple_connection_take_error(purple_connection, error);
 
 		return;
 	}
@@ -162,7 +185,8 @@
 purple_ircv3_connection_connected_cb(GObject *source, GAsyncResult *result,
                                      gpointer data)
 {
-	PurpleIRCv3Connection *connection = data;
+	PurpleIRCv3Connection *connection = NULL;
+	PurpleConnection *purple_connection = data;
 	GError *error = NULL;
 	GInputStream *istream = NULL;
 	GOutputStream *ostream = NULL;
@@ -174,12 +198,15 @@
 	if(conn == NULL || error != NULL) {
 		g_prefix_error(&error, "%s", _("Unable to connect: "));
 
-		purple_connection_take_error(PURPLE_CONNECTION(connection), error);
+		purple_connection_take_error(purple_connection, error);
 
 		return;
 	}
 
-	purple_connection_set_state(PURPLE_CONNECTION(connection),
+	connection = g_object_get_data(G_OBJECT(purple_connection),
+	                               PURPLE_IRCV3_CONNECTION_KEY);
+
+	purple_connection_set_state(purple_connection,
 	                            PURPLE_CONNECTION_STATE_CONNECTED);
 
 	g_message("Successfully connected to %s", connection->server_name);
@@ -204,7 +231,7 @@
 	                                    G_PRIORITY_DEFAULT,
 	                                    connection->cancellable,
 	                                    purple_ircv3_connection_read_cb,
-	                                    connection);
+	                                    purple_connection);
 
 	/* Send our registration commands. */
 	purple_ircv3_connection_writef(connection, "CAP LS %s",
@@ -223,6 +250,10 @@
 	PurpleIRCv3Connection *connection = PURPLE_IRCV3_CONNECTION(obj);
 
 	switch(param_id) {
+		case PROP_ACCOUNT:
+			g_value_set_object(value,
+			                   purple_ircv3_connection_get_account(connection));
+			break;
 		case PROP_CANCELLABLE:
 			g_value_set_object(value,
 			                   purple_ircv3_connection_get_cancellable(connection));
@@ -241,7 +272,13 @@
 purple_ircv3_connection_set_property(GObject *obj, guint param_id,
                                      const GValue *value, GParamSpec *pspec)
 {
+	PurpleIRCv3Connection *connection = PURPLE_IRCV3_CONNECTION(obj);
+
 	switch(param_id) {
+		case PROP_ACCOUNT:
+			purple_ircv3_connection_set_account(connection,
+			                                    g_value_get_object(value));
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
 			break;
@@ -252,6 +289,7 @@
 purple_ircv3_connection_dispose(GObject *obj) {
 	PurpleIRCv3Connection *connection = PURPLE_IRCV3_CONNECTION(obj);
 
+	g_clear_object(&connection->account);
 	g_clear_object(&connection->cancellable);
 
 	g_clear_object(&connection->input);
@@ -278,18 +316,18 @@
 static void
 purple_ircv3_connection_constructed(GObject *obj) {
 	PurpleIRCv3Connection *connection = PURPLE_IRCV3_CONNECTION(obj);
-	PurpleAccount *account = NULL;
+	PurpleConnection *purple_connection = NULL;
 	gchar **userparts = NULL;
 	const gchar *username = NULL;
 
 	G_OBJECT_CLASS(purple_ircv3_connection_parent_class)->constructed(obj);
 
-	account = purple_connection_get_account(PURPLE_CONNECTION(connection));
+	purple_connection = purple_account_get_connection(connection->account);
 
 	/* Make sure the username (which includes the servername via usersplits),
 	 * does not contain any whitespace.
 	 */
-	username = purple_account_get_username(account);
+	username = purple_account_get_username(connection->account);
 	if(strpbrk(username, " \t\v\r\n") != NULL) {
 		g_set_error(&connection->validate_error,
 		            PURPLE_CONNECTION_ERROR,
@@ -301,8 +339,7 @@
 
 	/* Split the username into nick and server and store the values. */
 	userparts = g_strsplit(username, "@", 2);
-	purple_connection_set_display_name(PURPLE_CONNECTION(connection),
-	                                   userparts[0]);
+	purple_connection_set_display_name(purple_connection, userparts[0]);
 	connection->server_name = g_strdup(userparts[1]);
 	g_strfreev(userparts);
 
@@ -329,6 +366,19 @@
 	obj_class->finalize = purple_ircv3_connection_finalize;
 
 	/**
+	 * PurpleIRCv3Connection:account:
+	 *
+	 * The [class@Purple.Account] that this connection is for.
+	 *
+	 * Since: 3.0.0
+	 */
+	properties[PROP_ACCOUNT] = g_param_spec_object(
+		"account", "account",
+		"The account for this connection",
+		PURPLE_TYPE_ACCOUNT,
+		G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+	/**
 	 * PurpleIRCv3Connection:cancellable:
 	 *
 	 * The [class@Gio.Cancellable] for this connection.
@@ -368,6 +418,21 @@
 	purple_ircv3_connection_register_type(G_TYPE_MODULE(plugin));
 }
 
+PurpleIRCv3Connection *
+purple_ircv3_connection_new(PurpleAccount *account) {
+	return g_object_new(
+		PURPLE_IRCV3_TYPE_CONNECTION,
+		"account", account,
+		NULL);
+}
+
+PurpleAccount *
+purple_ircv3_connection_get_account(PurpleIRCv3Connection *connection) {
+	g_return_val_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection), NULL);
+
+	return connection->account;
+}
+
 GCancellable *
 purple_ircv3_connection_get_cancellable(PurpleIRCv3Connection *connection) {
 	g_return_val_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection), NULL);
@@ -393,7 +458,7 @@
 
 void
 purple_ircv3_connection_connect(PurpleIRCv3Connection *connection) {
-	PurpleAccount *account = NULL;
+	PurpleConnection *purple_connection = NULL;
 	GError *error = NULL;
 	GSocketClient *client = NULL;
 	gint default_port = PURPLE_IRCV3_DEFAULT_TLS_PORT;
@@ -403,29 +468,29 @@
 	g_return_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection));
 	g_return_if_fail(connection->connection == NULL);
 
-	account = purple_connection_get_account(PURPLE_CONNECTION(connection));
-	client = purple_gio_socket_client_new(account, &error);
+	purple_connection = purple_account_get_connection(connection->account);
+	client = purple_gio_socket_client_new(connection->account, &error);
 	if(!G_IS_SOCKET_CLIENT(client)) {
-		purple_connection_take_error(PURPLE_CONNECTION(connection), error);
+		purple_connection_take_error(purple_connection, error);
 
 		return;
 	}
 
 	/* Turn on TLS if requested. */
-	use_tls = purple_account_get_bool(account, "use-tls", TRUE);
+	use_tls = purple_account_get_bool(connection->account, "use-tls", TRUE);
 	g_socket_client_set_tls(client, use_tls);
 
 	/* If TLS is not being used, set the default port to the plain port. */
 	if(!use_tls) {
 		default_port = PURPLE_IRCV3_DEFAULT_PLAIN_PORT;
 	}
-	port = purple_account_get_int(account, "port", default_port);
+	port = purple_account_get_int(connection->account, "port", default_port);
 
 	/* Finally start the async connection. */
 	g_socket_client_connect_to_host_async(client, connection->server_name,
 	                                      port, connection->cancellable,
 	                                      purple_ircv3_connection_connected_cb,
-	                                      connection);
+	                                      purple_connection);
 
 	g_clear_object(&client);
 }
diff --git a/libpurple/protocols/ircv3/purpleircv3core.h b/libpurple/protocols/ircv3/purpleircv3core.h
--- a/libpurple/protocols/ircv3/purpleircv3core.h
+++ b/libpurple/protocols/ircv3/purpleircv3core.h
@@ -27,6 +27,8 @@
 
 #define PURPLE_IRCV3_DOMAIN (g_quark_from_static_string("ircv3-plugin"))
 
+#define PURPLE_IRCV3_CONNECTION_KEY "ircv3-connection"
+
 #define PURPLE_IRCV3_CONNECTION_CAP_VERSION "302"
 
 #endif /* PURPLE_IRCV3_CORE_H */
diff --git a/libpurple/protocols/ircv3/purpleircv3protocol.c b/libpurple/protocols/ircv3/purpleircv3protocol.c
--- a/libpurple/protocols/ircv3/purpleircv3protocol.c
+++ b/libpurple/protocols/ircv3/purpleircv3protocol.c
@@ -84,38 +84,44 @@
 	return options;
 }
 
-static PurpleConnection *
-purple_ircv3_protocol_login(PurpleProtocol *protocol, PurpleAccount *account,
-                            const char *password)
+static void
+purple_ircv3_protocol_login(G_GNUC_UNUSED PurpleProtocol *protocol,
+                            PurpleAccount *account)
 {
-	PurpleConnection *connection = NULL;
+	PurpleIRCv3Connection *connection = NULL;
+	PurpleConnection *purple_connection = NULL;
 	GError *error = NULL;
-	gboolean valid = FALSE;
 
-	connection = g_object_new(
-		PURPLE_IRCV3_TYPE_CONNECTION,
-		"protocol", protocol,
-		"account", account,
-		"password", password,
-		NULL);
+	purple_connection = purple_account_get_connection(account);
 
-	valid = purple_ircv3_connection_valid(PURPLE_IRCV3_CONNECTION(connection),
-	                                      &error);
-	if(!valid) {
-		purple_connection_take_error(connection, error);
-	} else {
-		purple_ircv3_connection_connect(PURPLE_IRCV3_CONNECTION(connection));
+	connection = purple_ircv3_connection_new(account);
+	if(!purple_ircv3_connection_valid(connection, &error)) {
+		purple_connection_take_error(purple_connection, error);
+
+		return;
 	}
 
+	g_object_set_data_full(G_OBJECT(purple_connection),
+	                       PURPLE_IRCV3_CONNECTION_KEY,
+	                       connection, g_object_unref);
 
-	return connection;
+	purple_ircv3_connection_connect(connection);
 }
 
 static void
 purple_ircv3_protocol_close(G_GNUC_UNUSED PurpleProtocol *protocol,
-                            PurpleConnection *connection)
+                            PurpleConnection *purple_connection)
 {
-	purple_ircv3_connection_close(PURPLE_IRCV3_CONNECTION(connection));
+	PurpleIRCv3Connection *connection = NULL;
+
+	connection = g_object_get_data(G_OBJECT(purple_connection),
+	                               PURPLE_IRCV3_CONNECTION_KEY);
+
+	purple_ircv3_connection_close(connection);
+
+	/* Set our connection data to NULL which will remove the last reference. */
+	g_object_set_data(G_OBJECT(purple_connection), PURPLE_IRCV3_CONNECTION_KEY,
+	                  NULL);
 }
 
 static GList *
diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c
--- a/libpurple/protocols/jabber/jabber.c
+++ b/libpurple/protocols/jabber/jabber.c
@@ -1003,21 +1003,17 @@
 	}
 }
 
-static PurpleConnection *
-jabber_login(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleAccount *account,
-             const char *password)
-{
-	PurpleConnection *gc = NULL;
+static void
+jabber_login(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleAccount *account) {
+	PurpleConnection *gc = purple_account_get_connection(account);
 	JabberStream *js;
 	PurpleImage *image;
 
-	gc = purple_connection_new(protocol, account, password);
-
 	purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_HTML |
 		PURPLE_CONNECTION_FLAG_NO_IMAGES);
 	js = jabber_stream_new(account);
 	if (js == NULL)
-		return gc;
+		return;
 
 	/* replace old default proxies with the new default: NULL
 	 * TODO: these can eventually be removed */
@@ -1041,8 +1037,6 @@
 	}
 
 	jabber_stream_connect(js);
-
-	return gc;
 }
 
 
@@ -1499,12 +1493,9 @@
 	JabberStream *js;
 
 	if (purple_connection_get_state(gc) != PURPLE_CONNECTION_STATE_CONNECTED) {
-		#warning fix registration and unregistration
-		#if 0
-		if (purple_connection_get_state(gc) != PURPLE_CONNECTION_CONNECTING) {
+		if (purple_connection_get_state(gc) != PURPLE_CONNECTION_STATE_CONNECTING) {
 			jabber_login(PURPLE_PROTOCOL(protocol_server), account);
 		}
-		#endif
 
 		js = purple_connection_get_protocol_data(gc);
 		js->unregistration = TRUE;
diff --git a/libpurple/protocols/novell/novell.c b/libpurple/protocols/novell/novell.c
--- a/libpurple/protocols/novell/novell.c
+++ b/libpurple/protocols/novell/novell.c
@@ -2184,10 +2184,8 @@
  * Protocol Ops
  ******************************************************************************/
 
-static PurpleConnection *
-novell_login(PurpleProtocol *protocol, PurpleAccount *account,
-             const char *password)
-{
+static void
+novell_login(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleAccount *account) {
 	PurpleConnection *gc;
 	NMUser *user = NULL;
 	const char *server;
@@ -2195,7 +2193,12 @@
 	int port;
 	GError *error = NULL;
 
-	gc = purple_connection_new(protocol, account, password);
+	if (account == NULL)
+		return;
+
+	gc = purple_account_get_connection(account);
+	if (gc == NULL)
+		return;
 
 	purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_NO_IMAGES);
 
@@ -2211,7 +2214,7 @@
 			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
 			_("Unable to connect to server. Please enter the "
 			  "address of the server to which you wish to connect."));
-		return gc;
+		return;
 	}
 
 	port = purple_account_get_int(account, "port", DEFAULT_PORT);
@@ -2226,7 +2229,7 @@
 		user->conn->client = purple_gio_socket_client_new(account, &error);
 		if (user->conn->client == NULL) {
 			purple_connection_take_error(gc, error);
-			return gc;
+			return;
 		}
 
 		g_socket_client_set_tls(user->conn->client, TRUE);
@@ -2234,8 +2237,6 @@
 		        user->conn->client, user->conn->addr, user->conn->port,
 		        user->cancellable, novell_login_callback, gc);
 	}
-
-	return gc;
 }
 
 static void
diff --git a/libpurple/protocols/sametime/sametime.c b/libpurple/protocols/sametime/sametime.c
--- a/libpurple/protocols/sametime/sametime.c
+++ b/libpurple/protocols/sametime/sametime.c
@@ -3522,9 +3522,9 @@
 }
 
 
-static PurpleConnection *
-mw_protocol_login(PurpleProtocol *protocol, PurpleAccount *account,
-                  const char *password)
+static void
+mw_protocol_login(G_GNUC_UNUSED PurpleProtocol *protocol,
+                  PurpleAccount *account)
 {
   PurpleConnection *gc;
   struct mwPurpleProtocolData *pd;
@@ -3534,7 +3534,7 @@
 
   GError *error = NULL;
 
-  gc = purple_connection_new(protocol, account, password);
+  gc = purple_account_get_connection(account);
   pd = mwPurpleProtocolData_new(gc);
 
   /* while we do support images, the default is to not offer it */
@@ -3561,7 +3561,7 @@
     purple_connection_error(gc,
             PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
             _("A server is required to connect this account"));
-    return gc;
+    return;
   }
 
   pass = g_strdup(purple_connection_get_password(gc));
@@ -3603,15 +3603,13 @@
   pd->client = purple_gio_socket_client_new(account, &error);
   if (pd->client == NULL) {
     purple_connection_take_error(gc, error);
-    return gc;
+    return;
   }
 
   g_socket_client_connect_to_host_async(
           pd->client, host,
           port, pd->cancellable,
           connect_cb, pd);
-
-  return gc;
 }
 
 
diff --git a/libpurple/protocols/silc/silc.c b/libpurple/protocols/silc/silc.c
--- a/libpurple/protocols/silc/silc.c
+++ b/libpurple/protocols/silc/silc.c
@@ -575,9 +575,9 @@
 	silcpurple_continue_running(sg);
 }
 
-static PurpleConnection *
-silcpurple_login(PurpleProtocol *protocol, PurpleAccount *account,
-                 const char *password)
+static void
+silcpurple_login(G_GNUC_UNUSED PurpleProtocol *protocol,
+                 PurpleAccount *account)
 {
 	SilcClient client;
 	PurpleConnection *gc;
@@ -587,7 +587,10 @@
 	char *username, *hostname, *realname, **up;
 	int i;
 
-	gc = purple_connection_new(protocol, account, password);
+	gc = purple_account_get_connection(account);
+	if (!gc)
+		return;
+
 	purple_connection_set_protocol_data(gc, NULL);
 
 	memset(&params, 0, sizeof(params));
@@ -598,7 +601,7 @@
 	if (!client) {
 		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 		                             _("Out of memory"));
-		return gc;
+		return;
 	}
 
 	/* Get username, real name and local hostname for SILC library */
@@ -638,7 +641,7 @@
 
 	sg = silc_calloc(1, sizeof(*sg));
 	if (!sg)
-		return gc;
+		return;
 	sg->cancellable = g_cancellable_new();
 	sg->client = client;
 	sg->gc = gc;
@@ -654,7 +657,7 @@
 		silcpurple_free(sg);
 		silc_free(hostname);
 		g_free(username);
-		return gc;
+		return;
 	}
 	silc_free(hostname);
 	g_free(username);
@@ -665,7 +668,7 @@
 		                             _("Error loading SILC key pair"));
 		purple_connection_set_protocol_data(gc, NULL);
 		silcpurple_free(sg);
-		return gc;
+		return;
 	}
 
 	/* Run SILC scheduler */
@@ -673,8 +676,6 @@
 	silc_schedule_set_notify(client->schedule, silcpurple_scheduler,
 				 client);
 	silc_client_run_one(client);
-
-	return gc;
 }
 
 static int
diff --git a/libpurple/protocols/zephyr/zephyr.c b/libpurple/protocols/zephyr/zephyr.c
--- a/libpurple/protocols/zephyr/zephyr.c
+++ b/libpurple/protocols/zephyr/zephyr.c
@@ -672,17 +672,15 @@
 	return g_strdup(realm);
 }
 
-static PurpleConnection *
-zephyr_login(PurpleProtocol *protocol, PurpleAccount *account,
-             const char *password)
-{
+static void
+zephyr_login(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleAccount *account) {
 	PurpleConnection *gc;
 	zephyr_account *zephyr;
 	ZephyrLoginFunc login;
 	GSourceFunc check_notify;
 	ZSubscription_t sub;
 
-	gc = purple_connection_new(protocol, account, password);
+	gc = purple_account_get_connection(account);
 
 #ifdef WIN32
 	username = purple_account_get_username(account);
@@ -721,7 +719,7 @@
 	zephyr->encoding = (char *)purple_account_get_string(account, "encoding", ZEPHYR_FALLBACK_CHARSET);
 
 	if (!login(zephyr)) {
-		return gc;
+		return;
 	}
 	purple_debug_info("zephyr","does it get here\n");
 	purple_debug_info("zephyr"," realm: %s username:%s\n", zephyr->realm, zephyr->username);
@@ -741,7 +739,7 @@
 		purple_notify_error(gc, NULL,
 			"Unable to subscribe to messages", "Unable to subscribe to initial messages",
 			purple_request_cpar_from_connection(gc));
-		return gc;
+		return;
 	}
 
 	purple_connection_set_state(gc, PURPLE_CONNECTION_STATE_CONNECTED);
@@ -755,8 +753,6 @@
 
 	zephyr->nottimer = g_timeout_add(100, check_notify, gc);
 	zephyr->loctimer = g_timeout_add_seconds(20, check_loc, zephyr);
-
-	return gc;
 }
 
 static void write_zsubs(zephyr_account *zephyr)
diff --git a/libpurple/purpleprotocol.h b/libpurple/purpleprotocol.h
--- a/libpurple/purpleprotocol.h
+++ b/libpurple/purpleprotocol.h
@@ -141,7 +141,7 @@
 	PurpleBuddyIconSpec *(*get_buddy_icon_spec)(PurpleProtocol *protocol);
 	PurpleWhiteboardOps *(*get_whiteboard_ops)(PurpleProtocol *protocol);
 
-	PurpleConnection *(*login)(PurpleProtocol *protocol, PurpleAccount *account, const char *password);
+	void (*login)(PurpleProtocol *protocol, PurpleAccount *account);
 
 	void (*close)(PurpleProtocol *protocol, PurpleConnection *connection);
 
@@ -270,18 +270,12 @@
  * purple_protocol_login:
  * @protocol: The instance.
  * @account: The [class@Purple.Account] to login.
- * @password: The password for this connection.
  *
- * Logs @account in to @protocol using @password.
- *
- * In simple cases, you can just pass the values to
- * [ctor@Purple.Connection.new] and return that value.
- *
- * Returns: (transfer full): The new connection.
+ * Logs @account in to @protocol.
  *
  * Since: 3.0.0
  */
-PurpleConnection *purple_protocol_login(PurpleProtocol *protocol, PurpleAccount *account, const char *password);
+void purple_protocol_login(PurpleProtocol *protocol, PurpleAccount *account);
 
 /**
  * purple_protocol_close:
diff --git a/libpurple/purpleprotocol.c b/libpurple/purpleprotocol.c
--- a/libpurple/purpleprotocol.c
+++ b/libpurple/purpleprotocol.c
@@ -522,21 +522,17 @@
 	return NULL;
 }
 
-PurpleConnection *
-purple_protocol_login(PurpleProtocol *protocol, PurpleAccount *account,
-                      const char *password)
-{
+void
+purple_protocol_login(PurpleProtocol *protocol, PurpleAccount *account) {
 	PurpleProtocolClass *klass = NULL;
 
-	g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), NULL);
-	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
+	g_return_if_fail(PURPLE_IS_PROTOCOL(protocol));
+	g_return_if_fail(PURPLE_IS_ACCOUNT(account));
 
 	klass = PURPLE_PROTOCOL_GET_CLASS(protocol);
 	if(klass != NULL && klass->login != NULL) {
-		return klass->login(protocol, account, password);
+		klass->login(protocol, account);
 	}
-
-	return NULL;
 }
 
 void
