Fixes for cache issues.

This commit is contained in:
stephb9959
2021-12-22 20:02:37 -08:00
parent ae5c32a8ec
commit d27441d793
5 changed files with 101 additions and 49 deletions

2
build
View File

@@ -1 +1 @@
120 121

View File

@@ -76,7 +76,7 @@ namespace OpenWifi {
} }
if(!CallToken.empty()) { if(!CallToken.empty()) {
auto Client = UserCache_.get(CallToken); auto Client = UserCacheTokenToSharedID_.get(CallToken);
if( Client.isNull() ) { if( Client.isNull() ) {
SecurityObjects::WebToken WT; SecurityObjects::WebToken WT;
uint64_t RevocationDate=0; uint64_t RevocationDate=0;
@@ -86,8 +86,9 @@ namespace OpenWifi {
return false; return false;
Expired = (WT.created_ + WT.expires_in_) < time(nullptr); Expired = (WT.created_ + WT.expires_in_) < time(nullptr);
if(StorageService()->GetUserById(UserId,UInfo.userinfo)) { if(StorageService()->GetUserById(UserId,UInfo.userinfo)) {
UserCacheTokenToSharedID_.update(CallToken, { WT, UserId});
UserCacheIDToUserInfo_.update(UserId, UInfo.userinfo);
UInfo.webtoken = WT; UInfo.webtoken = WT;
UserCache_.update(CallToken, UInfo);
SessionToken = CallToken; SessionToken = CallToken;
return true; return true;
} }
@@ -96,8 +97,16 @@ namespace OpenWifi {
} }
if(!Expired) { if(!Expired) {
SessionToken = CallToken; SessionToken = CallToken;
UInfo = *Client ; UInfo.webtoken = Client->WT ;
return true; auto UInfoCacheEntry = UserCacheIDToUserInfo_.get(Client->ID);
if(UInfoCacheEntry.isNull()) {
if(!StorageService()->GetUserById(Client->ID,UInfo.userinfo)) {
return false;
}
} else {
UInfo.userinfo = *UInfoCacheEntry;
}
return true;
} }
RevokeToken(CallToken); RevokeToken(CallToken);
return false; return false;
@@ -120,18 +129,19 @@ namespace OpenWifi {
} }
if(!CallToken.empty()) { if(!CallToken.empty()) {
auto Client = SubUserCache_.get(CallToken); auto Client = SubUserCacheTokenToSharedID_.get(CallToken);
if( Client.isNull() ) { if( Client.isNull() ) {
SecurityObjects::WebToken WT; SecurityObjects::WebToken WT;
uint64_t RevocationDate=0; uint64_t RevocationDate=0;
std::string UserId; std::string UserId;
if(StorageService()->GetSubToken(CallToken,WT, UserId, RevocationDate)) { if(StorageService()->GetSubToken(CallToken, WT, UserId, RevocationDate)) {
if(RevocationDate!=0) if(RevocationDate!=0)
return false; return false;
Expired = (WT.created_ + WT.expires_in_) < time(nullptr); Expired = (WT.created_ + WT.expires_in_) < time(nullptr);
if(StorageService()->GetSubUserById(UserId,UInfo.userinfo)) { if(StorageService()->GetSubUserById(UserId,UInfo.userinfo)) {
SubUserCacheTokenToSharedID_.update(CallToken, { WT, UserId});
SubUserCacheIDToUserInfo_.update(UserId, UInfo.userinfo);
UInfo.webtoken = WT; UInfo.webtoken = WT;
SubUserCache_.update(CallToken, UInfo);
SessionToken = CallToken; SessionToken = CallToken;
return true; return true;
} }
@@ -140,7 +150,15 @@ namespace OpenWifi {
} }
if(!Expired) { if(!Expired) {
SessionToken = CallToken; SessionToken = CallToken;
UInfo = *Client ; UInfo.webtoken = Client->WT ;
auto UInfoCacheEntry = SubUserCacheIDToUserInfo_.get(Client->ID);
if(UInfoCacheEntry.isNull()) {
if(!StorageService()->GetSubUserById(Client->ID,UInfo.userinfo)) {
return false;
}
} else {
UInfo.userinfo = *UInfoCacheEntry;
}
return true; return true;
} }
RevokeSubToken(CallToken); RevokeSubToken(CallToken);
@@ -153,45 +171,47 @@ namespace OpenWifi {
} }
void AuthService::RevokeToken(std::string & Token) { void AuthService::RevokeToken(std::string & Token) {
UserCache_.remove(Token); UserCacheTokenToSharedID_.remove(Token);
StorageService()->RevokeToken(Token); StorageService()->RevokeToken(Token);
} }
void AuthService::RevokeSubToken(std::string & Token) { void AuthService::RevokeSubToken(std::string & Token) {
SubUserCache_.remove(Token); SubUserCacheTokenToSharedID_.remove(Token);
StorageService()->RevokeSubToken(Token); StorageService()->RevokeSubToken(Token);
} }
bool AuthService::DeleteUserFromCache(const std::string &UserName) { bool AuthService::DeleteUserFromCache(const std::string &Id) {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
std::vector<std::string> OldTokens; std::vector<std::string> OldTokens;
UserCacheIDToUserInfo_.remove(Id);
UserCache_.forEach([&OldTokens,UserName](const std::string &token, const SecurityObjects::UserInfoAndPolicy& O) -> void UserCacheTokenToSharedID_.forEach([&OldTokens,Id](const std::string &token, const SharedTokenID & O) -> void
{ if(O.userinfo.email==UserName) { if(O.ID==Id)
OldTokens.push_back(token); OldTokens.push_back(token);
}); });
for(const auto &i:OldTokens) { for(const auto &i:OldTokens) {
Logout(i,false); Logout(i,false);
UserCache_.remove(i); UserCacheTokenToSharedID_.remove(i);
} }
return true; return true;
} }
bool AuthService::DeleteSubUserFromCache(const std::string &UserName) { bool AuthService::DeleteSubUserFromCache(const std::string &Id) {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
std::vector<std::string> OldTokens; std::vector<std::string> OldTokens;
SubUserCacheIDToUserInfo_.remove(Id);
SubUserCache_.forEach([&OldTokens,UserName](const std::string &token, const SecurityObjects::UserInfoAndPolicy& O) -> void SubUserCacheTokenToSharedID_.forEach([&OldTokens,Id](const std::string &token, const SharedTokenID & O) -> void
{ if(O.userinfo.email==UserName) { if(O.ID==Id)
OldTokens.push_back(token); OldTokens.push_back(token);
}); });
for(const auto &i:OldTokens) { for(const auto &i:OldTokens) {
SubLogout(i,false); Logout(i,false);
SubUserCache_.remove(i); SubUserCacheTokenToSharedID_.remove(i);
} }
return true; return true;
} }
@@ -289,7 +309,8 @@ namespace OpenWifi {
UInfo.webtoken.username_ = UserName; UInfo.webtoken.username_ = UserName;
UInfo.webtoken.errorCode = 0; UInfo.webtoken.errorCode = 0;
UInfo.webtoken.userMustChangePassword = false; UInfo.webtoken.userMustChangePassword = false;
UserCache_.update(UInfo.webtoken.access_token_,UInfo); UserCacheTokenToSharedID_.update(UInfo.webtoken.access_token_,{UInfo.webtoken,UInfo.userinfo.Id});
UserCacheIDToUserInfo_.update(UInfo.userinfo.Id, UInfo.userinfo);
StorageService()->SetLastLogin(UInfo.userinfo.Id); StorageService()->SetLastLogin(UInfo.userinfo.Id);
StorageService()->AddToken(UInfo.userinfo.Id, UInfo.webtoken.access_token_, StorageService()->AddToken(UInfo.userinfo.Id, UInfo.webtoken.access_token_,
UInfo.webtoken.refresh_token_, UInfo.webtoken.token_type_, UInfo.webtoken.refresh_token_, UInfo.webtoken.token_type_,
@@ -313,7 +334,8 @@ namespace OpenWifi {
UInfo.webtoken.username_ = UserName; UInfo.webtoken.username_ = UserName;
UInfo.webtoken.errorCode = 0; UInfo.webtoken.errorCode = 0;
UInfo.webtoken.userMustChangePassword = false; UInfo.webtoken.userMustChangePassword = false;
SubUserCache_.update(UInfo.webtoken.access_token_,UInfo); SubUserCacheTokenToSharedID_.update(UInfo.webtoken.access_token_,{UInfo.webtoken,UInfo.userinfo.Id});
SubUserCacheIDToUserInfo_.update(UInfo.userinfo.Id, UInfo.userinfo);
StorageService()->SetSubLastLogin(UInfo.userinfo.Id); StorageService()->SetSubLastLogin(UInfo.userinfo.Id);
StorageService()->AddSubToken(UInfo.userinfo.Id, UInfo.webtoken.access_token_, StorageService()->AddSubToken(UInfo.userinfo.Id, UInfo.webtoken.access_token_,
UInfo.webtoken.refresh_token_, UInfo.webtoken.token_type_, UInfo.webtoken.refresh_token_, UInfo.webtoken.token_type_,
@@ -625,61 +647,74 @@ namespace OpenWifi {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
Expired = false; Expired = false;
auto Client = UserCache_.get(Token); auto Client = UserCacheTokenToSharedID_.get(Token);
if(!Client.isNull()) { if(!Client.isNull()) {
Expired = (Client->webtoken.created_ + Client->webtoken.expires_in_) < std::time(nullptr); Expired = (Client->WT.created_ + Client->WT.expires_in_) < std::time(nullptr);
WebToken = Client->webtoken; WebToken = Client->WT;
UserInfo = Client->userinfo; auto CachedUserInfo = UserCacheIDToUserInfo_.get(Client->ID);
if(!CachedUserInfo.isNull()) {
UserInfo = *CachedUserInfo;
return true;
}
if(!StorageService()->GetUserById(Client->ID,UserInfo)) {
return false;
}
return true; return true;
} }
std::string TToken{Token}, UserId; std::string TToken{Token}, UserId;
SecurityObjects::UserInfoAndPolicy UInfo;
SecurityObjects::WebToken WT; SecurityObjects::WebToken WT;
uint64_t RevocationDate=0; uint64_t RevocationDate=0;
if(StorageService()->GetToken(TToken, WT, UserId, RevocationDate)) { if(StorageService()->GetToken(TToken, WT, UserId, RevocationDate)) {
if(RevocationDate!=0) if(RevocationDate!=0)
return false; return false;
Expired = (WT.created_ + WT.expires_in_) < std::time(nullptr); Expired = (WT.created_ + WT.expires_in_) < std::time(nullptr);
if(StorageService()->GetUserById(UserId,UInfo.userinfo)) { if(StorageService()->GetUserById(UserId,UserInfo)) {
WebToken = WT; WebToken = WT;
UserCache_.update(UInfo.webtoken.access_token_, UInfo); UserCacheTokenToSharedID_.update(Token, {WebToken, UserId});
UserCacheIDToUserInfo_.update(UserId, UserInfo);
return true; return true;
} }
return false; return false;
} }
return IsValidSubToken(Token, WebToken, UserInfo, Expired); return IsValidSubToken(Token, WebToken, UserInfo, Expired);
} }
bool AuthService::IsValidSubToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo, bool & Expired) { bool AuthService::IsValidSubToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo, bool & Expired) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
auto Now = std::time(nullptr);
Expired = false; Expired = false;
auto Client = SubUserCache_.get(Token);
auto Client = SubUserCacheTokenToSharedID_.get(Token);
if(!Client.isNull()) { if(!Client.isNull()) {
Expired = (Client->webtoken.created_ + Client->webtoken.expires_in_) < Now ; Expired = (Client->WT.created_ + Client->WT.expires_in_) < std::time(nullptr);
WebToken = Client->webtoken; WebToken = Client->WT;
UserInfo = Client->userinfo; auto CachedUserInfo = SubUserCacheIDToUserInfo_.get(Client->ID);
if(!CachedUserInfo.isNull()) {
UserInfo = *CachedUserInfo;
return true;
}
if(!StorageService()->GetSubUserById(Client->ID,UserInfo)) {
return false;
}
return true; return true;
} }
std::string TToken{Token}, UserId; std::string TToken{Token}, UserId;
SecurityObjects::UserInfoAndPolicy UInfo;
SecurityObjects::WebToken WT; SecurityObjects::WebToken WT;
uint64_t RevocationDate=0; uint64_t RevocationDate=0;
if(StorageService()->GetSubToken(TToken, WT, UserId, RevocationDate)) { if(StorageService()->GetSubToken(TToken, WT, UserId, RevocationDate)) {
if(RevocationDate!=0) if(RevocationDate!=0)
return false; return false;
Expired = (WT.created_ + WT.expires_in_) < std::time(nullptr); Expired = (WT.created_ + WT.expires_in_) < std::time(nullptr);
if(StorageService()->GetSubUserById(UserId,UInfo.userinfo)) { if(StorageService()->GetSubUserById(UserId,UserInfo)) {
WebToken = WT; WebToken = WT;
UserCache_.update(UInfo.webtoken.access_token_, UInfo); SubUserCacheTokenToSharedID_.update(Token, {WebToken, UserId});
SubUserCacheIDToUserInfo_.update(UserId, UserInfo);
return true; return true;
} }
return false; return false;
} }
return false; return false;
} }

View File

@@ -59,6 +59,14 @@ namespace OpenWifi{
[[nodiscard]] const std:: string & PasswordValidationExpression() const { return PasswordValidationStr_;}; [[nodiscard]] const std:: string & PasswordValidationExpression() const { return PasswordValidationStr_;};
void Logout(const std::string &token, bool EraseFromCache=true); void Logout(const std::string &token, bool EraseFromCache=true);
inline void UpdateUserCache(const SecurityObjects::UserInfo &UI) {
UserCacheIDToUserInfo_.update(UI.Id,UI);
}
inline void UpdateSubUserCache(const SecurityObjects::UserInfo &UI) {
SubUserCacheIDToUserInfo_.update(UI.Id,UI);
}
[[nodiscard]] bool IsSubAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired); [[nodiscard]] bool IsSubAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired);
[[nodiscard]] UNAUTHORIZED_REASON AuthorizeSub( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired ); [[nodiscard]] UNAUTHORIZED_REASON AuthorizeSub( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired );
void CreateSubToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo); void CreateSubToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo);
@@ -114,8 +122,16 @@ namespace OpenWifi{
Poco::JWT::Signer Signer_; Poco::JWT::Signer Signer_;
Poco::SHA2Engine SHA2_; Poco::SHA2Engine SHA2_;
Poco::ExpireLRUCache<std::string,SecurityObjects::UserInfoAndPolicy> UserCache_{256,1200000}; struct SharedTokenID {
Poco::ExpireLRUCache<std::string,SecurityObjects::UserInfoAndPolicy> SubUserCache_{4096,1200000}; SecurityObjects::WebToken WT; // Web token
std::string ID; // user.Id
};
Poco::ExpireLRUCache<std::string,SharedTokenID> UserCacheTokenToSharedID_{256,1200000};
Poco::ExpireLRUCache<std::string,SecurityObjects::UserInfo> UserCacheIDToUserInfo_{256,1200000};
Poco::ExpireLRUCache<std::string,SharedTokenID> SubUserCacheTokenToSharedID_{4096,1200000};
Poco::ExpireLRUCache<std::string,SecurityObjects::UserInfo> SubUserCacheIDToUserInfo_{256,1200000};
std::string AccessPolicy_; std::string AccessPolicy_;
std::string PasswordPolicy_; std::string PasswordPolicy_;

View File

@@ -4,10 +4,10 @@
#include "RESTAPI_subuser_handler.h" #include "RESTAPI_subuser_handler.h"
#include "StorageService.h" #include "StorageService.h"
#include "Poco/JSON/Parser.h"
#include "framework/RESTAPI_errors.h" #include "framework/RESTAPI_errors.h"
#include "SMSSender.h" #include "SMSSender.h"
#include "ACLProcessor.h" #include "ACLProcessor.h"
#include "AuthService.h"
namespace OpenWifi { namespace OpenWifi {
@@ -63,7 +63,7 @@ namespace OpenWifi {
return NotFound(); return NotFound();
} }
if(AuthService()->DeleteSubUserFromCache(TargetUser.email)) { if(AuthService()->DeleteSubUserFromCache(Id)) {
// nothing to do // nothing to do
} }
@@ -234,6 +234,7 @@ namespace OpenWifi {
if(StorageService()->UpdateSubUserInfo(UserInfo_.userinfo.email,Id,Existing)) { if(StorageService()->UpdateSubUserInfo(UserInfo_.userinfo.email,Id,Existing)) {
SecurityObjects::UserInfo NewUserInfo; SecurityObjects::UserInfo NewUserInfo;
StorageService()->GetSubUserByEmail(UserInfo_.userinfo.email,NewUserInfo); StorageService()->GetSubUserByEmail(UserInfo_.userinfo.email,NewUserInfo);
AuthService()->UpdateSubUserCache(NewUserInfo);
Poco::JSON::Object ModifiedObject; Poco::JSON::Object ModifiedObject;
FilterCredentials(NewUserInfo); FilterCredentials(NewUserInfo);
NewUserInfo.to_json(ModifiedObject); NewUserInfo.to_json(ModifiedObject);

View File

@@ -59,7 +59,7 @@ namespace OpenWifi {
return NotFound(); return NotFound();
} }
if(AuthService()->DeleteUserFromCache(UInfo.email)) { if(AuthService()->DeleteUserFromCache(Id)) {
// nothing to do // nothing to do
} }