How do I configure JxBrowser to automatically persist cookie and use them automatically to login site? - jxbrowser

I am using JxBrowser v7.10 in mac and have some cookie issues on persisting them and use them automatically to autologin site on application restart. It seems that cookies fail to persist somehow.
I searched and read the documentation in
https://jxbrowser-support.teamdev.com/docs/guides/cookies.html#working-with-cookies
https://jxbrowser-support.teamdev.com/javadoc/7.2/com/teamdev/jxbrowser/cookie/CookieStore.html
and yet could not find how to use the cookie.
The doc mentions
"JxBrowser delegates the work with cookies to the Chromium engine. Chromium decides how to download cookies from a web server, extract them from the HTTP headers and store them in a local file system (persistent cookies) or in the memory (session cookies)."
So from that understanding, the cookie should be auto-persist and able to use them on application restart , but instead I need to relogin everytime the application restart.
The following is the test code . I should be able to login gmail and jxbrowser auto persist the cookie (no coding require) and autologin gmail on restart , however the following code fail to do that .
Is that something I need to do to implement that ?
import com.teamdev.jxbrowser.browser.Browser;
import com.teamdev.jxbrowser.engine.Engine;
import com.teamdev.jxbrowser.engine.EngineOptions;
import com.teamdev.jxbrowser.view.swing.BrowserView;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import static com.teamdev.jxbrowser.engine.RenderingMode.HARDWARE_ACCELERATED;
public final class CookieBrowser {
public static void main(String[] args) {
// Creating and running Chromium engine
final Engine engine = Engine.newInstance(
EngineOptions.newBuilder(HARDWARE_ACCELERATED).build());
Browser browser = engine.newBrowser();
// Loading the required web page
browser.navigation().loadUrl("www.gmail.com");
// No cookie printed out, why ?
engine.cookieStore().cookies().forEach(System.out::println);
SwingUtilities.invokeLater(() -> {
// Creating Swing component for rendering web content
// loaded in the given Browser instance
BrowserView view = BrowserView.newInstance(browser);
// Creating and displaying Swing app frame
JFrame frame = new JFrame("JxBrowser AWT/Swing");
// Closing the engine when app frame is about to close
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.out.println("Cookie persist"); // but unable to use them automatically on restart
engine.cookieStore().persist();
engine.close();
}
});
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.add(view, BorderLayout.CENTER);
frame.setSize(800, 600);
frame.setVisible(true);
});
}
}`enter code here`

You get this behavior because you don't configure the Engine instance with the user data directory. So, every time you create a new Engine instance, a temp directory will be created and the cookie store will be initialized there. As a result, all the previously created cookies will not be available anymore.
Please check out the guide at https://jxbrowser-support.teamdev.com/docs/guides/engine.html#user-data-directory
From that guide:
User Data Directory
Represents an absolute path to the directory where the data such as cache, cookies, history, GPU cache, local storage, visited links, web data, spell checking dictionary files, etc. is stored. For example:
Engine engine = Engine.newInstance(EngineOptions.newBuilder(...)
.userDataDir(Paths.get("/Users/Me/.jxbrowser"))
.build());
If you do not provide the user data directory path, JxBrowser will create and use a temp directory in the user’s temp folder.
FYI: Just in case I will mention this info in the Cookies guide as well.

Related

Android WebView does not use manually installed certificates

I have a WebView in a Xamarin Forms application. It shows generated HTML which has references to resources on the intranet. These resources are TLS protected and a self signed certificate backs the secure communication.
The root-certificate is installed on the android device. Accessing it with google chrome works. However accessing it from WebView fails with an SSL error (3, untrusted).
For testing purposes, I changed the WebViewClient and overwrote OnReceiveSslError. There I check for my self signed certificate, allowing it manually (handler.Proceed). This works.
However this gives me new issues such as that the Navigating-event on the Xamarin.Forms.WebView does no more fire. Probably, I could also circumvent this problem, but everything seems a bit wrong.
To me it looks like as if the Android WebView does not use the same certificate store as that Google Chrome does. Is this correct and is there a fix to this behavior, hopefully without the necessity to create a custom renderer for the WebView control and introducing a whole bunch of potential new issues (such as the missing Navigating-event)?
Update according to Jessie Zhang's request
Broken Navigating Event
Attach in XAML a Navigating event. Assign a custom renderer for the WebView and in OnElementChanged assign a custom WebviewClient via SetWebViewClient. This step breaks the Navigating event, regardless whether the OnReceiveSslError is overriden or not (see code below).
Certificate Error
Use a WebView and assign it a custom built HTML via HtmlWebViewSource and embed some images which reference a https:// resource on a server with a self signed root-certificate (OpenSSL). Add the root certificate to the Android certificate store (via the User certificates applet). Although chrome and other clients accept now the https-resources, WebView does not. It seems as it does not consider the manually installed root certificate.
As an additional information: When overriding the OnReceiveSslEvent in WebViewClient, the certificate is available in the SslError parameter, however not accepted.
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e) {
base.OnElementChanged(e);
if (e.NewElement != null) {
Control.SetWebViewClient(
new BreakingWebViewClient()
);
}
}
class BreakingWebViewClient : WebViewClient{
// ... some code, but for breaking the Navigating-event, no code is necessary
}

in Xamarin/App how do I Secure Files on ASP.NET Restful Server in folders from other users and general public

I have an APP using restful server. I want to store PDF's, images, etc. in folders on my server. How can I make the folders private on server, yet allow App to access only certain folders depending on their app access.
I have different users in app and security/tokens established, etc. But if they upload an image for their avatar (and now PDF's), they get stored in folders on the server, and I just display with image source=https://blahblah.com/org1/images/user232.jpg.
How can I make that not accessible to outside (like just going to browser), yet make accessible to app if they have correct login privilege's for that organization/user? And then further extend that logic to more sensative PDF's, and other docs uploaded through app. I didn't want to store in SQL since then harder to use simple image display tools and I already have upload and media managers using folders structures.
I can see how to secure if logging onto server through browser (credentials), but can't see how you connect App with that security level and maintain it for the session.
For future readers. Most of the work was done on the restful (ASP.NET) side. I first tried using authorization/Authentication in web.config and having Allow and deny. This allowed a redirect of a user to a login page; however, it didn't do it if they entered an image exactly correct on website.
Found HTTPHandlers (adding in webconfig ) where I could write code that would be executed once the user entered the specific Image address xyz/abc/image.png. I found this a bit feeling like a hack.
So lastly modified my
routes.MapRoute(
name: "staticFileRoute",
url: "publicstor/{*file}",
defaults: new { controller = "Home", action = "HandleStatic" }
And add a function like this to home controller.
[System.Web.Http.HttpGet]
public ActionResult HandleStatic(string file)
{
if (Session["OrgId"] == null) //todo need to add full security check.
{
return View("Login");
}
else //Either coming from app or coming from web interface
{
string mimeType = MimeInfo.GetMimeType(Path.GetExtension(file));
return File(file, mimeType);
}
}
The final bit is on the Xamarin side to now pass security when getting an image. Since just a simple Xamarin.Forms.Image doesn't have a way to pass login info or tokens/authentication I used
https://forums.xamarin.com/discussion/145575/image-from-url-needing-auth
And established an appwide webclient that logged in generally once forcing my restful to go through security validation, then just accessed the images/documents through out my app from that webclient. So far so good. Hopefully there are no holes.
This gives the gist to a future reader.

Creating a new MobileServiceClient() freezes VS and Android app

Working on a Xamarin Forms app (Android & iOS)
When trying to create my connection to an easy table I have in an Azure Mobile App my Visual Studio Freezes for around 7 seconds and then when it comes back it has exited the code and the Android app, running in debug is permanently frozen.
When stepping through the code it steps over
client = new MobileServiceClient(appUrl);
and then when it hits the next line it freezes. But it doesn't matter what the next line is. I have put many different things after and it still freezes. Also, this is in a try/catch block, yet no exception is thrown.
I also wanted to see if the problem was server side. But both Post and Get with PostMan works fine. So I think my server is fine. Not completely sure though...
Here is some of the code:
public class ChatStorageAzureService : IChatStorageAzureService
{
public MobileServiceClient client { get; set; }
private IMobileServiceSyncTable<MessageViewModel> chatTable;
public static bool UseAuth { get; set; } = false;
private static ChatStorageAzureService instance;
public static ChatStorageAzureService Instance => instance ?? (instance = new ChatStorageAzureService());
public async Task InitializeAsync()
{
if (client?.SyncContext?.IsInitialized ?? false)
return;
var appUrl = "http://"MY-WEBSITE".azurewebsites.net/";
try
{
client = new MobileServiceClient(appUrl);
var path = "syncstore.db";
var store = new MobileServiceSQLiteStore(path);
store.DefineTable<MessageViewModel>();
await client.SyncContext.InitializeAsync(store);
chatTable = client.GetSyncTable<MessageViewModel>();
}
catch (Exception e)
{
Debug.WriteLine("Exception thrown in Initialize: " + e);
throw;
}
}
The InitializeAsync has been called in Async methods. It has been called with .Wait() method in a constructor. It has been called with button presses or in page creations. I have tried a ton of different ways to call. But it always freezes.
One thing that I think is weird is that my server code, is one project containing both the SignalR hub code and the Easy Table, yet you access them through different web addresses, For example
"http://"SignalR".azurewebsites.net/"
and
"http://"EasyTable".azurewebsites.net/"
Again PostMan is able to access both the tables and the SignalR and the SignalR works on the Android project. But I dont know if having to domains is bad. I am new... if you could not tell already, lol!
I followed this Tutorial for the Easy Table integration and when I did it in a separate project it worked fine. I am trying to integrate it into my actual project and that is where I am having all these problems.
I also turned on debugging with Azure and it doesnt seem like my app ever even reaches the service. No call is ever met. I think. But again I am new to debugging with Azure, so I might not know how to do it right. I followed this Tutorial for setting up Azure debugging
Thanks for any and all help!
Your path is incorrect. It needs to be a directory path, for example on iOS it is /<AppHome>/Library/<YourAppName>/syncstore.db.
We can leverage MobileServiceClient.DefaultDatabasePath to get the default database path in a cross-platform manner.
var path = Path.Combine(MobileServiceClient.DefaultDatabasePath, "syncstore.db");
Feel free to reference this Xamarin.Forms Sample App that uses Azure Mobile Service Client:
https://github.com/brminnick/UITestSampleApp/blob/master/Src/UITestSampleApp/Services/AzureService.cs
So I finally got it to work!!! "How?" you ask. I went on 2 week vacation, came back, started a again. Copied the new URL of the tut project into my actual project, did some testing. And then this is the big thing, I then put the same address I had been using back into my app, and... it just worked.... I did NOTHING to the code, and now it seems to work... So almost a month of work time lost and all I had to do was just put a different URL in, run it, and then put the original URL back in.... Lovely. I am guessing it cleared out some weird temp file that was messing up the program or something... even though I erased the temp files countless times... I don't get it, but onward I go!

Invalid Token when using ASP.NET MVC 5 and Dependency Injection with Unity

I am building an ASP.NET MVC 5 website and am using Unity for dependency injection. I get an Invalid Token exception when some time has passed (more than an hour, less than a day) between the token generation and the token validation.
I have the following code in my Startup.cs:
internal static IDataProtectionProvider DataProtectionProvider { get; private set; }
public void Configuration(IAppBuilder app)
{
DataProtectionProvider = app.GetDataProtectionProvider();
ConfigureAuth(app);
}
I have the following code in the conctructor of my ApplicationUserManager class (timespan is set to 7 days now just to make sure that is not the issue):
var dataProtectionProvider = Startup.DataProtectionProvider;
if (dataProtectionProvider != null)
{
this.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser> (dataProtectionProvider.Create("ASP.NET Identity")) {
TokenLifespan = TimeSpan.FromDays(7)
};
}
In Startup.Auth.cs, I have the following line of code in the ConfigureAuth method:
app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<ApplicationUserManager>());
In UnityConfig.cs, I have set up dependency injection:
container.RegisterType<ApplicationDbContext>();
container.RegisterType<ApplicationSignInManager>();
container.RegisterType<ApplicationUserManager>();
container.RegisterType<ApplicationRoleManager>();
container.RegisterType<IAuthenticationManager>(
new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication)
);
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(
new InjectionConstructor(typeof(ApplicationDbContext))
);
container.RegisterType<IRoleStore<IdentityRole, string>, RoleStore<IdentityRole>>(
new InjectionConstructor(typeof(ApplicationDbContext))
);
I have to add that one of my scenarios allows for the creation of a Contact with an associated user account. The Contact and associated user account are created in the ContactController, while the ConfirmEmail method is in the AccountController. Both take ApplicationUserManager as a constructor parameter, which means the ApplicationUserManager is injected into the controllers.
That does not appear to be the issue, since everything works fine if I confirm right after receiving the confirmation email. However, if I wait an hour or so, and then try to confirm, I get the Invalid Token exception.
I have already verified that I am not accidentally mixing different token types, both generation and verification are for email confirmation. I have also verified that I am url encoding (and decoding) the token.
I am currently testing on an Azure virtual machine with a static IP that is running its own IIS, the production environment will most likely be on a non-Azure VPS, als running its own IIS. I am not an Azure expert, but to my knowledge, I didn't select any options that are related to load balancing.
I would really appreciate your help, as I have already tried any possible solutions I was able to find here and on other websites.
The Invalid token issue has been solved. Since it only happened after some time had passed, I figured it might have something to do with my application recycling.
I managed to get rid of the problem by setting a fixed MachineKey in my web.config. You can use IIS Manager to generate it, as described here: https://blogs.msdn.microsoft.com/vijaysk/2009/05/13/iis-7-tip-10-you-can-generate-machine-keys-from-the-iis-manager/
Please note: for some reason, IIS adds the IsolateApps when it generates a machine key. However, this results in ASP.NET throwing an exception. After you manually remove the IsolateApps and save, it should work as expected.

ASP.NET Routing - GetRouteData does not work if path exists

I have a HttpModule which intercepts all requests and loads data from the database based on routing rules. However, I run into one problem all the time; GetRouteData only works if the path does not exist:
var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current));
Assuming a request comes in for the url http://localhost/contact, I get the correct routing data relating to that url if that path does not exist in the file system. The problem appears when I want to customize the page at that url which I do by creating an aspx page in the path ~/contact/default.aspx. Once I do that, GetRouteData return null.
I have even tried creating a new HttpContext object, but I still can not retrieve route data if the page exists.
Has anyone ever run into this problem? Is there a solution/workaround?
All help will be greatly appreciated.
Set RouteCollection.RouteExistingFiles to true.
public static void RegisterRoutes(RouteCollection routes)
{
// Cause paths to be routed even if they exists physically
routes.RouteExistingFiles = true;
// Map routes
routes.MapPageRoute("...", "...", "...");
}
Beware though. IIS7 behaves a little differently than the server used when debugging within Visual Studio. I got bit by this when I deployed my application to the web. Check out this feedback I submitted to Microsoft Connection.

Resources