Completing sub mfa support.

This commit is contained in:
stephb9959
2021-12-01 22:12:28 -08:00
parent ec82bdec24
commit 2217a428c1
8 changed files with 245 additions and 16 deletions

View File

@@ -98,7 +98,7 @@ add_executable( owsec
src/SMS_provider_twilio.cpp src/SMS_provider_twilio.h
src/ActionLinkManager.cpp src/ActionLinkManager.h
src/ACLProcessor.h src/RESTAPI/RESTAPI_preferences.cpp src/RESTAPI/RESTAPI_preferences.h
src/framework/OpenWifiTypes.h)
src/framework/OpenWifiTypes.h src/RESTAPI/RESTAPI_submfa_handler.cpp src/RESTAPI/RESTAPI_submfa_handler.h)
if(NOT SMALL_BUILD)
target_link_libraries(owsec PUBLIC

2
build
View File

@@ -1 +1 @@
68
69

View File

@@ -405,6 +405,24 @@ components:
answer:
type: string
SubMfaConfig:
type: object
properties:
id:
type: string
format: uuid
type:
type: string
enum:
- disabled
- sms
- email
email:
type: string
format: email
sms:
type: string
#########################################################################################
##
## These are endpoints that all services in the uCentral stack must provide
@@ -735,7 +753,7 @@ paths:
tags:
- Authentication
summary: Get access token - to be used as Bearer token header for all other API requests.
operationId: getAccessToken
operationId: getSubAccessToken
parameters:
- in: query
name: newPassword
@@ -818,7 +836,7 @@ paths:
tags:
- Authentication
summary: Revoke a token.
operationId: removeAccessToken
operationId: removeSubAccessToken
parameters:
- in: path
name: token
@@ -905,9 +923,9 @@ paths:
/subusers:
get:
tags:
- User Management
- Subscribers
summary: Retrieve a list of existing users as well as some information about them.
operationId: getUsers
operationId: getSubUsers
parameters:
- in: query
name: offset
@@ -1055,8 +1073,8 @@ paths:
/subuser/{id}:
get:
tags:
- User Management
operationId: getUser
- Subscribers
operationId: getSubUser
summary: Retrieve the information for a single user.
parameters:
- in: path
@@ -1075,8 +1093,8 @@ paths:
delete:
tags:
- User Management
operationId: deleteUser
- Subscribers
operationId: deleteSubUser
summary: Delete a single user.
parameters:
- in: path
@@ -1095,8 +1113,8 @@ paths:
post:
tags:
- User Management
operationId: createUser
- Subscribers
operationId: createSubUser
summary: Create a single user.
parameters:
- in: path
@@ -1127,8 +1145,8 @@ paths:
put:
tags:
- User Management
operationId: updateUser
- Subscribers
operationId: updateSubUser
summary: Modify a single user.
parameters:
- in: path
@@ -1354,6 +1372,49 @@ paths:
400:
$ref: '#/components/responses/BadRequest'
/submfa:
get:
tags:
- MFA
summary: Retrieve the cyrrent setting for MFA
operationId: getMFS
responses:
200:
$ref: '#/components/schemas/SubMfaConfig'
put:
tags:
- MFA
summary: Retrieve the cyrrent setting for MFA
operationId: modifyMFS
parameters:
- in: query
name: startValidation
schema:
type: boolean
required: false
- in: query
name: completeValidation
schema:
type: boolean
required: false
- in: query
name: challengeCode
schema:
type: string
required: false
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/SubMfaConfig'
responses:
200:
$ref: '#/components/schemas/SubMfaConfig'
400:
$ref: '#/components/responses/BadRequest'
#########################################################################################
##
## These are endpoints that all services in the uCentral stack must provide
@@ -1433,8 +1494,9 @@ paths:
get:
tags:
- Security
- Subscribers
summary: Allows any microservice to validate a token and get security policy for a specific user.
operationId: validateToken
operationId: validateSubToken
parameters:
- in: query
name: token

View File

@@ -19,6 +19,7 @@
#include "RESTAPI/RESTAPI_subuser_handler.h"
#include "RESTAPI/RESTAPI_subusers_handler.h"
#include "RESTAPI/RESTAPI_validate_sub_token_handler.h"
#include "RESTAPI/RESTAPI_submfa_handler.h"
namespace OpenWifi {
@@ -55,7 +56,8 @@ namespace OpenWifi {
RESTAPI_suboauth2_handler,
RESTAPI_subuser_handler,
RESTAPI_suboauth2_handler,
RESTAPI_subusers_handler
RESTAPI_subusers_handler,
RESTAPI_submfa_handler
>(Path, Bindings, L, S);
}
}

View File

@@ -0,0 +1,106 @@
//
// Created by stephane bourque on 2021-12-01.
//
#include "RESTAPI_submfa_handler.h"
#include "StorageService.h"
#include "SMSSender.h"
namespace OpenWifi {
void RESTAPI_submfa_handler::DoGet() {
SecurityObjects::UserInfo User;
if (StorageService()->GetUserById(UserInfo_.userinfo.Id,User)) {
Poco::JSON::Object Answer;
SecurityObjects::SubMfaConfig MFC;
MFC.id = User.Id;
if(User.userTypeProprietaryInfo.mfa.enabled) {
if(User.userTypeProprietaryInfo.mfa.method == "sms") {
MFC.sms = User.userTypeProprietaryInfo.mobiles[0].number;
} else if(User.userTypeProprietaryInfo.mfa.method == "email") {
MFC.email = User.email;
}
} else {
MFC.type = "disabled";
}
MFC.to_json(Answer);
return ReturnObject(Answer);
}
NotFound();
}
void RESTAPI_submfa_handler::DoPut() {
auto Body = ParseStream();
SecurityObjects::SubMfaConfig MFC;
if(!MFC.from_json(Body)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(MFC.type=="disabled") {
SecurityObjects::UserInfo User;
StorageService()->GetUserById(UserInfo_.userinfo.Id,User);
User.userTypeProprietaryInfo.mfa.enabled = false;
StorageService()->UpdateUserInfo(UserInfo_.userinfo.email,UserInfo_.userinfo.Id,User);
Poco::JSON::Object Answer;
MFC.to_json(Answer);
return ReturnObject(Answer);
} else if (MFC.type=="email") {
SecurityObjects::UserInfo User;
StorageService()->GetUserById(UserInfo_.userinfo.Id,User);
User.userTypeProprietaryInfo.mfa.enabled = true;
User.userTypeProprietaryInfo.mfa.method = "email";
StorageService()->UpdateUserInfo(UserInfo_.userinfo.email,UserInfo_.userinfo.Id,User);
Poco::JSON::Object Answer;
MFC.to_json(Answer);
return ReturnObject(Answer);
} else if (MFC.type=="sms") {
if(GetBoolParameter("startValidation",false)) {
if(MFC.sms.empty()) {
return BadRequest("Missing phone number");
}
if(SMSSender()->StartValidation(MFC.sms, UserInfo_.userinfo.email)) {
return OK();
} else {
return InternalError("SMS could not be sent. Verify the number or try again later.");
}
} else if(GetBoolParameter("completeValidation",false)) {
auto ChallengeCode = GetParameter("challengeCode","");
if(ChallengeCode.empty()) {
return BadRequest("Missing 'challengeCode'");
}
if(MFC.sms.empty()) {
return BadRequest("Missing phone number");
}
if(SMSSender()->CompleteValidation(MFC.sms, ChallengeCode, UserInfo_.userinfo.email)) {
SecurityObjects::UserInfo User;
StorageService()->GetUserById(UserInfo_.userinfo.Id,User);
User.userTypeProprietaryInfo.mfa.method = "sms";
SecurityObjects::MobilePhoneNumber PhoneNumber;
PhoneNumber.number = MFC.sms;
PhoneNumber.primary = true;
PhoneNumber.verified = true;
User.userTypeProprietaryInfo.mfa.enabled = true;
User.userTypeProprietaryInfo.mobiles.clear();
User.userTypeProprietaryInfo.mobiles.push_back(PhoneNumber);
StorageService()->UpdateUserInfo(UserInfo_.userinfo.email,UserInfo_.userinfo.Id,User);
Poco::JSON::Object Answer;
MFC.to_json(Answer);
return ReturnObject(Answer);
} else {
return InternalError("SMS could not be sent. Verify the number or try again later.");
}
}
}
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
}

View File

@@ -0,0 +1,27 @@
//
// Created by stephane bourque on 2021-12-01.
//
#pragma once
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_submfa_handler : public RESTAPIHandler {
public:
RESTAPI_submfa_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal, false, false , RateLimit{.Interval=1000,.MaxCalls=10},
true) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/submfa"}; };
void DoGet() final;
void DoPost() final {};
void DoDelete() final {};
void DoPut() final ;
};
}

View File

@@ -531,5 +531,26 @@ namespace OpenWifi::SecurityObjects {
}
return false;
}
void SubMfaConfig::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id",id);
field_to_json(Obj,"type",type);
field_to_json(Obj,"sms",sms);
field_to_json(Obj,"email",email);
}
bool SubMfaConfig::from_json(Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"id",id);
field_from_json(Obj,"type",type);
field_from_json(Obj,"sms",sms);
field_from_json(Obj,"email",email);
return true;
} catch(...) {
}
return false;
}
}

View File

@@ -253,4 +253,15 @@ namespace OpenWifi::SecurityObjects {
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(Poco::JSON::Object::Ptr &Obj);
};
struct SubMfaConfig {
std::string id;
std::string type;
std::string sms;
std::string email;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(Poco::JSON::Object::Ptr &Obj);
};
}