Access cookies with a Firefox Addon content script? - cookies

I am trying to translate an Addon from Chrome that someone else created. It has a content script that has chrome.cookies.get in it. I can't find a suitable way to fix this for Firefox. Is there any way that I can access the cookies from a content script in the addon sdk?
Here's the original code:
function getCookies(domain, name, callback) {
chrome.cookies.get({"url": domain, "name": name},
function(cookie) {
if (callback) {
if (cookie) {
callback(cookie.value);
} else {
callback(null);
}
}
}
);
}

A content script doesn't have the necessary privileges to use any advanced API - neither in Firefox nor in Chrome. It can get the cookies for the current page via document.cookie however. Same restrictions apply as for the web page itself - HTTPOnly cookies won't be visible.
In the extension modules however you can use nsICookieManager2 interface to access cookies. See Access specific cookies by domain/name in Firefox extension for details. If you want that information from a content script you will have to send a message from the content script to the extension to make the extension retrieve it for you.

Related

Unity Facebook SDK Login, served with Django encounters CORS/CORB issues on Chrome

I am trying to get a very simple Unity application (Unity Version 2019.4.20f1 Personal) to authenticate with Facebook's SDK for unity. I have set up a local HTTPS server (with self-signed certificates) using Django & Gunicorn (Yes, not ideal, but just trying this out first), which serves the build products of Unity's WebGL.
Here is my one and only script in unity:
public class FacebookHelper : MonoBehaviour
{
// Awake function from Unity's MonoBehavior
void Awake ()
{
if (!FB.IsInitialized) {
// Initialize the Facebook SDK
FB.Init(InitCallback, OnHideUnity);
} else {
// Already initialized, signal an app activation App Event
FB.ActivateApp();
}
}
private void InitCallback ()
{
if (FB.IsInitialized) {
// Signal an app activation App Event
FB.ActivateApp();
// Continue with Facebook SDK
// ...
} else {
Debug.Log("Failed to Initialize the Facebook SDK");
}
}
private void OnHideUnity (bool isGameShown)
{
if (!isGameShown) {
// Pause the game - we will need to hide
Time.timeScale = 0;
} else {
// Resume the game - we're getting focus again
Time.timeScale = 1;
}
}
public void Login() {
var perms = new List<string>(){"public_profile", "email"};
FB.LogInWithReadPermissions(perms, this.AuthCallback);
}
public void Logout() {
FB.LogOut();
Debug.Log("User logged out.");
}
public void AuthCallback (ILoginResult result) {
if (FB.IsLoggedIn) {
// AccessToken class will have session details
var aToken = Facebook.Unity.AccessToken.CurrentAccessToken;
// Print current access token's User ID
Debug.Log("UserID: " + aToken.UserId);
// Print current access token's granted permissions
foreach (string perm in aToken.Permissions) {
Debug.Log("Permission: " + perm);
}
} else {
Debug.Log("User cancelled login");
}
}
}
where the Login() and Logout functions are called respectively when the two buttons below are pressed:
In Chrome, I have two issues:
I am getting CORS and CORB errors, notably only on the Logout() action, and not on the Login action.
For the Login() action, the Login Dialog is problematic because it opens a new tab as per usual, but it never allows me to input my login details before immediately closing this new tab. For some reason, my logging statements still say that FacebookSDK has successfully logged in.
In an attempt to solve this, I have
Enabled CORS on my Django application, according to instructions here. Sadly, this didn't work.
On the Facebook platform, I have done all these, to no avail as well:
Added localhost to the App Domain
Enabled Allow Cross Domain Share Redirects
Added https://localhost:8080 as the Website
Added https://localhost:8080 as a valid OAuth redirect uri to the 'Facebook Login for Gaming' Product
However, in Safari, I met with none of the aforementioned problems. The login flow works fine.
EDIT:
However, something I encountered on both Chrome and Safari is that for some reason, when the SDK is initialized, it always automatically signs in a default user. For now, I will just add some code to sign out at initialize time to remedy this.
As usual, spent quite a while on this but wasn't able to figure out how I can solve this. According to my understanding, I have to make sure the responses to my server have the Access-Control-Allow-Origin header, and these may be some ways I think I can do it:
Somehow make FacebookSDK set the Access-Control-Allow-Origin header on the response? Maybe their GraphQL API will be more helpful?
Use Nginx to reverse proxy and serve the static files instead, and then I should be able to do something like adding the Access-Control-Allow-Origin header as well. I have thought of doing this but it'll take a bit of investigation, so I haven't tried this yet.
For the CORB issues, I don't really have any ideas though.
I really appreciate it if anyone has taken the time to read up till here, but anyways, thank you to anyone who can help at all! :)
EDIT 1:
Here is the request/response for Safari:
And here are the request/response for Chrome:
The observations I can make is that for some reason Facebook is not returning the Access-Control-Allow-Origin in the response for the Chrome request. Maybe it is due to the additional headers in the Chrome request?
You need to use a third library or do that in Chrome itself but it's prerence dependent
pip install django-cors-headers
So in Settings:
INSTALLED_APPS = (
...
'corsheaders',
...
)
MIDDLEWARE_CLASSES = (
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
)
Or check out his docs for more details https://github.com/adamchainz/django-cors-headers#setup

On what domain is my Javascript in my Office Add-In

We have an Outlook Add-In which runs in OWA.
The Manifest sits on https://company.ourdomain.com
The Javascript sits on https://company.ourdomain.com
The Custom Web Service we wrote in-house sits on https://company.ourdomain.com
When I make a call from within JavaScript in response to an Add-In Command, I use the format https://company.ourdomain.com/api/Controller/Action in the ajax call.
I end up getting one of those CORS errors (sometimes it's pre-flight, other times CORB). Why am I getting this if the Javascript is literally sitting on the same domain as the web service?
I'm assuming I'm authenticated since I've logged into my Outlook account.
What gives?
NOTE:
As an experiment I attempted a RESTful call by directly typing in the URL (No OWA involved). This caused the code to Authenticate against Azure AD. Then afterward I logged into OWA in the same browser session and everything worked fine. Do I actually need to authenticate within the Javascript even if the webservice I'm calling is in the same domain?
AJAX CALL WHICH GENERATES ERROR
Remember, it will work just fine after I've made a RESTful call by making a call to my web service directly from the Browser
var apiUri = '/api/People/ShowRecord';
$.ajax({
url: apiUri,
type: 'POST',
data: JSON.stringify(serviceRequest),
contentType: 'application/json; charset=utf-8',
dataType: 'json'
}).done(function (response) {
if (!response.isError) {
// response to successful call
}
else {
// ...
}
}).fail(function (status) {
// some other response
}).always(function () {
console.log("Completed");
});
OBSERVATION
When I call the api from the Address Bar the code below is run. This code never gets invoked by Javascript
[assembly: OwinStartup(typeof(EEWService.AuthStartup))]
namespace EEWService
{
public partial class AuthStartup
{
public void Configuration(IAppBuilder app)
{ app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Notifications = new WsFederationAuthenticationNotifications
{
RedirectToIdentityProvider = (context) =>
{
context.ProtocolMessage.Whr = "ourdomain.com";
return Task.FromResult(0);
}
},
MetadataAddress = ConfigurationManager.AppSettings["ida:MetadataAddress"],
Wtrealm = ConfigurationManager.AppSettings["ida:Audience"],
TokenValidationParameters = new TokenValidationParameters
{
ValidAudiences = new string[] { $"spn:{ConfigurationManager.AppSettings["ida:Audience"]}" }
}
});
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"]
},
MetadataAddress = ConfigurationManager.AppSettings["ida:MetadataAddress"],
});
}
}
}
There are a few problems with this I think.
The first one is you are trying to serve your static content off the same server you are serving your code from. This is in general considered a bad-practice, purely because no point in wasting those precious server resources for static content. Ideally you should upload your static content to a CDN - and let the users' browser make a request to some super-cached file server. However - I understand this option might not be available to you as of now. This also isn't the root cause.
The second and the real problem is, (you think you are but) you are not authenticated. Authentication in Outlook web-addins doesn't come by default, it's something you need to handle. When Outlook loads your web add-in into the side panel it makes certain methods available to you which you can use and kind-of create a pseudo-identity (as an example Office.context.mailbox.userProfile.emailAddress ) - but if you want real authentication, you will need to do that yourself.
There are three ways of doing that as far as I can tell.
The first one is through the Exchange Identity Token
Second one is through the Single Sign On feature
The third one - which I think is the most convenient and the simplest in logic to implement is using WebSockets. (SignalR might be what you need).
When the user loads your first page, make sure a JS value like window.Unique_ID available to them. This will come in handy.
Have a button in your UI - which reads "Authenticate"
When the user clicks to this button, you pop them out to a url which will redirect to your authentication URL. (Something like https://company.ourdomain.com/redirToAuth). This would save you the trouble of getting blocked in the side-panel, because you are using window.open with a url that's on your domain. Pass that Unique_ID to redirection which then redirects you to OAuth login URL. That should look like https://login.microsoftonline.com/......&state=Unique_ID
Right after popping the user to sign in window, in your main JS (which is client-side), you open a web-socket to your server, again with that Unique_ID and start listening.
When the user completes authentication, the OAuth flow should post back either an access token, or the code. If you get the access token, you can send it through the sockets to front-end (using the Unique_ID which is in the parameters of post-back) or if you had the code, you finish authenticating the user with a server-to-server call and pass the access token the same way afterwards. So you use that unique Id to track the socket that user connected from and relay access token to only that user.

How to use lighthouse with specific cookie of login details?

I'm trying to run Lighthouse on my website from the command line.
When Chrome browser opens it comes without any cookies, therefore the desired page isn't loaded and instead I get my login page.
I tried to use --extra-headers flag when running lighthouse with a cookie, but I'm not sure this is the right way (and if so, what should be come inside "Cookie" attribute)
Running Lighthouse with:
lighthouse SITE_URL --output json --output-path ./report.json --extra-headers=./headers.json
And the headers.json file is:
{
"Cookie": "Username=my_username; Password:my_password;"
}
Is that the right way to insert a cookie for loading a website ?
If so, what is the right syntax for custom cookies?
To view the right syntax for the cookie, I logged in and copied the Session value for logging in.
{
"Cookie": "mySession=SESSION_HASH;"
}

Postman: How do you delete cookies in the pre-request script?

All the postman cookie-management answers I've seen refer to either the browser extension (open chrome, delete cookies viz interceptor etc) or with the app, using the UI to manually manage cookies.
I would like to delete certain cookies in my pre-request code as part of scripting my API tests. (delete them programmatically)
The Sandobx API docs mention pm.cookies so I tried
if (pm.cookies !== null) {
console.log("cookies!");
console.log(pm.cookies);
}
But the pm.cookies array is empty. Yet in the console, the GET call then passes a cookie.
There's also postman.getResponseCookies, which is null (I assume because we're in the pre-request section, not in the test section)
One answer suggested calling the postman-echo service to delete the cookie. I haven't investigated this yet, but it doesn't feel right.
new version now supports that since 2019/08, see more examples here: Delete cookies programmatically · Issue #3312 · postmanlabs/postman-app-support
Prerequisite
Cookie domains to be given programatic access must be whitelisted.
clear all cookies
const jar = pm.cookies.jar();
jar.clear(pm.request.url, function (error) {
// error - <Error>
});
get all cookies
const jar = pm.cookies.jar();
jar.getAll('http://example.com', function (error, cookies) {
// error - <Error>
// cookies - <PostmanCookieList>
// PostmanCookieList: https://www.postmanlabs.com/postman-collection/CookieList.html
});
get specific cookie
const jar = pm.cookies.jar();
jar.get('http://example.com', 'token', function (error, value) {
// error - <Error>
// value - <String>
});
According to the documentation pm API reference the pm.cookie API is only for the Tests tab, not for the Pre-request Script.
The following items are available in TEST SCRIPTS only.
pm.cookies
...
It seems that you will have to stick with this method : Interceptor Blog post
I know this is a very late answer, but for my case where I didn't want to use the cookies to start the execution of the collection, I just needed to uncheck the option "Save cookies after the collection run" and check the option "Run collection without using stored cookies" on the Runner panel.
And then if I want to manage the cookies on my own, I created a first request on the collection and used the Tests tab just to collect the cookies that I wanted and saved them on a variable.
pm.environment.set('cookie', pm.cookies.get('csrftoken'))
pm.environment.set('sessionid', pm.cookies.get('sessionid'))

phantomjs - Cookie is not being sent for any XHR/POST/GET AJAX requests

I found an interesting issue when attempting to login using PhantomJS. I'm at a loss as to why it's actually occurring.
Basically you start up a remote debugger like so:
/usr/local/bin/phantomjs --web-security=no --remote-debugger-port=13379 --remote-debugger-autorun=yes /tmp/test.js
Within the remote debugger:
> location.href = "https://www.mysite.com/login"
> $('input[name="username_or_email"]').val('blah#email.com')
> $('input[name="password"]').val('wrongpassword')
> $('button[type="submit"]').submit()
Doing this in Chrome will give me the correct "wrong password" message after the XHR request, whereas using phantomjs gives me a generic error as no cookie is sent with phantomjs (I examined the headers).
I'm quite confused on why phantomjs doesn't send the cookie with the POST request. Does anyone know how we can get phantomjs to send the cookie with ALL requests as it should? Setting a cookie-file doesn't make any difference either.
Ok, this seems to be something related with session cookies and not regular cookies.
Heres a huge thread on the developer in charge of the cookies feature of phantomjs and some guys with the same issue as yours.
https://groups.google.com/forum/#!msg/phantomjs/2UbPkIibnDg/JLV9jBKxhIQJ
If you dont want to skirm through the entire file, basically:
Phantomjs behaves like a regular browser, and it deletes all session cookies when browser closes, in your case, when your script execution ends.
So, even if you set the --cookies-file=/path/to/cookies.txt option you will only store regular cookies on it, for subsecuent executions.
There are two possible approaches for you. One, is to make all requests within the same script, or the other is to store and restore the cookies manually.
On the thread there are a couple of functions that you can use to do this.
function saveCookies(sessionCookieFile, page) {
var fs = require("fs");
fs.write(sessionCookieFile, JSON.stringify(page.cookies));
}
function restoreCookies(sessionCookieFile, page) {
var fs = require("fs");
var cookies = fs.read(sessionCookieFile);
page.cookies = JSON.parse(cookies);
}
var page = require('webpage').create();
And, if everything fails...
You could download source code and recopile phantomjs
You will need to edit src/cookiejar.cpp and remove or comment purgeSessionCookies();
Hope, this helps.