How to read and set cookies from Browser/WebView in NativeScript? - nativescript

I'm building an app which mainly displays public data from a website. A few items require authentication to read. I don't want to recreate the entire website in the app so I'd like to have the user log in via a web view or browser popup and grab the cookie containing the token from this session. I would then use it to authenticate my in-app rest calls in order to fetch the data. This should work on iOS and Android but I couldn't come up with a functioning solution yet. How would one read and write cookies from the phone browser / webview? I'm using the latest Angular (9) and NativeScript.

For android
The webview UI
<WebView height="1200px" src="https://www.nativescript.org"
(loadFinished)="onLoadFinished($event)"></WebView>
The typescript code
import * as application from 'application';
declare const android;
....
....
....
onLoadFinished(args: LoadEventData) {
android.webkit.CookieManager.getInstance().getCookie(<cookie name>)
android.webkit.CookieManager.getInstance().setCookie(<cookie name>, <cookie value>)
}
For IOS seems it is little bit complicated
Refer StackOverflow set cookie in IOS nativescript

Related

AddWebAllowedObject is not working when .Net Native Tool Chain is Enabled

I have created UWP app which has a webview embedded in it. The webview is loaded with URL of a web app.
The web app has a JavaScript object added to the window object.
example:window.html_communicator
The web app uses this html_communicator object and calls certain methods on it to invoke callbacks on the UWP application.
for example, there can be a method defined on html_communicator called onLocationSelect and the web app will call this method upon some user interaction.
The UWP app registers to the methods by calling addWebAllowedObject on the WebView.
The callbacks are working fine when I disabled .Net Native Tool Chain.
But these callbacks are not working fine when .Net Natvie Tool Chain is enabled.
Below is a javascript code snippet that calls the bridge method on button click.
var html_communicator = html_communicator || {};
window.onload = function () {
document.getElementById("locationSelect")
.addEventListener("click", () => {
if (html_communicator && html_communicator.onLocationSelect) {
document.getElementById("msg").innerHTML = `Successfully called bridge method: Button clicked at ${new Date()}`;
sumorea_app.onLocationSelect();
}
else {
document.getElementById("msg").innerHTML = `Failed to call bridge method: Button clicked at ${new Date()}`;
}
})
}
The callbacks are working fine when I disabled .Net Native Tool Chain. But these callbacks are not working fine when .Net Natvie Tool Chain is enabled.
Please refer to webview official document, In addition, trusted JavaScript content in WebView can be allowed to directly access Windows RuntimeAPI. This provides powerful native capabilities for web apps hosted in WebView. To enable this feature, the Uniform Resource Identifier (URI) for trusted content must be added to the allowlist in the ApplicationContentUriRules of the app in Package.appxmanifest, with WindowsRuntimeAccess specifically set to "all".
For Xamarin solution, you need check if has add above allowlist for UWP project.

Xamarin.Forms UI Automation Testing WaitForElement WebView always times out

My Xamarin.Forms app uses Azure AD B2C for authentication. It works great. I'm trying to build UI automation tests now and I ran into my first blocker. I have been trying to wait for the WebView to come on the screen so I can enter the email and password of a test user into my ui test automation script however the WaitForElement method always times out!
[Test]
public void RegistrationStarts()
{
app.Screenshot("Welcome screen.");
app.WaitForElement(c => c.WebView());
app.Tap(c => c.WebView().Css("input#logonIdentifier"));
app.EnterText("sample#example.com");
}
I'm not sure why. I'm only testing in Android. I notice that the Azure AD B2C login web view appears to be inside my app. I can tell this because when I open the Android task switcher I can see Chrome and my app.
Is there a reason you used input before the id? If logonIdentifier is your ID of whatever you want to type, it should just be
app.Tap(c => c.WebView().Css("#logonIdentifier"));
Also, if logonIdentifier is the TextBox in which you want to type, enter text should be
_app.EnterText(c => c.WebView().Css("#logonIdentifier"), "sample#example.com");
you can try wait for element with timeout - time in milisecond, second, and min.
app.WaitForElement(x => x.Marked("AutomationID"), timeout:TimeSpan.FromSeconds(90));
or
https://learn.microsoft.com/en-us/dotnet/api/xamarin.uitest.iapp.waitforelement?view=xamarin-uitest-sdk
It seems you are using systembrowser instead of WebView.
Change your method of acquiring token with WebView.
AuthenticationResult authResult = await _pca.AcquireTokenInteractive(B2CConstants.Scopes)
.WithUseEmbeddedWebView(true)
.ExecuteAsync();
https://github.com/microsoft/appcenter/issues/287#issuecomment-484151924

xamarin android project access PCL function

I created a Cross Platform Xamarin Forms app. In the Portable Class I have a WebView that loads a web page from a URL.
From my Android project, I would like to be able to change the WebView URL.
What is the best way to do this ? I am kind of new to this, so any help to point me in the right direction would be great.
Thank you
I had a similar scenario in which I wanted to read the received SMS in Android project and send the message to PCL project.
For that I used Xamarin's MessagingCenter:
In Android's activity, upon receiving the SMS, I used the following code to send the SMS message body back to PCL:
MessagingCenter.Send<RegisterSecondPage, string>
(new RegisterSecondPage(), "OtpReceived", code);
And in one of my PCL pages I received it back like this:
MessagingCenter.Subscribe<RegisterSecondPage, string>
(new RegisterSecondPage(), "OtpReceived", async (s, code) =>
{
ActivationCode = code;
});
I believe you can use similar scenario as well.

Xamarin forms open another app using Rivets component

I have to open an app from another app in Xamarin forms. I found the Rivets component which says it can do what i want but I'm not sure what url it refers to.
I looked at http://applinks.org/documentation/ and it says the url I want opened per mobile platform.
My question is, for iOS, what url is it looking for? I thought it was the link to the app in itunes. All that link does is open the app store at the app but doesn't launch the app if it's already installed.
Unless you have control over the Blue Diamond Party app's code or you know that the Blue Diamond Party app has registered one or more custom app links (which are the custom URLs you have read about), you will not be able to open it from your app on iOS. This is the only way to make that work with Rivets. The Blue Diamond Party app would need to register a custom URI of some kind that it would respond to. Then, using Rivets, your app would call that custom URI.
*Edit: To get your app to handle app links from other apps, you can head to the Xamarin's Getting Started Guide (look under the Handling Incoming App Link Navigation heading):
Android does things different than iOS, but for iOS:
Register the custom URI in the Info.plist (not sure if that is the correct XML but it is something like that, check out the link for an image)(the string under CFBundleURLName is just a custom name for your scheme and then you can list multiple schemes in the array under the name):
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.bluediamondparty.schemes</string>
<key>CFBundleURLSchemes</key>
<array>
<string>bluediamondparty</string>
</array>
</dict>
</array>
The above XML would register the bluediamondparty as your URI scheme for your app to respond to.
Now, in order for your app to do something when a URI with your custom scheme is run, you override OpenUrl in your AppDelegate (this allows you to put things after your custom URI scheme to, for example, open a specific page or item in your app):
public override bool OpenUrl (UIApplication app, NSUrl url, string srcApp, NSObject annotation) {
var rurl = new Rivets.AppLinkUrl (url.ToString ());
if (rurl.InputUrl.Host.Equals ("play")) {
var gameModeType = rurl.InputQueryParameters ["game_mode_type"];
var c = new ProductViewController (gameModeType, rurl.Referrer);
navController.PushViewController (c, true);
return true;
}
return false;
}
To open the URI from your second app, you might run something like this:
UIApplication.SharedApplication.OpenUrl(new NSUrl("bluediamondparty://play?game_mode_type=survival"));
Finally, you might notice that none of that actually required using the Rivets component... so what does that component actually do for us?! What Rivets actually does is to allow your app to pass in a real URL (such as http://rdio.com/song/12345) and Rivets will go to that page and look for special meta tags that describes how the content on the page is linked to a mobile app that the user might have installed on their device. So on that rdio web page they might have the following meta tag:
<meta property="al:ios:url" content="rdio://song/12345" />
In that meta tag it will list the correct custom URI scheme to attempt to open the Rdio app if the user has it installed and it has registered itself with the custom rdio URI scheme.
The other thing to know is that your app does not have exclusive rights to a URI scheme. So if another app chooses the same URI scheme as you and the user installs both of them, then the last app to be installed will respond to the URI scheme.

How can I authenticate with google inside of a firefox plugin

I'd like to add a calendar entry from my Firefox plugin to the user's Google calendar (with their authorization, of course). Unfortunately, I can't seem to figure out how to authenticate with Gapi within the context of the Firefox SDK.
I tried including the client.js from gapi directly as a module in my source, but this isn't effective, since it can't access the window object. My next attempt was something akin to what I do with jQuery - load it in a content script:
googleClient.js
var tabs = require("sdk/tabs");
var self = require('sdk/self');
function initAuth() {
var worker = tabs.activeTab.attach({
url: 'about:blank',
contentScriptFile: [self.data.url('gapi.js'), self.data.url('authContentScript.js')]
});
}
exports.initAuth = initAuth;
main.js:
var googleClient = require('./googleClient');
I get the following problem:
console.error: foxplugin:
Error opening input stream (invalid filename?)
In the ideal situation, it would open a new window in the browser that allows the user to login to Google (similar to what happens when one requests access to the oauth2 endpoint from within a "real" content script).
I had the same problem so I've made an npm plugin for that. It's called addon-google-oauth2 and works for Google OAuth2 tested with AdSense API. It's really simple, it just calls REST APIs for OAuth2. Steps:
Create an OAuth2 client for native application. No web or Android, just native.
If your addon is using jpm ok, if it uses cfx, please migrate to jpm
Download and save the dependency with npm
npm install addon-google-oauth2 --save
Follow the tutorial on the README.md file. It's easy, just two API calls
refreshToken(options,callback);
getToken();
Insert the HTML and JS file on your data/ directory

Resources