Adding token expiry detection and reporting.

This commit is contained in:
stephb9959
2021-11-13 15:24:24 -08:00
parent 6471eabc82
commit a5802bf631
8 changed files with 65 additions and 40 deletions

2
build
View File

@@ -1 +1 @@
66
68

View File

@@ -61,6 +61,7 @@ components:
- 6 # INTERNAL_ERROR,
- 7 # ACCESS_DENIED,
- 8 # INVALID_TOKEN
- 9 # expired token
ErrorDetails:
type: string
ErrorDescription:

View File

@@ -56,7 +56,7 @@ namespace OpenWifi {
Logger_.notice("Stopping...");
}
bool AuthService::IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo )
bool AuthService::IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired )
{
std::lock_guard Guard(Mutex_);
try {
@@ -80,7 +80,9 @@ namespace OpenWifi {
return false;
}
if((Client->second.webtoken.created_ + Client->second.webtoken.expires_in_) > time(nullptr)) {
Expired = (Client->second.webtoken.created_ + Client->second.webtoken.expires_in_) > time(nullptr);
if(!Expired) {
SessionToken = CallToken;
UInfo = Client->second ;
return true;
@@ -253,7 +255,7 @@ namespace OpenWifi {
return false;
}
UNAUTHORIZED_REASON AuthService::Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo )
UNAUTHORIZED_REASON AuthService::Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo , bool & Expired )
{
std::lock_guard Guard(Mutex_);
@@ -345,16 +347,17 @@ namespace OpenWifi {
return true;
}
bool AuthService::IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo) {
bool AuthService::IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo, bool & Expired) {
std::lock_guard G(Mutex_);
auto It = UserCache_.find(Token);
auto Client = UserCache_.find(Token);
std::cout << "Checking token: " << Token << std::endl;
if(It==UserCache_.end())
if(Client==UserCache_.end())
return false;
WebToken = It->second.webtoken;
UserInfo = It->second.userinfo;
Expired = (Client->second.webtoken.created_ + Client->second.webtoken.expires_in_) > time(nullptr);
WebToken = Client->second.webtoken;
UserInfo = Client->second.userinfo;
return true;
}

View File

@@ -51,8 +51,8 @@ namespace OpenWifi{
int Start() override;
void Stop() override;
[[nodiscard]] bool IsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo );
[[nodiscard]] UNAUTHORIZED_REASON Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo );
[[nodiscard]] bool IsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired);
[[nodiscard]] UNAUTHORIZED_REASON Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired );
void CreateToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo);
[[nodiscard]] bool SetPassword(const std::string &Password, SecurityObjects::UserInfo & UInfo);
[[nodiscard]] const std:: string & PasswordValidationExpression() const { return PasswordValidationStr_;};
@@ -60,8 +60,7 @@ namespace OpenWifi{
bool ValidatePassword(const std::string &pwd);
[[nodiscard]] bool IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo);
[[nodiscard]] bool IsValidAPIKEY(const Poco::Net::HTTPServerRequest &Request);
[[nodiscard]] bool IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo, bool & Expired);
[[nodiscard]] std::string GenerateTokenJWT(const std::string & UserName, ACCESS_TYPE Type);
[[nodiscard]] std::string GenerateTokenHMAC(const std::string & UserName, ACCESS_TYPE Type);
@@ -119,8 +118,8 @@ namespace OpenWifi{
inline AuthService * AuthService() { return AuthService::instance(); }
[[nodiscard]] inline bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ) {
return AuthService()->IsAuthorized(Request, SessionToken, UInfo );
[[nodiscard]] inline bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo , bool & Expired) {
return AuthService()->IsAuthorized(Request, SessionToken, UInfo, Expired );
}
} // end of namespace

View File

@@ -18,7 +18,10 @@
namespace OpenWifi {
void RESTAPI_oauth2Handler::DoGet() {
if (!IsAuthorized()) {
bool Expired = false;
if (!IsAuthorized(Expired)) {
if(Expired)
return UnAuthorized(RESTAPI::Errors::ExpiredToken,EXPIRED_TOKEN);
return UnAuthorized(RESTAPI::Errors::MissingAuthenticationInformation);
}
bool GetMe = GetBoolParameter(RESTAPI::Protocol::ME, false);
@@ -32,9 +35,12 @@ namespace OpenWifi {
}
void RESTAPI_oauth2Handler::DoDelete() {
if (!IsAuthorized()) {
return UnAuthorized("Not authorized.");
}
bool Expired = false;
if (!IsAuthorized(Expired)) {
if(Expired)
return UnAuthorized(RESTAPI::Errors::ExpiredToken,EXPIRED_TOKEN);
return UnAuthorized(RESTAPI::Errors::MissingAuthenticationInformation);
}
auto Token = GetBinding(RESTAPI::Protocol::TOKEN, "...");
if (Token == SessionToken_) {
@@ -115,7 +121,8 @@ namespace OpenWifi {
}
SecurityObjects::UserInfoAndPolicy UInfo;
auto Code=AuthService()->Authorize(userId, password, newPassword, UInfo);
bool Expired=false;
auto Code=AuthService()->Authorize(userId, password, newPassword, UInfo, Expired);
if (Code==SUCCESS) {
Poco::JSON::Object ReturnObj;
if(AuthService()->RequiresMFA(UInfo)) {

View File

@@ -13,7 +13,8 @@ namespace OpenWifi {
if (i.first == "token") {
// can we find this token?
SecurityObjects::UserInfoAndPolicy SecObj;
if (AuthService()->IsValidToken(i.second, SecObj.webtoken, SecObj.userinfo)) {
bool Expired = false;
if (AuthService()->IsValidToken(i.second, SecObj.webtoken, SecObj.userinfo, Expired)) {
Poco::JSON::Object Obj;
SecObj.to_json(Obj);
return ReturnObject(Obj);

View File

@@ -80,7 +80,8 @@ namespace OpenWifi {
PASSWORD_INVALID,
INTERNAL_ERROR,
ACCESS_DENIED,
INVALID_TOKEN
INVALID_TOKEN,
EXPIRED_TOKEN
};
class AppServiceRegistry {
@@ -1529,14 +1530,16 @@ namespace OpenWifi {
if (!ContinueProcessing())
return;
if (AlwaysAuthorize_ && !IsAuthorized()) {
return;
bool Expired=false;
if (AlwaysAuthorize_ && !IsAuthorized(Expired)) {
if(Expired)
return UnAuthorized(RESTAPI::Errors::ExpiredToken, EXPIRED_TOKEN);
return UnAuthorized(RESTAPI::Errors::InvalidCredentials, ACCESS_DENIED);
}
std::string Reason;
if(!RoleIsAuthorized(RequestIn.getURI(), Request->getMethod(), Reason)) {
UnAuthorized(Reason, ACCESS_DENIED);
return;
return UnAuthorized(Reason, ACCESS_DENIED);
}
ParseParameters();
@@ -1874,7 +1877,7 @@ namespace OpenWifi {
return true;
}
inline bool IsAuthorized();
inline bool IsAuthorized(bool & Expired);
inline void ReturnObject(Poco::JSON::Object &Object) {
PrepareResponse();
@@ -2220,7 +2223,7 @@ namespace OpenWifi {
return ((T.expires_in_+T.created_)<std::time(nullptr));
}
inline bool RetrieveTokenInformation(const std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo) {
inline bool RetrieveTokenInformation(const std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired) {
try {
Types::StringPairVec QueryData;
QueryData.push_back(std::make_pair("token",SessionToken));
@@ -2232,6 +2235,11 @@ namespace OpenWifi {
if(Req.Do(Response)==Poco::Net::HTTPResponse::HTTP_OK) {
if(Response->has("tokenInfo") && Response->has("userInfo")) {
UInfo.from_json(Response);
if(IsTokenExpired(UInfo.webtoken)) {
Expired = true;
return false;
}
Expired = false;
Cache_.update(SessionToken, UInfo);
return true;
}
@@ -2239,16 +2247,22 @@ namespace OpenWifi {
} catch (...) {
}
Expired = false;
return false;
}
inline bool IsAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo) {
inline bool IsAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired) {
auto User = Cache_.get(SessionToken);
if(!User.isNull() && !IsTokenExpired(User->webtoken)) {
UInfo = *User;
return true;
if(!User.isNull()) {
if(IsTokenExpired(User->webtoken)) {
Expired = true;
return false;
}
Expired = false;
UInfo = *User;
return true;
}
return RetrieveTokenInformation(SessionToken, UInfo);
return RetrieveTokenInformation(SessionToken, UInfo, Expired);
}
private:
@@ -3608,9 +3622,9 @@ namespace OpenWifi {
}
#ifdef TIP_SECURITY_SERVICE
[[nodiscard]] bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo );
[[nodiscard]] bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired );
#endif
inline bool RESTAPIHandler::IsAuthorized() {
inline bool RESTAPIHandler::IsAuthorized( bool & Expired ) {
if(Internal_) {
auto Allowed = MicroService::instance().IsValidAPIKEY(*Request);
if(!Allowed) {
@@ -3640,9 +3654,9 @@ namespace OpenWifi {
}
}
#ifdef TIP_SECURITY_SERVICE
if (AuthServiceIsAuthorized(*Request, SessionToken_, UserInfo_)) {
if (AuthServiceIsAuthorized(*Request, SessionToken_, UserInfo_, Expired)) {
#else
if (AuthClient()->IsAuthorized( SessionToken_, UserInfo_)) {
if (AuthClient()->IsAuthorized( SessionToken_, UserInfo_, Expired)) {
#endif
if(Server_.LogIt(Request->getMethod(),true)) {
Logger_.debug(Poco::format("X-REQ-ALLOWED(%s): User='%s@%s' Method='%s' Path='%s",
@@ -3659,7 +3673,6 @@ namespace OpenWifi {
Utils::FormatIPv6(Request->clientAddress().toString()),
Request->getMethod(), Request->getURI()));
}
UnAuthorized("Invalid token", INVALID_TOKEN);
}
return false;
}

View File

@@ -59,6 +59,7 @@ namespace OpenWifi::RESTAPI::Errors {
static const std::string UnrecognizedRequest{"Ill-formed request. Please consult documentation."};
static const std::string MissingAuthenticationInformation{"Missing authentication information."};
static const std::string InsufficientAccessRights{"Insufficient access rights to complete the operation."};
static const std::string ExpiredToken{"Token has expired, user must login."};
}
#endif //OWPROV_RESTAPI_ERRORS_H