Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions App/Server/OpenAPIGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,16 +509,14 @@ QJsonObject OpenAPIGenerator::retrieveJson(
});
}

// if (APIObject->requiresJWT()) {
if (APIObject->tokenActorType() != enuTokenActorType::ANONYMOUSE) {
if (APIObject->mustProvideJWT()) {
ResponseModel["401"] = QJsonObject({{ "description", "Authorization information is missing or invalid" }});
ResponseModel["403"] = QJsonObject({{ "description", "Access forbidden" }});
}

PathInfo["responses"] = ResponseModel;

// if (APIObject->requiresJWT()) {
if (APIObject->tokenActorType() != enuTokenActorType::ANONYMOUSE) {
if (APIObject->mustProvideJWT()) {
PathInfo["security"] = QJsonArray({
QJsonObject({
{ "Bearer", QJsonArray() },
Expand Down
19 changes: 11 additions & 8 deletions App/Server/RESTAPIRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,7 @@ QMap<QString, QString> RESTAPIRegistry::extractMethods(
clsAPIObject* APIObject = _registry.value(Key);
QStringList Parameters;

// if (APIObject->requiresJWT())
if (APIObject->tokenActorType() != enuTokenActorType::ANONYMOUSE)
if (APIObject->mustProvideJWT())
Parameters.append(QString(_showTypes ? "TAPI::JWT_t " : "") + "JWT");

for (quint8 i=0; i<APIObject->/*BaseMethod.parameterCount()*/ParamTypesName.count(); ++i) {
Expand Down Expand Up @@ -704,12 +703,16 @@ void RESTAPIRegistry::dumpAPIs()
bool IsLastMethod = (Method == Methods.last());

QString JWTType = "";
// if (API.APIObject->requiresJWT())
if (API.APIObject->tokenActorType() != enuTokenActorType::ANONYMOUSE)
JWTType = QString(" (JWT:%1%2)")
.arg(enuTokenActorType::toStr(API.APIObject->tokenActorType()))
.arg(API.APIObject->tokenIsOptional() ? "/OPTIONAL" : "")
;
if (API.APIObject->canProvideJWT()) {
QStringList JWTTypesList;
if (API.APIObject->tokenAllowANONYMOUSE())
JWTTypesList.append("ANONYMOUSE");
if (API.APIObject->tokenAllowUSER())
JWTTypesList.append("USER");
if (API.APIObject->tokenAllowAPI())
JWTTypesList.append("API");
JWTType = QString(" (JWT:%1)").arg(JWTTypesList.join(','));
}

TargomanDebug(5).noLabel().noquote().nospace()
<< (IsLastAPI ? " " : "│") << " "
Expand Down
48 changes: 34 additions & 14 deletions App/Server/clsAPIObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,11 @@ clsAPIObject::clsAPIObject(
HasExtraMethodName(_hasExtraMethodName),
Parent(_module),
// RequiresJWT(false)
TokenActorType(enuTokenActorType::ANONYMOUSE),
TokenIsOptional(true)
// TokenActorType(enuTokenActorType::ANONYMOUSE),
// TokenIsOptional(true)
TokenAllowANONYMOUSE(false),
TokenAllowUSER(false),
TokenAllowAPI(false)
{
QList<QByteArray> parameterTypes = _method.parameterTypes();
quint8 i = 0;
Expand All @@ -74,19 +77,36 @@ clsAPIObject::clsAPIObject(
--this->RequiredParamsCount;
this->BaseMethod.DefaultValues.removeAt(0);

if (ParameterTypeName.startsWith(APICALLBOOM_TYPE_JWT_USER_DECL_STR)) {
this->TokenActorType = enuTokenActorType::USER;
this->TokenIsOptional = false;
} else if (ParameterTypeName.startsWith(APICALLBOOM_TYPE_JWT_USER_OR_ANONYMOUSE_DECL_STR)) {
this->TokenActorType = enuTokenActorType::USER;
this->TokenIsOptional = true;
if (ParameterTypeName.startsWith(APICALLBOOM_TYPE_JWT_ANONYMOUSE_DECL_STR)) {
this->TokenAllowANONYMOUSE = true;
this->TokenAllowUSER = false;
this->TokenAllowAPI = false;
} else if (ParameterTypeName.startsWith(APICALLBOOM_TYPE_JWT_ANONYMOUSE_OR_USER_DECL_STR)) {
this->TokenAllowANONYMOUSE = true;
this->TokenAllowUSER = true;
this->TokenAllowAPI = false;
} else if (ParameterTypeName.startsWith(APICALLBOOM_TYPE_JWT_ANONYMOUSE_OR_API_DECL_STR)) {
this->TokenAllowANONYMOUSE = true;
this->TokenAllowUSER = false;
this->TokenAllowAPI = true;
} else if (ParameterTypeName.startsWith(APICALLBOOM_TYPE_JWT_USER_DECL_STR)) {
this->TokenAllowANONYMOUSE = false;
this->TokenAllowUSER = true;
this->TokenAllowAPI = false;
} else if (ParameterTypeName.startsWith(APICALLBOOM_TYPE_JWT_API_DECL_STR)) {
this->TokenActorType = enuTokenActorType::API;
this->TokenIsOptional = false;
} else if (ParameterTypeName.startsWith(APICALLBOOM_TYPE_JWT_API_OR_ANONYMOUSE_DECL_STR)) {
this->TokenActorType = enuTokenActorType::API;
this->TokenIsOptional = true;
}
this->TokenAllowANONYMOUSE = false;
this->TokenAllowUSER = false;
this->TokenAllowAPI = true;
} else if (ParameterTypeName.startsWith(APICALLBOOM_TYPE_JWT_USER_OR_API_DECL_STR)) {
this->TokenAllowANONYMOUSE = false;
this->TokenAllowUSER = true;
this->TokenAllowAPI = true;
} else if (ParameterTypeName.startsWith(APICALLBOOM_TYPE_JWT_ANONYMOUSE_OR_USER_OR_API_DECL_STR)) {
this->TokenAllowANONYMOUSE = true;
this->TokenAllowUSER = true;
this->TokenAllowAPI = true;
} else
throw exHTTPInternalServerError(QString("Unknown jwt type: %1").arg(ParameterTypeName));

} else {
QByteArray ParamNameNoUnderScore = (ParamName.startsWith('_') ? ParamName.mid(1) : ParamName);
Expand Down
35 changes: 24 additions & 11 deletions App/Server/clsAPIObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,26 @@ class clsAPIObject : public intfAPIObject, public QObject
return this->Parent;
}

// inline bool requiresJWT() const {
// return this->RequiresJWT; //ParamTypesName.contains(PARAM_JWT);
// }
// enuTokenActorType::Type tokenActorType() { return this->TokenActorType; }
// bool tokenIsOptional() { return this->TokenIsOptional; }

// inline enuTokenActorType::Type moduleActorType() const {
// return this->Parent->actorType();
// }
enuTokenActorType::Type tokenActorType() { return this->TokenActorType; }
bool tokenIsOptional() { return this->TokenIsOptional; }
bool tokenAllowANONYMOUSE() { return this->TokenAllowANONYMOUSE; }
bool tokenAllowUSER() { return this->TokenAllowUSER; }
bool tokenAllowAPI() { return this->TokenAllowAPI; }

inline bool mustProvideJWT() {
return ((this->tokenAllowANONYMOUSE() == false)
&& (this->tokenAllowUSER() || this->tokenAllowAPI())
);
}
inline bool canProvideJWT() {
return (/*this->tokenAllowANONYMOUSE()
&&*/ (this->tokenAllowUSER() || this->tokenAllowAPI())
);
}
inline bool noJWTNeeded() {
return ((this->tokenAllowUSER() == false) && (this->tokenAllowAPI() == false));
}

// inline bool requiresCookies() const {
// return this->ParamTypesName.contains(PARAM_COOKIES);
Expand Down Expand Up @@ -164,9 +175,11 @@ class clsAPIObject : public intfAPIObject, public QObject
quint8 RequiredParamsCount;
bool HasExtraMethodName;
intfPureModule* Parent;
// bool RequiresJWT;
enuTokenActorType::Type TokenActorType;
bool TokenIsOptional;
// enuTokenActorType::Type TokenActorType;
// bool TokenIsOptional;
bool TokenAllowANONYMOUSE;
bool TokenAllowUSER;
bool TokenAllowAPI;

friend class RESTAPIRegistry;
friend class OpenAPIGenerator;
Expand Down
80 changes: 54 additions & 26 deletions App/Server/clsRequestHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,25 +335,51 @@ clsRequestHandler::stuResult clsRequestHandler::run(
const QString& _pksByPath,
const QString& _api
) {
auto fnTiming = [=](const QString &_name, const QString &_desc, quint64 _nanoSecs) {
auto FnTiming = [=](const QString &_name, const QString &_desc, quint64 _nanoSecs) {
this->addToTimings(_name, _desc, _nanoSecs);
};

enuTokenActorType::Type TokenActorType = _apiObject->tokenActorType();
QScopedPointer<intfAPICallBoom> APICALLBOOM;

if (TokenActorType == enuTokenActorType::USER) {
if (_apiObject->tokenIsOptional())
APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_USER_OR_ANONYMOUSE_DECL(fnTiming));
else
APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_USER_DECL(fnTiming));
} else if (TokenActorType == enuTokenActorType::API) {
if (_apiObject->tokenIsOptional())
APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_API_OR_ANONYMOUSE_DECL(fnTiming));
else
APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_API_DECL(fnTiming));
} else //enuTokenActorType::ANONYMOUSE
APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_ANONYMOUSE_DECL(fnTiming));
if (_apiObject->tokenAllowANONYMOUSE()) {
if (_apiObject->tokenAllowUSER()) {
if (_apiObject->tokenAllowAPI())
APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_ANONYMOUSE_OR_USER_OR_API_DECL(FnTiming));
else
APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_ANONYMOUSE_OR_USER_DECL(FnTiming));
} else {
if (_apiObject->tokenAllowAPI())
APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_ANONYMOUSE_OR_API_DECL(FnTiming));
else
APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_ANONYMOUSE_DECL(FnTiming));
}
} else {
if (_apiObject->tokenAllowUSER()) {
if (_apiObject->tokenAllowAPI())
APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_USER_OR_API_DECL(FnTiming));
else
APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_USER_DECL(FnTiming));
} else {
if (_apiObject->tokenAllowAPI())
APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_API_DECL(FnTiming));
else
throw exHTTPInternalServerError("jwt f,f,f");
}
}

// enuTokenActorType::Type TokenActorType = _apiObject->tokenActorType();
// if (TokenActorType == enuTokenActorType::USER) {
// if (_apiObject->tokenIsOptional())
// APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_ANONYMOUSE_OR_USER_DECL(fnTiming));
// else
// APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_USER_DECL(fnTiming));
// } else if (TokenActorType == enuTokenActorType::API) {
// if (_apiObject->tokenIsOptional())
// APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_ANONYMOUSE_OR_API_DECL(fnTiming));
// else
// APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_API_DECL(fnTiming));
// } else //enuTokenActorType::ANONYMOUSE
// APICALLBOOM.reset(new APICALLBOOM_TYPE_JWT_ANONYMOUSE_DECL(fnTiming));

try {
for (auto QueryIter = _queries.begin(); QueryIter != _queries.end(); ++QueryIter)
Expand All @@ -379,26 +405,28 @@ clsRequestHandler::stuResult clsRequestHandler::run(
}

if (BearerToken.isEmpty()) {
if ((TokenActorType != enuTokenActorType::ANONYMOUSE)
&& (_apiObject->tokenIsOptional() == false))
throw exHTTPForbidden("No authentication header is present");

} else if (TokenActorType == enuTokenActorType::ANONYMOUSE) {
if (_apiObject->mustProvideJWT())
throw exHTTPForbidden("No authentication header is present");
} else if (_apiObject->noJWTNeeded()) {
// throw exHTTPForbidden("The authentication header should not be sent for anonymouse apis");
APICALLBOOM->addResponseHeader("x-tapi-jwt-warning", "no jwt needed");
APICALLBOOM->addResponseHeaderNameToExpose("x-tapi-jwt-warning");

} else {
try {
TAPI::enuTokenActorType::Type JWTTokenActorType;

QJWT::verifyJWT(
BearerToken,
RemoteIP,
TokenActorType,
_apiObject->tokenAllowUSER(),
_apiObject->tokenAllowAPI(),
JWTTokenActorType,
JWT
);

//check svcs just for API tokens
if ((TokenActorType == enuTokenActorType::API)
if ((JWTTokenActorType == enuTokenActorType::API)
&& JWT.contains("prv") && JWT["prv"].toObject().contains("svc")) {
QString ModuleBaseName = _apiObject->parentModule()->moduleBaseName().split(":").first();
if (ModuleBaseName.isEmpty() == false) {
Expand All @@ -409,12 +437,12 @@ clsRequestHandler::stuResult clsRequestHandler::run(
}

} catch (exJWTExpired &exp) {
enuTokenActorType::Type TokenType = enuTokenActorType::USER;
enuTokenActorType::Type JWTTokenActorType = enuTokenActorType::USER;

if (JWT.contains("typ"))
TokenType = enuTokenActorType::toEnum(JWT["typ"].toString());
JWTTokenActorType = enuTokenActorType::toEnum(JWT["typ"].toString());

if (TokenType == enuTokenActorType::USER) {
if (JWTTokenActorType == enuTokenActorType::USER) {
auto RenewJWTServerTiming = APICALLBOOM->createScopeTiming("jwt", "renew");

bool IsRenewed = false;
Expand All @@ -433,10 +461,10 @@ clsRequestHandler::stuResult clsRequestHandler::run(
APICALLBOOM->addResponseHeader("x-auth-warning", "replace token");
APICALLBOOM->addResponseHeaderNameToExpose("x-auth-warning");
}
} else if (TokenType == enuTokenActorType::API)
} else if (JWTTokenActorType == enuTokenActorType::API)
throw exHTTPForbidden("API token is expired");
else
throw exHTTPForbidden(QString("Unknown token type `%1`").arg(TokenType));
throw exHTTPForbidden(QString("Unknown token type `%1`").arg(JWTTokenActorType));
} //catch (exJWTExpired &exp)

JWT["encodedJWT"] = BearerToken;
Expand Down
Loading