Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d66fa18
Incorporate CSRF token handling into the GAM security provider.
claudiamurialdo Aug 7, 2023
d315f98
Fix build error.
claudiamurialdo Aug 7, 2023
f5b8a36
Remove unnecessary assignment.
claudiamurialdo Aug 7, 2023
8b5c0fd
Rename Config key to ValidateCSRF
claudiamurialdo Aug 7, 2023
6cf9ce8
Add ValidateCsrfToken routine and reuse code.
claudiamurialdo Aug 7, 2023
a908a95
validateCSRFToken was not initialized when objIntegratedSecurityLevel…
claudiamurialdo Aug 9, 2023
5f0b721
validateCSRFToken was not initialized when objIntegratedSecurityLevel…
claudiamurialdo Aug 10, 2023
80768f7
Add Cookie-to-header AntiForgery token validation.
claudiamurialdo Aug 17, 2023
19cebd0
The ValidateCsrf configuration was always true, regardless of the val…
claudiamurialdo Aug 17, 2023
7ee3b59
Validate forgery token also in PUT and DELETE verbs.
claudiamurialdo Aug 17, 2023
ad26c79
Add Unit Test for CSRF Validation
claudiamurialdo Aug 17, 2023
d011249
Remove unsused package references.
claudiamurialdo Aug 17, 2023
d45953f
Remove unused package.
claudiamurialdo Aug 17, 2023
e0a0e0a
Remove unused packages
claudiamurialdo Aug 17, 2023
ad6e960
Move VerificationToken to MapRoute.
claudiamurialdo Aug 17, 2023
962d16d
Fix test.
claudiamurialdo Aug 17, 2023
fea75cf
SuppressXFrameOptionsHeader is false.
claudiamurialdo Aug 17, 2023
b1e3fa0
Disable some tests until solve concurrency issue.
claudiamurialdo Aug 17, 2023
5d03d72
Enable Antiforgery validation for rest services in .NET Framework
claudiamurialdo Aug 18, 2023
c70f1fe
Remove unneeded using.
claudiamurialdo Aug 18, 2023
e002e7e
Set ReasonPhrase to code InvalidCSRFToken on failed validation.
claudiamurialdo Aug 18, 2023
ecec3fe
Fix System.MethodAccessException: Attempt by security transparent met…
claudiamurialdo Aug 21, 2023
427e4f5
Revert changes for CSRFTOken validation in GAM layer.
claudiamurialdo Aug 22, 2023
1e5e57d
Minor format changes.
claudiamurialdo Aug 22, 2023
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: 3 additions & 3 deletions dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ public class Preferences
public static string DefaultRewriteFile = "rewrite.config";
const string USE_NAMED_PARAMETERS = "UseNamedParameters";
const string REST_DATES_WITH_MILLIS = "REST_DATES_WITH_MILLIS";
const string YES = "1";
internal const string YES = "1";
const string NO = "0";
static string defaultDatastore;
const string DEFAULT_DS = "Default";
Expand Down Expand Up @@ -867,9 +867,9 @@ public static bool RewriteEnabled
if (rewriteEnabled == -1)
{
#if NETCORE
var basePath = FileUtil.GetBasePath();
string basePath = FileUtil.GetBasePath();
#else
var basePath = Directory.GetParent(FileUtil.GetStartupDirectory()).FullName;
string basePath = Directory.GetParent(FileUtil.GetStartupDirectory()).FullName;
#endif
string rewriteFile = Path.Combine(basePath, DefaultRewriteFile);
rewriteEnabled = File.Exists(rewriteFile)?1:0;
Expand Down
8 changes: 6 additions & 2 deletions dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
using log4net;
using System.IO;
using Jayrock.Json;


using GeneXus.Configuration;

namespace GeneXus.Utils
{
Expand Down Expand Up @@ -140,5 +139,10 @@ public static Dictionary<string, object> ReadRestBodyParameters(Stream stream)
}
return bodyParameters;
}

internal static bool ValidateCsrfToken()
{
return Config.GetValueOf("ValidateCSRF", Preferences.YES) == Preferences.YES;
}
}
}
6 changes: 6 additions & 0 deletions dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class HttpHeader
public static string XGXFILENAME = "x-gx-filename";
internal static string ACCEPT = "Accept";
internal static string TRANSFER_ENCODING = "Transfer-Encoding";
internal static string X_GXCSRF_TOKEN = "X-GXCSRF-TOKEN";
}
internal class HttpHeaderValue
{
Expand Down Expand Up @@ -91,6 +92,7 @@ public class HttpHelper
const string GAM_CODE_OTP_USER_ACCESS_CODE_SENT = "400";
const string GAM_CODE_TFA_USER_MUST_VALIDATE = "410";
const string GAM_CODE_TOKEN_EXPIRED = "103";
const string GAM_CODE_CSRF_INVALID_TOKEN = "550";
static Regex CapitalsToTitle = new Regex(@"(?<=[A-Z])(?=[A-Z][a-z]) | (?<=[^A-Z])(?=[A-Z]) | (?<=[A-Za-z])(?=[^A-Za-z])", RegexOptions.IgnorePatternWhitespace);

const string CORS_MAX_AGE_SECONDS = "86400";
Expand Down Expand Up @@ -252,6 +254,10 @@ private static HttpStatusCode GamCodeToHttpStatus(string code, HttpStatusCode de
{
return HttpStatusCode.Forbidden;
}
else if (code == GAM_CODE_CSRF_INVALID_TOKEN)
{
return HttpStatusCode.BadRequest;
}
return defaultCode;
}
private static void SetJsonError(HttpContext httpContext, string statusCode, string statusDescription)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ public class OutData : Dictionary<string, object>
public interface ISecurityProvider
{
GxResult checkaccesstoken(IGxContext context, String token, out bool isOK);
GxResult checkaccesstoken(IGxContext context, bool useCSRF_Token, out string CSRF_Token, out bool isOK);
GxResult checkaccesstokenprm(IGxContext context, String token, String permissionPrefix, out bool sessionOk, out bool permissionOk);
GxResult checkaccesstokenprm(IGxContext context, bool useCSRF_Token, string permissionName, out string CSRF_Token, out bool sessionOk, out bool permission);
void checksession(IGxContext context, string CleanAbsoluteUri, out bool isOK);
void checksessionprm(IGxContext context, string pathAndQuery, String permissionPrefix, out bool isOK, out bool isPermissionOK);
GxResult refreshtoken(IGxContext context, String clientId, String clientSecret, String refreshToken, out OutData outData, out bool flag);
Expand Down Expand Up @@ -88,14 +90,25 @@ public GxResult checkaccesstoken(IGxContext context, string token, out bool isOK
isOK = false;
return new GxResult();
}

public GxResult checkaccesstoken(IGxContext context, bool useCSRF_Token, out string CSRF_Token, out bool isOK)
{
isOK = false;
CSRF_Token = string.Empty;
return new GxResult();
}
public GxResult checkaccesstokenprm(IGxContext context, string token, string permissionPrefix, out bool sessionOk, out bool permissionOk)
{
permissionOk = false;
sessionOk = true;
return new GxResult();
}

public GxResult checkaccesstokenprm(IGxContext context, bool useCSRF_Token, string permissionName, out string CSRF_Token, out bool sessionOk, out bool permission)
{
sessionOk = false;
permission = false;
CSRF_Token = string.Empty;
return new GxResult();
}
public void checksession(IGxContext context, string CleanAbsoluteUri, out bool isOK)
{
isOK = false;
Expand Down
17 changes: 14 additions & 3 deletions dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -450,23 +450,34 @@ private bool IsAuthenticated(GAMSecurityLevel objIntegratedSecurityLevel, bool o
else
{

token = token.Replace("OAuth ", "");
string CSRFToken;
bool validateCSRFToken = false;
if (objIntegratedSecurityLevel == GAMSecurityLevel.SecurityLow)
{
bool isOK;
GxResult result = GxSecurityProvider.Provider.checkaccesstoken(context, token, out isOK);
validateCSRFToken = RestAPIHelpers.ValidateCsrfToken();
GxResult result = GxSecurityProvider.Provider.checkaccesstoken(context, validateCSRFToken, out CSRFToken, out isOK);
if (!isOK)
{
HttpHelper.SetGamError(httpContext, result.Code, result.Description);
return false;
}
else
{
if (!string.IsNullOrEmpty(CSRFToken))
AddHeader(HttpHeader.X_GXCSRF_TOKEN, CSRFToken);
}

}
else if (objIntegratedSecurityLevel == GAMSecurityLevel.SecurityHigh)
{
bool sessionOk, permissionOk;
GxResult result = GxSecurityProvider.Provider.checkaccesstokenprm(context, token, objPermissionPrefix, out sessionOk, out permissionOk);
GxResult result = GxSecurityProvider.Provider.checkaccesstokenprm(context, validateCSRFToken, objPermissionPrefix, out CSRFToken, out sessionOk, out permissionOk);
if (permissionOk)
{
if (!string.IsNullOrEmpty(CSRFToken))
AddHeader(HttpHeader.X_GXCSRF_TOKEN, CSRFToken);

return true;
}
else
Expand Down
16 changes: 12 additions & 4 deletions dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -567,24 +567,32 @@ protected bool IsAuthenticated(GAMSecurityLevel objIntegratedSecurityLevel, bool
}
else
{

token = token.Replace("OAuth ", "");
string CSRFToken;
bool validateCSRFToken = false;
if (objIntegratedSecurityLevel == GAMSecurityLevel.SecurityLow)
{
bool isOK;
GxResult result = GxSecurityProvider.Provider.checkaccesstoken(_gxContext, token, out isOK);
validateCSRFToken = RestAPIHelpers.ValidateCsrfToken();
GxResult result = GxSecurityProvider.Provider.checkaccesstoken(_gxContext, validateCSRFToken, out CSRFToken, out isOK);
if (!isOK)
{
HttpHelper.SetGamError(_httpContext, result.Code, result.Description);
return false;
}
else
{
if (!string.IsNullOrEmpty(CSRFToken))
AddHeader(HttpHeader.X_GXCSRF_TOKEN, CSRFToken);
}
}
else if (objIntegratedSecurityLevel == GAMSecurityLevel.SecurityHigh)
{
bool sessionOk, permissionOk;
GxResult result = GxSecurityProvider.Provider.checkaccesstokenprm(_gxContext, token, objPermissionPrefix, out sessionOk, out permissionOk);
GxResult result = GxSecurityProvider.Provider.checkaccesstokenprm(_gxContext, validateCSRFToken, objPermissionPrefix, out CSRFToken, out sessionOk, out permissionOk);
if (permissionOk)
{
if (!string.IsNullOrEmpty(CSRFToken))
AddHeader(HttpHeader.X_GXCSRF_TOKEN, CSRFToken);
return true;
}
else
Expand Down