diff --git a/build b/build index d1cbcfa..3d9aebb 100644 --- a/build +++ b/build @@ -1 +1 @@ -66 \ No newline at end of file +68 \ No newline at end of file diff --git a/openpapi/ucentralsec/owsec.yaml b/openpapi/ucentralsec/owsec.yaml index 609572f..d86e47a 100644 --- a/openpapi/ucentralsec/owsec.yaml +++ b/openpapi/ucentralsec/owsec.yaml @@ -61,6 +61,7 @@ components: - 6 # INTERNAL_ERROR, - 7 # ACCESS_DENIED, - 8 # INVALID_TOKEN + - 9 # expired token ErrorDetails: type: string ErrorDescription: diff --git a/src/AuthService.cpp b/src/AuthService.cpp index 97c3337..231c04c 100644 --- a/src/AuthService.cpp +++ b/src/AuthService.cpp @@ -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; } diff --git a/src/AuthService.h b/src/AuthService.h index 228e254..3f9c49f 100644 --- a/src/AuthService.h +++ b/src/AuthService.h @@ -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 diff --git a/src/RESTAPI/RESTAPI_oauth2Handler.cpp b/src/RESTAPI/RESTAPI_oauth2Handler.cpp index 95ea31e..29b118f 100644 --- a/src/RESTAPI/RESTAPI_oauth2Handler.cpp +++ b/src/RESTAPI/RESTAPI_oauth2Handler.cpp @@ -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)) { diff --git a/src/RESTAPI/RESTAPI_validateToken_handler.cpp b/src/RESTAPI/RESTAPI_validateToken_handler.cpp index 8f38cf6..a937ea1 100644 --- a/src/RESTAPI/RESTAPI_validateToken_handler.cpp +++ b/src/RESTAPI/RESTAPI_validateToken_handler.cpp @@ -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); diff --git a/src/framework/MicroService.h b/src/framework/MicroService.h index d23a452..c78c9e9 100644 --- a/src/framework/MicroService.h +++ b/src/framework/MicroService.h @@ -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_)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; } diff --git a/src/framework/RESTAPI_errors.h b/src/framework/RESTAPI_errors.h index b1bee35..362a1a4 100644 --- a/src/framework/RESTAPI_errors.h +++ b/src/framework/RESTAPI_errors.h @@ -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