signon: move libaccounts-based plugins into their own source file
The libaccounts-based backends ("gsso" and "uoa") are going to use more of libaccounts-glib, making sharing of code with the plain "signon" plugin much harder to maintain.
This commit is contained in:
parent
75115022c5
commit
ab4524ab9f
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) version 3.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <syncevo/IdentityProvider.h>
|
||||
|
||||
#ifdef USE_SIGNON
|
||||
#ifdef USE_GSSO
|
||||
#include "libgsignon-glib/signon-auth-service.h"
|
||||
#include "libgsignon-glib/signon-identity.h"
|
||||
#elif defined USE_UOA
|
||||
#include "libsignon-glib/signon-auth-service.h"
|
||||
#include "libsignon-glib/signon-identity.h"
|
||||
#endif // USE_GSSO
|
||||
#include "libaccounts-glib/ag-account.h"
|
||||
#include "libaccounts-glib/ag-account-service.h"
|
||||
#include <libaccounts-glib/ag-auth-data.h>
|
||||
#include <libaccounts-glib/ag-service.h>
|
||||
#include <libaccounts-glib/ag-manager.h>
|
||||
|
||||
#include <syncevo/GLibSupport.h>
|
||||
#include <syncevo/GVariantSupport.h>
|
||||
#include <pcrecpp.h>
|
||||
|
||||
#include <boost/lambda/core.hpp>
|
||||
|
||||
SE_GOBJECT_TYPE(SignonAuthService)
|
||||
SE_GOBJECT_TYPE(SignonAuthSession)
|
||||
SE_GOBJECT_TYPE(SignonIdentity)
|
||||
|
||||
SE_GOBJECT_TYPE(AgAccount)
|
||||
SE_GOBJECT_TYPE(AgAccountService)
|
||||
SE_GOBJECT_TYPE(AgManager)
|
||||
SE_GLIB_TYPE(AgService, ag_service)
|
||||
SE_GLIB_TYPE(AgAuthData, ag_auth_data)
|
||||
|
||||
#endif // USE_SIGNON
|
||||
|
||||
#include <syncevo/declarations.h>
|
||||
SE_BEGIN_CXX
|
||||
|
||||
#ifdef USE_SIGNON
|
||||
|
||||
typedef GListCXX<AgService, GList, ag_service_unref> ServiceListCXX;
|
||||
|
||||
class SignonAuthProvider : public AuthProvider
|
||||
{
|
||||
SignonAuthSessionCXX m_authSession;
|
||||
GHashTableCXX m_sessionData;
|
||||
std::string m_mechanism;
|
||||
|
||||
public:
|
||||
SignonAuthProvider(const SignonAuthSessionCXX &authSession,
|
||||
const GHashTableCXX &sessionData,
|
||||
const std::string &mechanism) :
|
||||
m_authSession(authSession),
|
||||
m_sessionData(sessionData),
|
||||
m_mechanism(mechanism)
|
||||
{}
|
||||
|
||||
virtual bool methodIsSupported(AuthMethod method) const { return method == AUTH_METHOD_OAUTH2; }
|
||||
|
||||
virtual Credentials getCredentials() const { SE_THROW("only OAuth2 is supported"); }
|
||||
|
||||
virtual std::string getOAuth2Bearer(int failedTokens,
|
||||
const PasswordUpdateCallback &passwordUpdateCallback) const
|
||||
{
|
||||
SE_LOG_DEBUG(NULL, "retrieving OAuth2 token, attempt %d", failedTokens);
|
||||
|
||||
// Retry login if even the refreshed token failed.
|
||||
g_hash_table_insert(m_sessionData, g_strdup("UiPolicy"),
|
||||
g_variant_ref_sink(g_variant_new_uint32(failedTokens >= 2 ? SIGNON_POLICY_REQUEST_PASSWORD : 0)));
|
||||
// We get assigned a plain pointer to an instance that we'll own,
|
||||
// so we have to use the "steal" variant to enable that assignment.
|
||||
GVariantStealCXX resultDataVar;
|
||||
GErrorCXX gerror;
|
||||
GVariantCXX sessionDataVar(HashTable2Variant(m_sessionData));
|
||||
PlainGStr buffer(g_variant_print(sessionDataVar, true));
|
||||
SE_LOG_DEBUG(NULL, "asking for OAuth2 token with method %s, mechanism %s and parameters %s",
|
||||
signon_auth_session_get_method(m_authSession),
|
||||
m_mechanism.c_str(),
|
||||
buffer.get());
|
||||
|
||||
#define signon_auth_session_process_async_finish signon_auth_session_process_finish
|
||||
SYNCEVO_GLIB_CALL_SYNC(resultDataVar, gerror, signon_auth_session_process_async,
|
||||
m_authSession, sessionDataVar, m_mechanism.c_str(), NULL);
|
||||
buffer.reset(resultDataVar ? g_variant_print(resultDataVar, true) : NULL);
|
||||
SE_LOG_DEBUG(NULL, "OAuth2 token result: %s, %s",
|
||||
buffer.get() ? buffer.get() : "<<null>>",
|
||||
gerror ? gerror->message : "???");
|
||||
if (!resultDataVar || gerror) {
|
||||
SE_THROW_EXCEPTION_STATUS(StatusException,
|
||||
StringPrintf("could not obtain OAuth2 token: %s", gerror ? gerror->message : "???"),
|
||||
STATUS_FORBIDDEN);
|
||||
}
|
||||
GHashTableCXX resultData(Variant2HashTable(resultDataVar));
|
||||
GVariant *tokenVar = static_cast<GVariant *>(g_hash_table_lookup(resultData, (gpointer)"AccessToken"));
|
||||
if (!tokenVar) {
|
||||
SE_THROW("no AccessToken in OAuth2 response");
|
||||
}
|
||||
const char *token = g_variant_get_string(tokenVar, NULL);
|
||||
if (!token) {
|
||||
SE_THROW("AccessToken did not contain a string value");
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
virtual std::string getUsername() const { return ""; }
|
||||
};
|
||||
|
||||
class StoreIdentityData
|
||||
{
|
||||
public:
|
||||
StoreIdentityData() : m_running(true) {}
|
||||
|
||||
bool m_running;
|
||||
guint32 m_id;
|
||||
GErrorCXX m_gerror;
|
||||
};
|
||||
|
||||
static void StoreIdentityCB(SignonIdentity *self,
|
||||
guint32 id,
|
||||
const GError *error,
|
||||
gpointer userData)
|
||||
{
|
||||
StoreIdentityData *data = reinterpret_cast<StoreIdentityData *>(userData);
|
||||
data->m_running = false;
|
||||
data->m_id = id;
|
||||
data->m_gerror = error;
|
||||
}
|
||||
|
||||
boost::shared_ptr<AuthProvider> createSignonAuthProvider(const InitStateString &username,
|
||||
const InitStateString &password)
|
||||
{
|
||||
boost::shared_ptr<AuthProvider> provider;
|
||||
|
||||
// Split username into <account ID> and <service name>.
|
||||
// Be flexible and allow leading/trailing white space.
|
||||
// Comma is optional.
|
||||
static const pcrecpp::RE re("^\\s*(\\d+)\\s*,?\\s*(.*)\\s*$");
|
||||
AgAccountId accountID;
|
||||
std::string serviceName;
|
||||
if (!re.FullMatch(username, &accountID, &serviceName)) {
|
||||
SE_THROW(StringPrintf("username must have the format gsso:<account ID>,<service name>: %s",
|
||||
username.c_str()));
|
||||
}
|
||||
SE_LOG_DEBUG(NULL, "looking up account ID %d and service '%s'",
|
||||
accountID,
|
||||
serviceName.c_str());
|
||||
AgManagerCXX manager(ag_manager_new(), TRANSFER_REF);
|
||||
GErrorCXX gerror;
|
||||
AgAccountCXX account(ag_manager_load_account(manager, accountID, gerror), TRANSFER_REF);
|
||||
if (!account) {
|
||||
gerror.throwError(SE_HERE, StringPrintf("loading account with ID %d from %s failed",
|
||||
accountID,
|
||||
username.c_str()));
|
||||
}
|
||||
if (!ag_account_get_enabled(account)) {
|
||||
SE_THROW(StringPrintf("account with ID %d from %s is disabled, refusing to use it",
|
||||
accountID,
|
||||
username.c_str()));
|
||||
}
|
||||
AgAccountServiceCXX accountService;
|
||||
if (serviceName.empty()) {
|
||||
accountService = AgAccountServiceCXX::steal(ag_account_service_new(account, NULL));
|
||||
} else {
|
||||
ServiceListCXX services(ag_account_list_enabled_services(account));
|
||||
BOOST_FOREACH (AgService *service, services) {
|
||||
const char *name = ag_service_get_name(service);
|
||||
SE_LOG_DEBUG(NULL, "enabled service: %s", name);
|
||||
if (serviceName == name) {
|
||||
accountService = AgAccountServiceCXX::steal(ag_account_service_new(account, service));
|
||||
// Do *not* select the service for reading/writing properties.
|
||||
// AgAccountService does this internally, and when we create
|
||||
// a new identity below, we want it to be shared by all
|
||||
// services so that the user only needs to log in once.
|
||||
// ag_account_select_service(account, service);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!accountService) {
|
||||
SE_THROW(StringPrintf("service '%s' in account with ID %d not found or not enabled",
|
||||
serviceName.c_str(),
|
||||
accountID));
|
||||
}
|
||||
AgAuthDataCXX authData(ag_account_service_get_auth_data(accountService), TRANSFER_REF);
|
||||
|
||||
// SignonAuthServiceCXX authService(signon_auth_service_new(), TRANSFER_REF);
|
||||
guint signonID = ag_auth_data_get_credentials_id(authData);
|
||||
const char *method = ag_auth_data_get_method(authData);
|
||||
const char *mechanism = ag_auth_data_get_mechanism(authData);
|
||||
|
||||
GVariantCXX sessionDataVar(ag_auth_data_get_login_parameters(authData, NULL), TRANSFER_REF);
|
||||
GHashTableCXX sessionData(Variant2HashTable(sessionDataVar));
|
||||
#ifdef USE_GSSO
|
||||
GVariant *realmsVariant = (GVariant *)g_hash_table_lookup(sessionData, "Realms");
|
||||
PlainGStrArray realms(g_variant_dup_strv(realmsVariant, NULL));
|
||||
#endif
|
||||
|
||||
// Check that the service has a credentials ID. If not, create it and
|
||||
// store its ID permanently.
|
||||
if (!signonID) {
|
||||
SE_LOG_DEBUG(NULL, "have to create signon identity");
|
||||
SignonIdentityCXX identity(signon_identity_new(), TRANSFER_REF);
|
||||
boost::shared_ptr<SignonIdentityInfo> identityInfo(signon_identity_info_new(), signon_identity_info_free);
|
||||
signon_identity_info_set_caption(identityInfo.get(),
|
||||
StringPrintf("created by SyncEvolution for account #%d and service %s",
|
||||
accountID,
|
||||
serviceName.empty() ? "<<none>>" : serviceName.c_str()).c_str());
|
||||
const gchar *mechanisms[] = { mechanism ? mechanism : "*", NULL };
|
||||
signon_identity_info_set_method(identityInfo.get(), method, mechanisms);
|
||||
#ifdef USE_GSSO
|
||||
if (realms) {
|
||||
signon_identity_info_set_realms(identityInfo.get(), realms);
|
||||
}
|
||||
#endif
|
||||
StoreIdentityData data;
|
||||
signon_identity_store_credentials_with_info(identity, identityInfo.get(),
|
||||
StoreIdentityCB, &data);
|
||||
GRunWhile(boost::lambda::var(data.m_running));
|
||||
if (!data.m_id || data.m_gerror) {
|
||||
SE_THROW(StringPrintf("failed to create signon identity: %s",
|
||||
data.m_gerror ? data.m_gerror->message : "???"));
|
||||
}
|
||||
|
||||
// Now store in account.
|
||||
static const char CREDENTIALS_ID[] = "CredentialsId";
|
||||
ag_account_set_variant(account, CREDENTIALS_ID, g_variant_new_uint32(data.m_id));
|
||||
#define ag_account_store_async_finish ag_account_store_finish
|
||||
gboolean res;
|
||||
SYNCEVO_GLIB_CALL_SYNC(res, gerror, ag_account_store_async,
|
||||
account, NULL);
|
||||
if (!res) {
|
||||
gerror.throwError(SE_HERE, "failed to store account");
|
||||
}
|
||||
|
||||
authData = AgAuthDataCXX::steal(ag_account_service_get_auth_data(accountService));
|
||||
signonID = ag_auth_data_get_credentials_id(authData);
|
||||
if (!signonID) {
|
||||
SE_THROW("still no signonID?!");
|
||||
}
|
||||
method = ag_auth_data_get_method(authData);
|
||||
mechanism = ag_auth_data_get_mechanism(authData);
|
||||
}
|
||||
|
||||
SignonIdentityCXX identity(signon_identity_new_from_db(signonID), TRANSFER_REF);
|
||||
SE_LOG_DEBUG(NULL, "using signond identity %d", signonID);
|
||||
SignonAuthSessionCXX authSession(signon_identity_create_session(identity, method, gerror), TRANSFER_REF);
|
||||
|
||||
// TODO (?): retrieve start URL from account system
|
||||
|
||||
provider.reset(new SignonAuthProvider(authSession, sessionData, mechanism));
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
#endif // USE_SIGNON
|
||||
|
||||
SE_END_CXX
|
||||
|
|
@ -38,7 +38,6 @@ MOSTLYCLEANFILES += $(src_backends_signon_libs)
|
|||
|
||||
src_backends_signon_common_sources = \
|
||||
src/backends/signon/signon.h \
|
||||
src/backends/signon/signon.cpp \
|
||||
$(NONE)
|
||||
|
||||
if ENABLE_MODULES
|
||||
|
@ -57,7 +56,9 @@ src_backends_signon_common_cppflags = -DUSE_SIGNON -I$(top_srcdir)/test $(BACKEN
|
|||
src_backends_signon_common_dependencies = src/syncevo/libsyncevolution.la
|
||||
|
||||
if USE_GSSO
|
||||
src_backends_signon_providergsso_la_SOURCES = $(src_backends_signon_common_sources)
|
||||
src_backends_signon_providergsso_la_SOURCES = \
|
||||
src/backends/signon/signon-accounts.cpp \
|
||||
$(src_backends_signon_common_sources)
|
||||
src_backends_signon_providergsso_la_LIBADD = $(GSSO_LIBS) $(ACCOUNTS_LIBS) $(src_backends_signon_common_libadd)
|
||||
src_backends_signon_providergsso_la_LDFLAGS = $(src_backends_signon_common_ldflags)
|
||||
src_backends_signon_providergsso_la_CXXFLAGS = $(GSSO_CFLAGS) $(ACCOUNTS_CFLAGS) $(src_backends_signon_common_cxxflags)
|
||||
|
@ -66,7 +67,9 @@ src_backends_signon_providergsso_la_DEPENDENCIES = $(src_backends_signon_common_
|
|||
endif
|
||||
|
||||
if USE_UOA
|
||||
src_backends_signon_provideruoa_la_SOURCES = $(src_backends_signon_common_sources)
|
||||
src_backends_signon_provideruoa_la_SOURCES = \
|
||||
src/backends/signon/signon-accounts.cpp \
|
||||
$(src_backends_signon_common_sources)
|
||||
src_backends_signon_provideruoa_la_LIBADD = $(UOA_LIBS) $(ACCOUNTS_LIBS) $(src_backends_signon_common_libadd)
|
||||
src_backends_signon_provideruoa_la_LDFLAGS = $(src_backends_signon_common_ldflags)
|
||||
src_backends_signon_provideruoa_la_CXXFLAGS = $(UOA_CFLAGS) $(ACCOUNTS_CFLAGS) $(src_backends_signon_common_cxxflags)
|
||||
|
@ -75,7 +78,9 @@ src_backends_signon_provideruoa_la_DEPENDENCIES = $(src_backends_signon_common_d
|
|||
endif
|
||||
|
||||
if USE_SIGNON
|
||||
src_backends_signon_providersignon_la_SOURCES = $(src_backends_signon_common_sources)
|
||||
src_backends_signon_providersignon_la_SOURCES = \
|
||||
src/backends/signon/signon.cpp \
|
||||
$(src_backends_signon_common_sources)
|
||||
src_backends_signon_providersignon_la_LIBADD = $($(DEFAULT_SIGNON)_LIBS) $(ACCOUNTS_LIBS) $(src_backends_signon_common_libadd)
|
||||
src_backends_signon_providersignon_la_LDFLAGS = $(src_backends_signon_common_ldflags)
|
||||
src_backends_signon_providersignon_la_CXXFLAGS = $($(DEFAULT_SIGNON)_CFLAGS) $(ACCOUNTS_CFLAGS) $(src_backends_signon_common_cxxflags)
|
||||
|
|
|
@ -29,13 +29,6 @@
|
|||
#include "libsignon-glib/signon-auth-service.h"
|
||||
#include "libsignon-glib/signon-identity.h"
|
||||
#endif // USE_GSSO
|
||||
#ifdef USE_ACCOUNTS
|
||||
#include "libaccounts-glib/ag-account.h"
|
||||
#include "libaccounts-glib/ag-account-service.h"
|
||||
#include <libaccounts-glib/ag-auth-data.h>
|
||||
#include <libaccounts-glib/ag-service.h>
|
||||
#include <libaccounts-glib/ag-manager.h>
|
||||
#endif
|
||||
|
||||
#include <syncevo/GLibSupport.h>
|
||||
#include <syncevo/GVariantSupport.h>
|
||||
|
@ -47,14 +40,6 @@ SE_GOBJECT_TYPE(SignonAuthService)
|
|||
SE_GOBJECT_TYPE(SignonAuthSession)
|
||||
SE_GOBJECT_TYPE(SignonIdentity)
|
||||
|
||||
#ifdef USE_ACCOUNTS
|
||||
SE_GOBJECT_TYPE(AgAccount)
|
||||
SE_GOBJECT_TYPE(AgAccountService)
|
||||
SE_GOBJECT_TYPE(AgManager)
|
||||
SE_GLIB_TYPE(AgService, ag_service)
|
||||
SE_GLIB_TYPE(AgAuthData, ag_auth_data)
|
||||
#endif
|
||||
|
||||
#endif // USE_SIGNON
|
||||
|
||||
#include <syncevo/declarations.h>
|
||||
|
@ -62,10 +47,6 @@ SE_BEGIN_CXX
|
|||
|
||||
#ifdef USE_SIGNON
|
||||
|
||||
#ifdef USE_ACCOUNTS
|
||||
typedef GListCXX<AgService, GList, ag_service_unref> ServiceListCXX;
|
||||
#endif
|
||||
|
||||
class SignonAuthProvider : public AuthProvider
|
||||
{
|
||||
SignonAuthSessionCXX m_authSession;
|
||||
|
@ -131,156 +112,6 @@ public:
|
|||
virtual std::string getUsername() const { return ""; }
|
||||
};
|
||||
|
||||
#ifdef USE_ACCOUNTS
|
||||
class StoreIdentityData
|
||||
{
|
||||
public:
|
||||
StoreIdentityData() : m_running(true) {}
|
||||
|
||||
bool m_running;
|
||||
guint32 m_id;
|
||||
GErrorCXX m_gerror;
|
||||
};
|
||||
|
||||
static void StoreIdentityCB(SignonIdentity *self,
|
||||
guint32 id,
|
||||
const GError *error,
|
||||
gpointer userData)
|
||||
{
|
||||
StoreIdentityData *data = reinterpret_cast<StoreIdentityData *>(userData);
|
||||
data->m_running = false;
|
||||
data->m_id = id;
|
||||
data->m_gerror = error;
|
||||
}
|
||||
|
||||
boost::shared_ptr<AuthProvider> createSignonAuthProvider(const InitStateString &username,
|
||||
const InitStateString &password)
|
||||
{
|
||||
boost::shared_ptr<AuthProvider> provider;
|
||||
|
||||
// Split username into <account ID> and <service name>.
|
||||
// Be flexible and allow leading/trailing white space.
|
||||
// Comma is optional.
|
||||
static const pcrecpp::RE re("^\\s*(\\d+)\\s*,?\\s*(.*)\\s*$");
|
||||
AgAccountId accountID;
|
||||
std::string serviceName;
|
||||
if (!re.FullMatch(username, &accountID, &serviceName)) {
|
||||
SE_THROW(StringPrintf("username must have the format gsso:<account ID>,<service name>: %s",
|
||||
username.c_str()));
|
||||
}
|
||||
SE_LOG_DEBUG(NULL, "looking up account ID %d and service '%s'",
|
||||
accountID,
|
||||
serviceName.c_str());
|
||||
AgManagerCXX manager(ag_manager_new(), TRANSFER_REF);
|
||||
GErrorCXX gerror;
|
||||
AgAccountCXX account(ag_manager_load_account(manager, accountID, gerror), TRANSFER_REF);
|
||||
if (!account) {
|
||||
gerror.throwError(SE_HERE, StringPrintf("loading account with ID %d from %s failed",
|
||||
accountID,
|
||||
username.c_str()));
|
||||
}
|
||||
if (!ag_account_get_enabled(account)) {
|
||||
SE_THROW(StringPrintf("account with ID %d from %s is disabled, refusing to use it",
|
||||
accountID,
|
||||
username.c_str()));
|
||||
}
|
||||
AgAccountServiceCXX accountService;
|
||||
if (serviceName.empty()) {
|
||||
accountService = AgAccountServiceCXX::steal(ag_account_service_new(account, NULL));
|
||||
} else {
|
||||
ServiceListCXX services(ag_account_list_enabled_services(account));
|
||||
BOOST_FOREACH (AgService *service, services) {
|
||||
const char *name = ag_service_get_name(service);
|
||||
SE_LOG_DEBUG(NULL, "enabled service: %s", name);
|
||||
if (serviceName == name) {
|
||||
accountService = AgAccountServiceCXX::steal(ag_account_service_new(account, service));
|
||||
// Do *not* select the service for reading/writing properties.
|
||||
// AgAccountService does this internally, and when we create
|
||||
// a new identity below, we want it to be shared by all
|
||||
// services so that the user only needs to log in once.
|
||||
// ag_account_select_service(account, service);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!accountService) {
|
||||
SE_THROW(StringPrintf("service '%s' in account with ID %d not found or not enabled",
|
||||
serviceName.c_str(),
|
||||
accountID));
|
||||
}
|
||||
AgAuthDataCXX authData(ag_account_service_get_auth_data(accountService), TRANSFER_REF);
|
||||
|
||||
// SignonAuthServiceCXX authService(signon_auth_service_new(), TRANSFER_REF);
|
||||
guint signonID = ag_auth_data_get_credentials_id(authData);
|
||||
const char *method = ag_auth_data_get_method(authData);
|
||||
const char *mechanism = ag_auth_data_get_mechanism(authData);
|
||||
|
||||
GVariantCXX sessionDataVar(ag_auth_data_get_login_parameters(authData, NULL), TRANSFER_REF);
|
||||
GHashTableCXX sessionData(Variant2HashTable(sessionDataVar));
|
||||
#ifdef USE_GSSO
|
||||
GVariant *realmsVariant = (GVariant *)g_hash_table_lookup(sessionData, "Realms");
|
||||
PlainGStrArray realms(g_variant_dup_strv(realmsVariant, NULL));
|
||||
#endif
|
||||
|
||||
// Check that the service has a credentials ID. If not, create it and
|
||||
// store its ID permanently.
|
||||
if (!signonID) {
|
||||
SE_LOG_DEBUG(NULL, "have to create signon identity");
|
||||
SignonIdentityCXX identity(signon_identity_new(), TRANSFER_REF);
|
||||
boost::shared_ptr<SignonIdentityInfo> identityInfo(signon_identity_info_new(), signon_identity_info_free);
|
||||
signon_identity_info_set_caption(identityInfo.get(),
|
||||
StringPrintf("created by SyncEvolution for account #%d and service %s",
|
||||
accountID,
|
||||
serviceName.empty() ? "<<none>>" : serviceName.c_str()).c_str());
|
||||
const gchar *mechanisms[] = { mechanism ? mechanism : "*", NULL };
|
||||
signon_identity_info_set_method(identityInfo.get(), method, mechanisms);
|
||||
#ifdef USE_GSSO
|
||||
if (realms) {
|
||||
signon_identity_info_set_realms(identityInfo.get(), realms);
|
||||
}
|
||||
#endif
|
||||
StoreIdentityData data;
|
||||
signon_identity_store_credentials_with_info(identity, identityInfo.get(),
|
||||
StoreIdentityCB, &data);
|
||||
GRunWhile(boost::lambda::var(data.m_running));
|
||||
if (!data.m_id || data.m_gerror) {
|
||||
SE_THROW(StringPrintf("failed to create signon identity: %s",
|
||||
data.m_gerror ? data.m_gerror->message : "???"));
|
||||
}
|
||||
|
||||
// Now store in account.
|
||||
static const char CREDENTIALS_ID[] = "CredentialsId";
|
||||
ag_account_set_variant(account, CREDENTIALS_ID, g_variant_new_uint32(data.m_id));
|
||||
#define ag_account_store_async_finish ag_account_store_finish
|
||||
gboolean res;
|
||||
SYNCEVO_GLIB_CALL_SYNC(res, gerror, ag_account_store_async,
|
||||
account, NULL);
|
||||
if (!res) {
|
||||
gerror.throwError(SE_HERE, "failed to store account");
|
||||
}
|
||||
|
||||
authData = AgAuthDataCXX::steal(ag_account_service_get_auth_data(accountService));
|
||||
signonID = ag_auth_data_get_credentials_id(authData);
|
||||
if (!signonID) {
|
||||
SE_THROW("still no signonID?!");
|
||||
}
|
||||
method = ag_auth_data_get_method(authData);
|
||||
mechanism = ag_auth_data_get_mechanism(authData);
|
||||
}
|
||||
|
||||
SignonIdentityCXX identity(signon_identity_new_from_db(signonID), TRANSFER_REF);
|
||||
SE_LOG_DEBUG(NULL, "using signond identity %d", signonID);
|
||||
SignonAuthSessionCXX authSession(signon_identity_create_session(identity, method, gerror), TRANSFER_REF);
|
||||
|
||||
// TODO (?): retrieve start URL from account system
|
||||
|
||||
provider.reset(new SignonAuthProvider(authSession, sessionData, mechanism));
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
#else // USE_ACCOUNTS
|
||||
|
||||
boost::shared_ptr<AuthProvider> createSignonAuthProvider(const InitStateString &username,
|
||||
const InitStateString &password)
|
||||
{
|
||||
|
@ -340,9 +171,6 @@ boost::shared_ptr<AuthProvider> createSignonAuthProvider(const InitStateString &
|
|||
return provider;
|
||||
}
|
||||
|
||||
#endif // USE_ACCOUNTS
|
||||
|
||||
|
||||
#endif // USE_SIGNON
|
||||
|
||||
SE_END_CXX
|
||||
|
|
Loading…
Reference in New Issue