// // Created by stephane bourque on 2021-11-30. // #include "RESTAPI_suboauth2_handler.h" #include "AuthService.h" #include "MFAServer.h" #include "RESTAPI/RESTAPI_db_helpers.h" #include "StorageService.h" namespace OpenWifi { void RESTAPI_suboauth2_handler::DoGet() { bool Expired = false, Contacted = false; if (!IsAuthorized(Expired, Contacted, true)) { if (Expired) return UnAuthorized(RESTAPI::Errors::EXPIRED_TOKEN); return UnAuthorized(RESTAPI::Errors::INVALID_TOKEN); } bool GetMe = GetBoolParameter(RESTAPI::Protocol::ME, false); if (GetMe) { Logger_.information(fmt::format("REQUEST-ME({}): Request for {}", Request->clientAddress().toString(), UserInfo_.userinfo.email)); Poco::JSON::Object Me; SecurityObjects::UserInfo ReturnedUser = UserInfo_.userinfo; Sanitize(UserInfo_, ReturnedUser); ReturnedUser.to_json(Me); return ReturnObject(Me); } BadRequest(RESTAPI::Errors::UnrecognizedRequest); } void RESTAPI_suboauth2_handler::DoDelete() { auto Token = GetBinding(RESTAPI::Protocol::TOKEN, ""); std::string SessionToken; try { Poco::Net::OAuth20Credentials Auth(*Request); if (Auth.getScheme() == "Bearer") { SessionToken = Auth.getBearerToken(); } } catch (const Poco::Exception &E) { return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); } if (Token.empty() || (Token != SessionToken)) { return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); } AuthService()->SubLogout(Token); return ReturnStatus(Poco::Net::HTTPResponse::HTTP_NO_CONTENT, true); } void RESTAPI_suboauth2_handler::DoPost() { const auto &Obj = ParsedBody_; auto userId = GetS(RESTAPI::Protocol::USERID, Obj); auto password = GetS(RESTAPI::Protocol::PASSWORD, Obj); auto newPassword = GetS(RESTAPI::Protocol::NEWPASSWORD, Obj); auto refreshToken = GetS("refreshToken", Obj); auto grant_type = GetParameter("grant_type"); Poco::toLowerInPlace(userId); if (!refreshToken.empty() && grant_type == "refresh_token") { SecurityObjects::UserInfoAndPolicy UInfo; if (AuthService()->RefreshSubToken(*Request, refreshToken, UInfo)) { Poco::JSON::Object Answer; UInfo.webtoken.to_json(Answer); return ReturnObject(Answer); } else { return UnAuthorized(RESTAPI::Errors::CANNOT_REFRESH_TOKEN); } } if (GetBoolParameter(RESTAPI::Protocol::REQUIREMENTS)) { Logger_.information( fmt::format("POLICY-REQUEST({}): Request.", Request->clientAddress().toString())); Poco::JSON::Object Answer; Answer.set(RESTAPI::Protocol::PASSWORDPATTERN, AuthService()->SubPasswordValidationExpression()); Answer.set(RESTAPI::Protocol::ACCESSPOLICY, AuthService()->GetSubAccessPolicy()); Answer.set(RESTAPI::Protocol::PASSWORDPOLICY, AuthService()->GetSubPasswordPolicy()); return ReturnObject(Answer); } if (GetBoolParameter(RESTAPI::Protocol::FORGOTPASSWORD)) { SecurityObjects::UserInfo UInfo1; auto UserExists = StorageService()->SubDB().GetUserByEmail(userId, UInfo1); if (UserExists) { Logger_.information(fmt::format("FORGOTTEN-PASSWORD({}): Request for {}", Request->clientAddress().toString(), userId)); SecurityObjects::ActionLink NewLink; NewLink.action = OpenWifi::SecurityObjects::LinkActions::SUB_FORGOT_PASSWORD; NewLink.id = MicroServiceCreateUUID(); NewLink.userId = UInfo1.id; NewLink.created = OpenWifi::Now(); NewLink.expires = NewLink.created + (24 * 60 * 60); NewLink.userAction = false; StorageService()->ActionLinksDB().CreateAction(NewLink); Poco::JSON::Object ReturnObj; SecurityObjects::UserInfoAndPolicy UInfo; UInfo.webtoken.userMustChangePassword = true; UInfo.webtoken.to_json(ReturnObj); return ReturnObject(ReturnObj); } else { Poco::JSON::Object ReturnObj; SecurityObjects::UserInfoAndPolicy UInfo; UInfo.webtoken.userMustChangePassword = true; UInfo.webtoken.to_json(ReturnObj); return ReturnObject(ReturnObj); } } if (GetBoolParameter(RESTAPI::Protocol::RESENDMFACODE)) { Logger_.information(fmt::format("RESEND-MFA-CODE({}): Request for {}", Request->clientAddress().toString(), userId)); if (Obj->has("uuid")) { auto uuid = Obj->get("uuid").toString(); if (MFAServer()->ResendCode(uuid)) return OK(); } return UnAuthorized(RESTAPI::Errors::BAD_MFA_TRANSACTION); } if (GetBoolParameter(RESTAPI::Protocol::COMPLETEMFACHALLENGE)) { Logger_.information(fmt::format("COMPLETE-MFA-CHALLENGE({}): Request for {}", Request->clientAddress().toString(), userId)); if (Obj->has("uuid") && Obj->has("answer")) { SecurityObjects::UserInfoAndPolicy UInfo; if (MFAServer()->CompleteMFAChallenge(Obj, UInfo)) { Poco::JSON::Object ReturnObj; UInfo.webtoken.to_json(ReturnObj); return ReturnObject(ReturnObj); } } return UnAuthorized(RESTAPI::Errors::MFA_FAILURE); } SecurityObjects::UserInfoAndPolicy UInfo; bool Expired = false; auto Code = AuthService()->AuthorizeSub(userId, password, newPassword, UInfo, Expired); switch (Code) { case SUCCESS: { Poco::JSON::Object ReturnObj; if (AuthService()->RequiresMFA(UInfo)) { if (MFAServer()->StartMFAChallenge(UInfo, ReturnObj)) { return ReturnObject(ReturnObj); } Logger_.warning( "MFA Seems to be broken. Please fix. Disabling MFA checking for now."); } UInfo.webtoken.to_json(ReturnObj); return ReturnObject(ReturnObj); } case INVALID_CREDENTIALS: return UnAuthorized(RESTAPI::Errors::INVALID_CREDENTIALS); case PASSWORD_INVALID: return UnAuthorized(RESTAPI::Errors::PASSWORD_INVALID); case PASSWORD_ALREADY_USED: return UnAuthorized(RESTAPI::Errors::PASSWORD_ALREADY_USED); case USERNAME_PENDING_VERIFICATION: return UnAuthorized(RESTAPI::Errors::USERNAME_PENDING_VERIFICATION); case PASSWORD_CHANGE_REQUIRED: return UnAuthorized(RESTAPI::Errors::PASSWORD_CHANGE_REQUIRED); case ACCOUNT_SUSPENDED: return UnAuthorized(RESTAPI::Errors::ACCOUNT_SUSPENDED); default: return UnAuthorized(RESTAPI::Errors::INVALID_CREDENTIALS); } } } // namespace OpenWifi