How to use cloudflare workers to bypass ad Blockers restrictions? - cloudflare

I am trying to load fingerprintjs script in a google chrome browser where Ublock origin is enabled but it's impossible with my current situation :
<script> // Initialize the agent at application startup. const fpPromise = import('https://fpcdn.io/v3/your-public-api-key')
.then(FingerprintJS => FingerprintJS.load({
endpoint: 'https://fp.yourdomain.com' }));
// When you need the visitor identifier: fpPromise .then(fp => fp.get())
.then(result => console.log(result.visitorId));
</script>
At the page load, my browser's console shows :
Uncaught (in promise) TypeError: Failed to fetch dynamically imported module: https://fpcdn.io/v3/your-public-api-key
Some people suggest to use cloudflare workers to evade Ublock restrictions. But I never used cloudflare I just started my first worker now :
addEventListener("fetch", event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
return new Response("Hello world")
}
How can I use this workers to get my visitorId ?

This feature will be released in a couple of weeks and will be part of the product. Nevertheless, there's a public beta that requires some manual steps. If you are interested, reach out to the official support: support#fingerprint.com

Related

Cypress uncaught:exception handler not working with Magic.link flow

I'm using Cypress to test a login flow that uses Magic.link auth on a mobile Web device, which is encountering the ResizeObserver loop limit exceeded error, as it tries to navigate the Google Auth forms. I've looked at numerous posts, and played around with my test, but it seems the handler is not working.
The recommended Google Authentication from the Cypress docs is insufficient, because with Magic, the flow is initiated by a call to magic.oauth.loginWithRedirect, hence I was hoping to drive the process via the UI directly.
You'll see I added a test to ensure the password input is visible. Now the exception is being thrown at that part of the test. If I remove that check the error occurs on the next step where I try to type the password.
describe('my auth flow', () => {
it('can auth with google', () => {
// click login button from my site
cy.get('button')
.contains('sign-in')
.click();
cy.origin('https://accounts.google.com', () => {
// enter email address
cy.get('input[type=email]')
.type('myuser#mydomain.com');
cy.get('button')
.find('span')
.contains('Next')
.click();
// wait for password page to show
cy.get('#password')
.should('exist')
.and('be.visible'); // error here...
// enter password
// error here if above visibility check removed
cy.get('#password input[type=password]')
.type('mypassword');
cy.get('button')
.find('span')
.contains('Next')
.click();
});
});
});
In support/commands.js, I've added the global error handler, which should handle all uncaught exceptions according to the documentation.
Cypress.on(
'uncaught:exception',
(err) => false
);
Magic does have a test mode, however I really don't want to bypass the login flow. Ideally I could exercise the login flow without hacks for testing.
The cy.origin() command is an isolated sandbox with different document and window to the primary domain.
Try adding the exception handler inside the origin command (presuming the error is happening while on the google domain).
cy.origin('https://accounts.google.com', () => {
Cypress.on('uncaught:exception', (err) => false)

cy.origin redirects user to a blank page

Scenario:
I am clicking a login button from my application served on localhost.
It redirects me to azure sso login through cy.origin
Authentication is performed fine.
User logs in successfully to the app.
But it redirects me to a blank page and hence rest of the IT blocks get failed.
The code attached below works fine but as soon as first IT block passes, upon the execution of second IT block page is set to about:blank so the test cases fail.
Question: What should be the workaround so that I can continue testing on application under test?
Second describe gets failed
Cypress.Commands.add('authenticate', () =>{
cy.visit('http://localhost:8080/')
cy.get('input[value="***"]').click();
cy.origin(`https://login.microsoftonline.com/`, () => {
cy.wait(3000)
cy.get('#i0116').type('username')
cy.get('#idSIButton9').click()
cy.wait(3000)
cy.get('#i0118').type('password')
cy.wait(2000)
cy.get('#idSIButton9').click()
cy.wait(2000)
cy.get('#idSIButton9').click();
})
cy.wait(6000)
cy.url().should('contain', 'Welcome')
})
According to the documentation, that behavior is by design
Take a look at cy.origin()
The cy.origin() command is currently experimental and can be enabled by setting the experimentalSessionAndOrigin flag to true in the Cypress config.
Enabling this flag does the following:
It adds the following new behaviors (that will be the default in a future major version release of Cypress) at the beginning of each test:
The page is cleared (by setting it to about:blank).
If by "Second describe gets failed" you mean the second test is not visiting the Welcome page, then just explicitly visit cy.visit('http://localhost:8080/') at the beginning of the second test.
This is the recommended approach when using cy.origin.
By the way, you should set http://localhost:8080/ as baseUrl in configuration, and use cy.visit('/') instead - from Cypress best practices.
Cypress.Commands.add("session_thing", (email, password) => {
cy.session([email, password], () => {
cy.visit('http://localhost:8080/AdminWebapp/Welcome.html')
cy.get('input[value="Log In With Office 365"]').click();
cy.origin(
`https://login.microsoftonline.com/`,
{ args: [email, password] },
([email, password]) => {
cy.wait(3000)
cy.get('#i0116').type(email)
cy.get('#idSIButton9').click()
cy.wait(3000)
cy.get('#i0118').type(password)
cy.wait(2000)
cy.get('#idSIButton9').click()
cy.wait(2000)
cy.get('#idSIButton9').click();
}
);
cy.url().should('contain', 'Welcome')
});
});
The desired behavior was achieved with above code. It restores the session in beforeEach hook. I am simply calling the cy.visit('/') in every IT block and perform the required actions which is kind of very fast with session feature.

Cypress doesn't work with an external login

I'm working on e2e test with cypress on my application.
In my case the login are manage by a external service.
When I want to enter in my application's home page (https://myApplication/home), the system redirects me in different superdomains to login.
At first cypress seems to be able to change the superdomain, but once arrived in external service page for the authentication, the system go in login error (as if we have already logged in, but incorrect).
This type of behavior does not happen outside the cypress .
Are there alternative solutions to manage external access in a cypress test or is it possible to manage it directly from cypress?
I added in my cypress.json the chromeWebSecurity:false and when I call the link for login, I added the failOnStatusCode: false,
but it still doesn't work.
Assuming this is caused by SameSite cookie blocking , then I've just been fighting the same issue. I resolved it by intercepting all requests, checking if they had a set-cookie header(s) and rewriting the SameSite attribute. There's probably a neater way to do it, as this does clutter up the cypress dashboard a little.
Sadly Zachary Costa's answer no longer works as Chrome 94 removed the SameSiteByDefaultCookies flag.
You can add this as a command for easy reuse:
In your commands file:
declare namespace Cypress {
interface Chainable<Subject> {
disableSameSiteCookieRestrictions(): void;
}
}
Cypress.Commands.add('disableSameSiteCookieRestrictions', () => {
cy.intercept('*', (req) => {
req.on('response', (res) => {
if (!res.headers['set-cookie']) {
return;
}
const disableSameSite = (headerContent: string): string => {
return headerContent.replace(/samesite=(lax|strict)/ig, 'samesite=none');
}
if (Array.isArray(res.headers['set-cookie'])) {
res.headers['set-cookie'] = res.headers['set-cookie'].map(disableSameSite);
} else {
res.headers['set-cookie'] = disableSameSite(res.headers['set-cookie']);
}
})
});
});
Usage:
it('should login using third party idp', () => {
cy.disableSameSiteCookieRestrictions();
//add test body here
});
or alteratively, run it before each test:
beforeEach(() => cy.disableSameSiteCookieRestrictions());
We were encountering a similar issue, where Cypress was redirecting us to the default "You are not logged in" page after getting through the login process. I'm not certain if that's EXACTLY the issue you were experiencing, but just in case, here's our solution. In our case, the issue was caused by Chrome's "Same Site Cookies" feature interacting poorly with Cypress, so we needed to disable it. In your plugins/index.js file, you would add the following code:
module.exports = (on, config) => {
on('before:browser:launch', (browser, launchOptions) => {
if (browser.name === 'chrome') {
launchOptions.args.push('--disable-features=SameSiteByDefaultCookies');
}
return launchOptions;
});
};
Note that if you already have launchOptions being set, you can just add this code onto it so it doesn't clash at all.
Hopefully, this works for you as well!
In the current version of cypress you can't go to another domain in the same test. This is due to the fact that cypress injects its test into the browser (they are working on this issue).
So one solution today is that you need to utilize cy.request to perform the login programmatically and inject the auth secret (jwt, cookie, localstorage, token or what you have) into the browser context yourself (for cookie this would be cy.setcookie).
Always make sure to checkout the plugins if there is already an abstraction for your login. Often this is openId or ntlm.

Vue PWA caching routes in advance

I'm hoping someone can tell me if I'm barking up the wrong tree. I have built a basic web app using Vue CLI and included the PWA support. Everything seems to work fine, I get the install prompt etc.
What I want to do, is cache various pages (routes) that user hasn't visited before, but so that they can when offline.
The reason here is that I'm planning to build an app for an airline and part of that app will act as an in flight magazine, allowing users to read various articles, however the aircrafts do not have wifi so the users need to download the app in the boarding area and my goal is to then pre cache say the top 10 articles so they can read them during the flight.
Is this possible? and is PWA caching the right way to go about it? Has anyone does this sort of thing before?
Thanks in advance
To "convert" your website to an PWA, you just need few steps.
You need to know that the service worker is not running on the main thread and you cant access for example the DOM inside him.
First create an serviceworker.
For example, go to your root directory of your project and add a javascript file called serviceworker.js this will be your service worker.
Register the service worker.
To register the service worker, you will need to check if its even possible in this browser, and then register him:
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/serviceworker.js').then(function(registration) {
// Registration was successful
console.log('ServiceWorker registration successful with scope');
}, function(err) {
// registration failed :(
console.log('ServiceWorker registration failed: ', err);
});
});
}
In vue.js you can put this inside mounted() or created() hook.
If you would run this code it will say that the service worker is successfully registered even if we havent wrote any code inside serviceworker.js
The fetch handler
Inside of serviceworker.js its good to create a variable for example CACHE_NAME. This will be the name of your cache where the cached content will be saved at.
var CACHE_NAME = "mycache_v1";
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.open(CACHE_NAME).then(function(cache) {
return cache.match(event.request).then(function (response) {
return response || fetch(event.request).then(function(response) {
cache.put(event.request, response.clone());
return response;
});
});
})
);
});
Everytime you make a network request your request runs through the service worker fetch handler here first. You need to response with event.respondWith()
Next step is you first open your cache called mycache_v1 and take a look inside if there is a match with your request.
Remember: cache.match() wont get rejected if there is no match, it just returns undefined because of that there is a || operator at the return statement.
If there is a match available return the match out of the cache, if not then fetch() the event request.
In the fetch() you save the response inside the cache AND return the response to the user.
This is called cache-first approach because you first take a look inside the cache and in case there is no match you make a fallback to the network.
Actually you could go a step further by adding a catch() at your fetch like this:
return response || fetch(event.request).then(function(response) {
cache.put(event.request, response.clone());
return response;
})
.catch(err => {
return fetch("/offline.html")
});
In case there is nothing inside the cache AND you also have no network error you could response with a offline page.
You ask yourself maybe: "Ok, no cache available and no internet, how is the user supposed to see the offline page, it requires internet connection too to see it right?"
In case of that you can pre-cache some pages.
First you create a array with routes that you want to cache:
var PRE_CACHE = ["/offline.html"];
In our case its just the offline.html page. You are able to add css and js files aswell.
Now you need the install handler:
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
return cache.addAll(PRE_CACHE);
})
);
});
The install is just called 1x whenever a service worker gets registered.
This just means: Open your cache, add the routes inside the cache. Now if you register you SW your offline.html is pre-cached.
I suggest to read the "Web fundamentals" from the google guys: https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook
There are other strategies like: network-first
To be honest i dont know exactly how the routing works with SPAs because SPA is just 1 index.html file that is shipped to the client and the routing is handled by javascript you will need to check it out witch is the best strategie for your app.

How to authenticate users in FirefoxOS using BrowserID / Persona?

I am trying to write an FirefoxOS app for my portal which uses Mozilla Persona for authentication. How I should proceed if I want to achieve:
Allow users of my app to signup to my portal using Persona
Allow users of my app to login to my portal within the FirefoxOS app and perform some actions with the API
Depends if users is logged or not - giving access to different actions.
I have found this post with info that its integrated already: http://identity.mozilla.com/post/47114516102/persona-on-firefox-os-phones but I can't find any real examples.
What type of application I need to create? webapp or privileged?
I am trying to implement it using regular tutorial: https://developer.mozilla.org/en/Persona/Quick_Setup
But with this code:
signinLink.onclick = function() { navigator.id.request(); };
I am getting only following error:
[17:25:18.089] Error: Permission denied to access object
One thing is to make sure you're calling watch() to setup callbacks before you call request().
For example, something like this in your page:
<script src="https://login.persona.org/include.js"></script>
<script>
window.addEventListener("DOMContentLoaded", function() {
navigator.id.watch({
// Provide a hint to Persona: who do you think is logged in?
loggedInUser: null,
// Called when persona provides you an identity assertion
// after a successful request(). You *must* post the assertion
// to your server for verification. Never verify assertions
// in client code. See Step 3 in this document:
// https://developer.mozilla.org/en/Persona/Quick_Setup
onlogin: function(assertion) {
// do something with assertion ...
// Note that Persona will also call this function automatically
// if a previously-signed-in user visits your page again.
},
onlogout: function() {
// handle logout ...
},
onready: function() {
// Your signal that Persona's state- and callback-management
// business is complete. Enable signin buttons etc.
}
});
// Set up click handlers for your buttons
document.getElementById("signin").addEventListener(
'click', function() {
navigator.id.request({
// optional callback to request so you can respond to
// a user canceling the sign-in flow
oncancel: function() { /* do something */ }
});
}
});
});
</script>
Here's an example that shows this in action:
https://people.mozilla.org/~jparsons/persona_example.html
However, on FirefoxOS, you should be aware that installed apps (not packaged or certified, but generic installed apps) are given a unique origin of the form app://{uuid}, with a different uuid for each device. This is unfortunately useless for sign-in purposes because there's no way for your server to know whether an app requesting sign-in is friend or foe. The way around this problem is to run your persona code in an invisible iframe hosted on your server. Thus the iframe will have the correct origin and your server will know it's your app. The iframe and the app can communicate via postMessage.
In the case of a packaged app (sometimes called a privileged app), your origin will be the origin declared in your webapp manifest. E.g., app://yourapp.yoursite.org. This gives you better assurance that the app is really yours, but the truly paranoid may still wish to deploy the iframe trick.
Hope this helps!
j