Encrypt and Decrypt Cookies stored in react-native Cookies database - react-native

In my react-native app, I used the fetch library for network communication, also I used Cookie in my communications.
My server sends me some sensitive data and I configured my fetch request to store the cookies by credentials: 'include'
fetch(URL, {
// other Options
credentials: 'include',
}).then().catch();
I tested my app on a rooted android device and figure out that the cookies have been stored within a database named Cookies.
when I opened the database in the SQLiteDatabase browser I figure out my sensitive data are insecurely stored in that database.
I know that fetch Api is using Okhttp3 in android implementation, so I tried to change the default client to change the default behavior by overriding its CookieJar class and add some Encryption and Decryption procedure to it.
MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OkHttpClientProvider.setOkHttpClientFactory(new OkHttpClientFactory() {
#Override
public OkHttpClient createNewNetworkModuleClient() {
ReactCookieJarContainer reactCookieJarContainer = new ReactCookieJarContainer();
reactCookieJarContainer.setCookieJar(new SecureCookieJar());
return new OkHttpClient.Builder()
// other configures
.cookieJar(reactCookieJarContainer)
.build();
}
});
}
SecureCookieJar
public class SecureCookieJar implements CookieJar {
#Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
// securely encrypt and store the cookies
}
#Override
public List<Cookie> loadForRequest(HttpUrl url) {
// decrypt the stored cookies
}
}
but when I debugging my code it seems my class does not take into account by react-native and still using its internal class JavaNetCookieJar (I debugged the code and reach the class blow)
ReactCookieJarContainer
Is there any way to override the default behavior at all and if yes how can I achieve it. the ideal approach is finding a way to override the JavaNetCookieJar to encrypt and decrypt cookie before transferring them.
Is there a similar procedure needed for IOS too? I don't know how IOS manages the cookies in its native implementation.

Related

How to clear basic authentication credentials when loading url in webview android

webview.setWebViewClient(new MyWebBrowser(userName, password));
webview.loadUrl(BuildConfig.WEBVIEW_URL);
sending auth using :
#Override
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
handler.proceed(username, password);
}
but only first time it (onReceivedHttpAuthRequest) is calling tried to clear cache with all flags but still nothing happens. Can any one help me?

Identity Server 4 OIDC authorization_code flow multi tenancy

I'm facing an issue for authenticating my users on my IS4 server with an application (Blazor Server/WASM).
My IDSRV4 is located on the same app that the API to protect, and each client has it owns database (for users and business models).
To choose the good database, I use an header and have set up a interceptor on EF Core to choose database according to header value.
Everything works great, except authentication. I was using resource_owner_password flow with a JavaScript app (security breach, I know) which allows me to pass custom headers for each calls (calling /connect/token with my custom header).
Now, with the authorization_code flow, I cannot manage to pass the header to choose good tenant, meaning good database, which causes authentication to failed because token is validated on another database that the user is currently register to.
I can pass the tenant to choose database during login process (when posting login info on IDSRV4 side), and I've set up event on client side to add header on when sending back code for having back id_token, but I lost the capability to do that after my idp redirect user after login on /connect/authorize (it seems there no extension on IDSRV4 side for adding custom headers).
So my user post login data (with tenant infos), that I lost when redirecting to /connect/authorize, and I have no way to customize this. Is there any chance to do that ?
Merging all users in the same database is not an option.
You can still add any custom headers to any HttpResponse from your MVC app hosting Identityserver.
// public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseCustomHeaders();
//CustomHeadersMiddleware.cs
public static class CustomHeadersMiddlewareExtensions
{
public static IApplicationBuilder UseCustomHeaders(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<CustomHeadersMiddleware>();
}
}
public class CustomHeadersMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<CustomHeadersMiddleware> _logger;
public CustomHeadersMiddleware(RequestDelegate next,
ILogger<CustomHeadersMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task Invoke(HttpContext context)
{
var watch = new Stopwatch();
watch.Start();
//To add Headers AFTER everything you need to do this
context.Response.OnStarting(() =>
{
if (!context.Response.Headers.ContainsKey("X-Response-Time-Milliseconds"))
context.Response.Headers.Add("X-Response-Time-Milliseconds",
new[] {watch.ElapsedMilliseconds.ToString()});
return Task.FromResult(0);
});
await _next(context);
}
}

ASP.NET Core: How to skip running authentication on [AllowAnonymous]

How to identify if authentication is not needed for current request?
We have a custom authentication handler, simplified here:
internal class CustomAuthHandler : AuthenticationHandler<CustomAuthOptions>
{
static readonly string[] DontCheckAuth = new string[] { "/servers", "/user/profile/", "/highscore/list", "/highscore/metadata/" };
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
/*
if url contains any of DontCheckAuth
then return AuthenticateResult.NoResult()
else
do custom auth
*/
}
}
So everything works OK, but HandleAuthenticateAsync is run on every request, even on URLs I have marked as [AllowAnonymous]. Currently I just check the URL and compare it to hard-coded list of URLs that does not require authentication.
How can I automate this process so I don't have to manually update the list of URLs (which I forget to do for new APIs)?

How to implement customized authentication in Spring Boot Application

I am building a web app with Spring Boot. Post requests can be made by a phone app to upload data in form of xml to the cloud. The phones that are allowed to push data are required to be registered company phones. The way to authenticate the APIs calls is to look up the android ID of the phone in a corporate database. It will accept the data only if the Android ID exists. The idea is to embed the android ID in the header of requests. Since it is not a typical way for authentication, how do I implement it with Spring Security? Or we don't even need Spring Security. Just extract the Android ID from the header and look it up in database. Reject the request if it is not a valid ID. Any advice would help.
Nothing prevents you from using Authorization header in a creative way, i.e., by embedding the Android ID into it. Then, in order to add authentication to your endpoints, you can use an AOP interceptor:
Protected operation marker interface:
#Target({ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public #interface ProtectedOperation {
}
Interceptor:
#Aspect
#Component
public class SecurityAspect {
private CorporateService corpService; // this is your custom service to check Android IDs
#Autowired
public SecurityAspect(CorporateService corpService) {
this.corpService = corpService;
}
#Around("#annotation(operation)")
public Object protectedOperationPermissionCheck(final ProceedingJoinPoint pjp, final ProtectedOperation operation) throws Throwable {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
String header = requestAttributes.getRequest().getHeader("Authorization");
String androidId = // get the ID from header - try not to use existing authorization header formats like Bearer, Negotiate etc. to avoid collision with other authentication systems
if (corpService.isAuthorized(androidId)) {
return pjp.proceed();
}
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.flushBuffer();
return null;
}
}
Make sure to add the spring-boot-starter-aop dependency to your pom.xml, for #Aspect support
EDIT: to protect an endpoint, annotate the endpoint method in your controller with #ProtectedOperation, and add #EnableAspectJAutoProxy to your Spring Boot application

Alternative to cookie based session/authentication

Is there an alternative to the session feature plugin in servicestack? In some scenarios I cannot use cookies to match the authorized session in my service implementation. Is there a possibility to resolve the session using a token in http header of the request? What is the preferred solution for that in case the browser is blocking cookies?
I'm using ServiceStack without the built-in auth and session providers.
I use a attribute as request filter to collect the user information (id and token), either from a cookie, request header or string parameter.
You can provide this information after the user takes login. You append a new cookie to the response and inject the id and token info on clientside when rendering the view, so you can use for http headers and query parameters for links.
public class AuthenticationAttribute : Attribute, IHasRequestFilter
{
public void RequestFilter(IHttpRequest request, IHttpResponse response, object dto)
{
var userAuth = new UserAuth { };
if(!string.IsNullOrWhiteSpace(request.GetCookieValue("auth"))
{
userAuth = (UserAuth)request.GetCookieValue("auth");
}
else if (!string.IsNullOrEmpty(request.Headers.Get("auth-key")) &&
!string.IsNullOrEmpty(request.Headers.Get("auth-id")))
{
userAuth.Id = request.Headers.Get("id");
userAuth.Token = request.Headers.Get("token");
}
authenticationService.Authenticate(userAuth.Id, userAuth.token);
}
public IHasRequestFilter Copy()
{
return new AuthenticationAttribute();
}
public int Priority { get { return -3; } } // negative are executed before global requests
}
If the user isn't authorized, i redirect him at this point.
My project supports SPA. If the user consumes the API with xmlhttprequests, the authentication stuff is done with headers. I inject that information on AngularJS when the page is loaded, and reuse it on all request (partial views, api consuming, etc). ServiceStack is powerful for this type of stuff, you can easily configure your AngularJS app and ServiceStack view engine to work side by side, validating every requests, globalizing your app, etc.
In case you don't have cookies and the requests aren't called by javascript, you can support the authentication without cookies if you always generate the links passing the id and token as query parameters, and pass them through hidden input on forms, for example.
#Guilherme Cardoso: In my current solution I am using a PreRequestFilters and the built-in session feature.
My workflow/workaround is the following:
When the user gets authorized I took the cookie and send it to the client by using an http header. Now the client can call services if the cookie is set in a http-header (Authorization) of the request.
To achieve this I redirect the faked authorization header to the cookie of the request using a PreRequestFilter. Now I am able to use the session feature. Feels like a hack but works for the moment ;-)
public class CookieRestoreFromAuthorizationHeaderPlugin : IPlugin
{
public void Register(IAppHost appHost)
{
appHost.PreRequestFilters.Add((req, res) =>
{
var cookieValue = req.GetCookieValue("ss-id");
if(!string.IsNullOrEmpty(cookieValue))
return;
var authorizationHeader = req.Headers.Get("Authorization");
if (!string.IsNullOrEmpty(authorizationHeader) && authorizationHeader.ToLower().StartsWith("basictoken "))
{
var cookie = Encoding.UTF8.GetString(Convert.FromBase64String(authorizationHeader.Split(' ').Last()));
req.Cookies.Add("ss-id",new Cookie("ss-id",cookie));
req.Items.Add("ss-id",cookie);
}
});
}
}