aboutsummaryrefslogtreecommitdiff
path: root/src/privet/auth_manager.cc
diff options
context:
space:
mode:
authorVitaly Buka <vitalybuka@google.com>2016-01-29 11:50:53 -0800
committerVitaly Buka <vitalybuka@google.com>2016-01-29 22:20:57 +0000
commit4fe71e314157576d2bdfe54cc6f8ce5df38c571d (patch)
treee9c0d8200c8462f87767f7059fc72c5594b8b547 /src/privet/auth_manager.cc
parent3cbb6869edd05975fc876844bfff52d12ac32f66 (diff)
downloadlibweave-4fe71e314157576d2bdfe54cc6f8ce5df38c571d.tar.gz
Make App ID a part of User ID
In addition to user ID, auth tokens could be bound to specific app ID. So internal libweave User ID, named UserAppId, from now will consist of auth type, user ID and optional app ID. If operation was called with token containing only user ID, libweave will grant access to all commands for every app for the given user ID. To distinguish between user authorized with local, pairing or anonymous tokens libweave uses UserAppId::type field. As macaroons have no caveats for this kind of information, current implementation will just append the type to the user ID caveat of the access token. BUG: 26292014 Change-Id: I528c2717c95c5daed74bb769b3569fac823761f2 Reviewed-on: https://weave-review.googlesource.com/2394 Reviewed-by: Alex Vakulenko <avakulenko@google.com>
Diffstat (limited to 'src/privet/auth_manager.cc')
-rw-r--r--src/privet/auth_manager.cc88
1 files changed, 64 insertions, 24 deletions
diff --git a/src/privet/auth_manager.cc b/src/privet/auth_manager.cc
index 3c08071..0b8a981 100644
--- a/src/privet/auth_manager.cc
+++ b/src/privet/auth_manager.cc
@@ -96,16 +96,26 @@ class ExpirationCaveat : public Caveat {
class UserIdCaveat : public Caveat {
public:
- explicit UserIdCaveat(const std::string& id)
+ explicit UserIdCaveat(const std::vector<uint8_t>& id)
: Caveat(kUwMacaroonCaveatTypeDelegateeUser, id.size()) {
CHECK(uw_macaroon_caveat_create_delegatee_user_(
- reinterpret_cast<const uint8_t*>(id.data()), id.size(), buffer_.data(),
- buffer_.size(), &caveat_));
+ id.data(), id.size(), buffer_.data(), buffer_.size(), &caveat_));
}
DISALLOW_COPY_AND_ASSIGN(UserIdCaveat);
};
+class AppIdCaveat : public Caveat {
+ public:
+ explicit AppIdCaveat(const std::vector<uint8_t>& id)
+ : Caveat(kUwMacaroonCaveatTypeDelegateeApp, id.size()) {
+ CHECK(uw_macaroon_caveat_create_delegatee_app_(
+ id.data(), id.size(), buffer_.data(), buffer_.size(), &caveat_));
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(AppIdCaveat);
+};
+
class ServiceCaveat : public Caveat {
public:
explicit ServiceCaveat(const std::string& id)
@@ -312,14 +322,19 @@ AuthManager::~AuthManager() {}
std::vector<uint8_t> AuthManager::CreateAccessToken(const UserInfo& user_info,
base::TimeDelta ttl) const {
ScopeCaveat scope{ToMacaroonScope(user_info.scope())};
- UserIdCaveat user{user_info.user_id()};
+ // Macaroons have no caveats for auth type. So we just append the type to the
+ // user ID.
+ std::vector<uint8_t> id_with_type{user_info.id().user};
+ id_with_type.push_back(static_cast<uint8_t>(user_info.id().type));
+ UserIdCaveat user{id_with_type};
+ AppIdCaveat app{user_info.id().app};
const base::Time now = Now();
ExpirationCaveat expiration{now + ttl};
- return CreateMacaroonToken(
- access_secret_, now,
- {
- &scope.GetCaveat(), &user.GetCaveat(), &expiration.GetCaveat(),
- });
+ return CreateMacaroonToken(access_secret_, now,
+ {
+ &scope.GetCaveat(), &user.GetCaveat(),
+ &app.GetCaveat(), &expiration.GetCaveat(),
+ });
}
bool AuthManager::ParseAccessToken(const std::vector<uint8_t>& token,
@@ -331,7 +346,7 @@ bool AuthManager::ParseAccessToken(const std::vector<uint8_t>& token,
UwMacaroonValidationResult result{};
const base::Time now = Now();
if (!LoadMacaroon(token, &buffer, &macaroon, error) ||
- macaroon.num_caveats != 3 ||
+ macaroon.num_caveats != 4 ||
!VerifyMacaroon(access_secret_, macaroon, now, &result, error)) {
return Error::AddTo(error, FROM_HERE, errors::kInvalidAuthorization,
"Invalid token");
@@ -346,12 +361,22 @@ bool AuthManager::ParseAccessToken(const std::vector<uint8_t>& token,
// If token is valid and token was not extended, it should has precisely this
// values.
CHECK_GE(FromJ2000Time(result.expiration_time), now);
- CHECK_EQ(1u, result.num_delegatees);
+ CHECK_EQ(2u, result.num_delegatees);
CHECK_EQ(kUwMacaroonDelegateeTypeUser, result.delegatees[0].type);
- std::string user_id{reinterpret_cast<const char*>(result.delegatees[0].id),
- result.delegatees[0].id_len};
+ CHECK_EQ(kUwMacaroonDelegateeTypeApp, result.delegatees[1].type);
+ CHECK_GT(result.delegatees[0].id_len, 1u);
+ std::vector<uint8_t> user_id{
+ result.delegatees[0].id,
+ result.delegatees[0].id + result.delegatees[0].id_len};
+ // Last byte is used for type. See |CreateAccessToken|.
+ AuthType type = static_cast<AuthType>(user_id.back());
+ user_id.pop_back();
+
+ std::vector<uint8_t> app_id{
+ result.delegatees[1].id,
+ result.delegatees[1].id + result.delegatees[1].id_len};
if (user_info)
- *user_info = UserInfo{auth_scope, user_id};
+ *user_info = UserInfo{auth_scope, UserAppId{type, user_id, app_id}};
return true;
}
@@ -463,6 +488,11 @@ bool AuthManager::CreateAccessTokenFromAuth(
[](const UwMacaroonDelegateeInfo& delegatee) {
return delegatee.type == kUwMacaroonDelegateeTypeUser;
});
+ auto last_app_id =
+ std::find_if(delegates_rbegin, delegates_rend,
+ [](const UwMacaroonDelegateeInfo& delegatee) {
+ return delegatee.type == kUwMacaroonDelegateeTypeApp;
+ });
if (last_user_id == delegates_rend || !last_user_id->id_len) {
return Error::AddTo(error, FROM_HERE, errors::kInvalidAuthCode,
@@ -480,9 +510,13 @@ bool AuthManager::CreateAccessTokenFromAuth(
if (!access_token)
return true;
- std::string user_id{reinterpret_cast<const char*>(last_user_id->id),
- last_user_id->id_len};
- UserInfo info{auth_scope, user_id};
+ std::vector<uint8_t> user_id{last_user_id->id,
+ last_user_id->id + last_user_id->id_len};
+ std::vector<uint8_t> app_id;
+ if (last_app_id != delegates_rend)
+ app_id.assign(last_app_id->id, last_app_id->id + last_app_id->id_len);
+
+ UserInfo info{auth_scope, {AuthType::kLocal, user_id, app_id}};
ttl = std::min(ttl, FromJ2000Time(result.expiration_time) - now);
*access_token = CreateAccessToken(info, ttl);
@@ -519,15 +553,21 @@ std::vector<uint8_t> AuthManager::DelegateToUser(
TimestampCaveat issued{now};
ExpirationCaveat expiration{now + ttl};
ScopeCaveat scope{ToMacaroonScope(user_info.scope())};
- UserIdCaveat user{user_info.user_id()};
+ UserIdCaveat user{user_info.id().user};
+ AppIdCaveat app{user_info.id().app};
SessionIdCaveat session{CreateSessionId()};
- return ExtendMacaroonToken(
- macaroon, now,
- {
- &issued.GetCaveat(), &expiration.GetCaveat(), &scope.GetCaveat(),
- &user.GetCaveat(), &session.GetCaveat(),
- });
+ std::vector<const UwMacaroonCaveat*> caveats{
+ &issued.GetCaveat(), &expiration.GetCaveat(), &scope.GetCaveat(),
+ &user.GetCaveat(),
+ };
+
+ if (!user_info.id().app.empty())
+ caveats.push_back(&app.GetCaveat());
+
+ caveats.push_back(&session.GetCaveat());
+
+ return ExtendMacaroonToken(macaroon, now, caveats);
}
} // namespace privet