identity: allow using and updating the "password" property

So far, only the "username" property was used once identity providers
were involved. The upcoming oauth2 provider uses the "password"
property for the refresh token and needs the ability to store a new
token if the OAuth2 server updates it.

Setting the new value will not always be possible (for example,
when running a command line operation where all properties were
provided on the command line without a permanent config). This still
needs to be handled.
This commit is contained in:
Mateusz Polrola 2014-09-08 12:00:15 +02:00 committed by Patrick Ohly
parent f2b2ea4271
commit b747a8c2e4
8 changed files with 26 additions and 14 deletions

View File

@ -199,7 +199,8 @@ public:
virtual Credentials getCredentials() const { SE_THROW("only OAuth2 is supported"); }
virtual std::string getOAuth2Bearer(int failedTokens) const
virtual std::string getOAuth2Bearer(int failedTokens,
const PasswordUpdateCallback &passwordUpdateCallback) const
{
m_account->m_ensureCredentials();
std::string token = m_account->m_getAccessToken();

View File

@ -85,7 +85,8 @@ public:
virtual Credentials getCredentials() const { SE_THROW("only OAuth2 is supported"); }
virtual std::string getOAuth2Bearer(int failedTokens) const
virtual std::string getOAuth2Bearer(int failedTokens,
const PasswordUpdateCallback &passwordUpdateCallback) const
{
SE_LOG_DEBUG(NULL, "retrieving OAuth2 token, attempt %d", failedTokens);

View File

@ -957,7 +957,8 @@ void Session::checkAuthorization()
// Count the number of times we asked for new tokens. This helps
// the provider determine whether the token that it returns are valid.
try {
m_oauth2Bearer = m_authProvider->getOAuth2Bearer(m_oauthTokenRejections);
m_oauth2Bearer = m_authProvider->getOAuth2Bearer(m_oauthTokenRejections,
boost::bind(&Settings::updatePassword, m_settings, _1));
SE_LOG_DEBUG(NULL, "got new OAuth2 token '%s' for next request", m_oauth2Bearer.c_str());
} catch (...) {
std::string explanation;

View File

@ -93,6 +93,11 @@ class Settings {
*/
virtual boost::shared_ptr<AuthProvider> getAuthProvider() = 0;
/**
* Updates password to new one returned during OAuth2 authorization.
*/
virtual void updatePassword(const std::string& password) = 0;
/**
* Google returns a 401 error even if the credentials
* are valid. It seems to use that to throttle request

View File

@ -157,6 +157,8 @@ public:
virtual boost::shared_ptr<AuthProvider> getAuthProvider();
void updatePassword(const string &password);
std::string getUsername()
{
lookupAuthProvider();
@ -205,6 +207,12 @@ boost::shared_ptr<AuthProvider> ContextSettings::getAuthProvider()
return m_authProvider;
}
void ContextSettings::updatePassword(const std::string &password)
{
m_context->setSyncPassword(password, false);
m_context->flush();
}
void ContextSettings::lookupAuthProvider()
{
if (m_authProvider) {

View File

@ -61,7 +61,7 @@ public:
virtual bool wasConfigured() const { return !m_creds.m_username.empty() || !m_creds.m_password.empty(); }
virtual bool methodIsSupported(AuthMethod method) const { return method == AUTH_METHOD_CREDENTIALS; }
virtual Credentials getCredentials() const { return m_creds; }
virtual std::string getOAuth2Bearer(int failedTokens) const { SE_THROW("OAuth2 not supported"); return ""; }
virtual std::string getOAuth2Bearer(int failedTokens, const PasswordUpdateCallback &passwordUpdateCallback) const { SE_THROW("OAuth2 not supported"); return ""; }
virtual std::string getUsername() const { return m_creds.m_username; }
};

View File

@ -104,11 +104,15 @@ class AuthProvider
* To achieve that, the caller must count how often he got a token that
* did not work.
*
* @param failedTokens zero when asking for initial token, one for refresh, two for full re-authorization
* @param failedTokens zero when asking for initial token, one for refresh, two for full re-authorization
* @param passwordUpdateCallback callback function to be called when stored refresh token need to be updated.
* Only parameter of this callback function is new value of refresh token.
*
* @return a base64 encoded token, ready to be used in "Authorization: Bearer %s"
*/
virtual std::string getOAuth2Bearer(int failedTokens) const = 0;
typedef boost::function<void (const std::string &newPassword)> PasswordUpdateCallback;
virtual std::string getOAuth2Bearer(int failedTokens,
const PasswordUpdateCallback &passwordUpdateCallback) const = 0;
/**
* Returns username at the remote service. Works for

View File

@ -2194,14 +2194,6 @@ void PasswordConfigProperty::savePassword(UserInterface &ui,
}
credConfig->setSyncPassword(password, false);
syncPropPassword.savePassword(ui, *credConfig);
} else if (identity.m_provider != USER_IDENTITY_PLAIN_TEXT) {
// Cannot store passwords in providers.
if (password.wasSet() && !password.empty()) {
SE_THROW(StringPrintf("setting property '%s' not supported for provider '%s' from property '%s'",
getMainName().c_str(),
identity.m_provider.c_str(),
usernameProperty.getMainName().c_str()));
}
} else {
if (password == "-" || password == "" ||
(boost::starts_with(password, "${") && boost::ends_with(password, "}"))) {