programming – Rantings in the dark https://kinsey.no/blog Because I want to be like the cool kids too Mon, 11 Jan 2021 20:57:51 +0000 en-US hourly 1 https://wordpress.org/?v=5.8.18 How to set up an AD backed OpenID Provider without direct communication https://kinsey.no/blog/index.php/2010/07/09/how-to-set-up-an-ad-backed-openid-provider-without-direct-communication/ https://kinsey.no/blog/index.php/2010/07/09/how-to-set-up-an-ad-backed-openid-provider-without-direct-communication/#comments Fri, 09 Jul 2010 17:11:41 +0000 http://kinsey.no/blog/?p=290 I’ve currently got a project where I need to provide an OpenID Provider (OP) to authenticate users using Active Directory (AD), something that shouldn’t be to much of a hassle.
But there is a catch: the OP needs to be outside the firewall in order to talk to the Relying Parties (RP) and is unable to communicate directly with AD. So what can you do?

Well, in this case the OP is only going to be used by users that are sitting behind the firewall, and who have access to both internal resources and external resources over port 80, and what this means is that we can use the client (the browser) to relay messages between the OP and the asserting party. In order to make the communication going via the browser trusted, we can use a challenge combined with symmetric encryption to verify authenticity.

This means that the chain of trust needed for the identity assertion looks like the following

  • The RP trust the assertion from the OP
    • The RP and the OP shares can communicate directly and uses a shared secret to verify the authenticity of the message passed through the browser
  • The RP trusts the assertion from the Internal Webserver (IW)
    • The RP and the IW has a pre-shared encryption key that together with a challenge serves to verify the authenticity of the messages passed through the browser

In the following code DotNetOpenAuth is used to provide support for OpenID, and easyXDM is used to provide the Cross-Document Communication.
Codewise, it all starts once the OpenID request hits the OP, and at this point we only store away the request and render a blank page containing the following JavaScript

// server.aspx
// This is called by ASP.NET Ajax once the page is ready
function pageLoad() {
    // Set up a new easyXDM.Rpc object
    var rpc = new easyXDM.Rpc({
        remote: "http://localhost:55192/Endpoint.aspx"
    }, {
        remote: {
            authenticate: {}
        }
    });

    // Retrieve a challenge from the server 
    PageMethods.GetChallenge(function (challenge) {
        // Relay the challenge to the internal webserver
        rpc.authenticate(challenge, function (response) {
            // Relay the response back to the server
            PageMethods.VerifyResponse(response, function (verified) {
                // If the response was verified, we redirect to the page that will complete the OpenID assertion
                if (verified) {
                    location.href = "complete.aspx";
                } else {
                    alert("not authenticated");
                }
            });
        });
    });
}

As you can see this uses PageMethods to talk to the server side code for retrieving the challenge, and for delivering the response

'server.aspx
<WebMethod()> _
Public Shared Function GetChallenge() As Utilities.Challenge
    ' This method is called to create a challenge, and to get access to the claimed identifier that the internal webserver will have to verify
    ' Create and store away a challenge
    Dim challenge As New Utilities.Challenge
    challenge.Guid = System.Guid.NewGuid().ToString()
    HttpContext.Current.Session("guid") = challenge.Guid

    If providerEndpoint.PendingAuthenticationRequest IsNot Nothing Then
        challenge.Identifier = providerEndpoint.PendingAuthenticationRequest.ClaimedIdentifier.OriginalString
    End If
    ' Return a Plain Old CRL Object (POCO). This will be serialized into JSON
    Return challenge
End Function

<WebMethod()> _
Public Shared Function VerifyResponse(ByVal response As String) As Boolean
    ' This method will be called after the response returns from the internal webserver
    If providerEndpoint.PendingAuthenticationRequest IsNot Nothing Then
        Dim enc = New Utilities.SymmetricEncryption("my secret")
        ' Encrypt the claimed identity and the stored challenge, and see if it matches the response from the internal server
        If enc.Encrypt(providerEndpoint.PendingAuthenticationRequest.ClaimedIdentifier.OriginalString & "_" & HttpContext.Current.Session("guid")) = response Then
            ' If it matches we issue an authentication token
            FormsAuthentication.SetAuthCookie(providerEndpoint.PendingAuthenticationRequest.ClaimedIdentifier, False)
            Return True
        End If
    End If
    Return False
End Function

On the internal server the setup is similar, we accept the claimed identity, verify it against the identity of the authenticated user, and return a signed response.
Here we expose a method whose only purpose is to relay the challenge back to the serverside code

// Endpoint.aspx
// This is called by ASP.NET Ajax once the page is ready
function pageLoad() {
    // Set up a new easyXDM.Rpc object
    var rpc = new easyXDM.Rpc({}, {
        local: {
            authenticate: function (challenge, fn) {
                // Relay the challenge to the serverside code
                PageMethods.Authenticate(challenge, function (response) {
                    // Relay the response back to the OP
                    fn(response);
                });
            }
        }
    });
}

Here we extract the username from the claimed identifier and compare it to the known one. If it matches we return an encrypted response

'Endpoint.aspx
<WebMethod()> _
Public Shared Function Authenticate(ByVal challenge As Utilities.Challenge) As String
    ' This is called to check wether the claimed identifier matches the known one
    Dim claimedUserName As String = New Uri(challenge.Identifier).Query.Substring(4)

    If HttpContext.Current.User.Identity.IsAuthenticated Then
        Dim username As String = HttpContext.Current.User.Identity.Name
        username = username.Substring(username.IndexOf("\") + 1)
        If username = claimedUserName Then
            ' If it matches we encrypt the identifier and the challenge, and return the result as the response
            Dim enc = New Utilities.SymmetricEncryption("my secret")
            Return enc.Encrypt(challenge.Identifier & "_" & challenge.Guid)
        End If
    End If

    Return String.Empty
End Function

One of the interesting things here is how the instances of Utilities.Challenge is serialized and deserialized going from the OP’s server side code to the client side code, and again serialized and deserialized going from the internal webservers client side code to the internal webservers server side code. Like magic right?

(Of course, we could easily have used a couple of redirects instead of the server-client-client-server communication, but that wouldn’t have been as fun now would it 🙂

]]>
https://kinsey.no/blog/index.php/2010/07/09/how-to-set-up-an-ad-backed-openid-provider-without-direct-communication/feed/ 4
jsContract – Code contracts for Javascript https://kinsey.no/blog/index.php/2010/02/03/jscontract-code-contracts-for-javascript/ https://kinsey.no/blog/index.php/2010/02/03/jscontract-code-contracts-for-javascript/#comments Wed, 03 Feb 2010 21:01:10 +0000 http://kinsey.no/blog/?p=214 I have recently started using code contracts in one of my .net projects and I came to think that since most of the code I produce these days are in Javascript, why don’t I try it there to!

Well, easier said than done – there just is no decent frameworks for this.

During my searching I found some references to libraries such as Cerny.js and ecmaDebug, but these just didn’t make the cut  – they all required heavy (and hard to follow) restructuring of your code to make them work.

So what did I do? Well I made jsContract, a library that is clean and .. wait for it .. extremely easy to use!

If you want a quick view on what Code Contracts can give you, take a look at this example!

The following method comes from the sample code in the link above

    function _internalMethod(a, b){
        Contract.expectNumber(a);
        Contract.expectNumber(b);
        Contract.expectWhen(config.mode === "divide", b > 0, "Divisor cannot be 0");
        Contract.expectWhen(config.mode === "multiply", a > 0 && b > 0, "The multiplicands cannot be 0");
        Contract.guaranteesNumber();
        Contract.guarantees(function(result){
            return result > 0;
        }, "Result must be > 0");

        if (config.mode == "divide") {
            return a / b;
        }
        // At this point config.mode must be "multiply"
        return a * b;
    }

As you can see, the contract statements does not ruin the flow of the code, rather, it helps to document it.
By looking at the contract at the start of the method, you can instantly see what the method expects and what it will return.
This also helps you reduce code since you do not need to check for conditions that are not allowed according to the contract.

Postconditions

So, you might be wondering about how the Contract.guarantees methods work? How can a statement placed in the head of the method possibly check the return value of the method?
Well, the above code will actually not check the return value when run, but by running it through  Contract.instrument we can get code that will!
This is the output created by Contract.instrument for the above code

    function _internalMethod(a, b){
        arguments.callee.isInstrumented = true;
        /*preconditions*/
        Contract.expectNumber(a);
        Contract.expectNumber(b);
        Contract.expectWhen(config.mode === "divide", b > 0, "Divisor cannot be 0");
        Contract.expectWhen(config.mode === "multiply", a > 0 && b > 0, "The multiplicands cannot be 0");
        var __return = (function(a, b){
            if (config.mode == "divide") {
                return a / b;
            }
            // At this point config.mode must be "multiply"
            return a * b;
        }(a, b));
        /*postconditions*/
        Contract.guaranteesNumber(__return);
        Contract.guarantees(__return, function(result){
            return result > 0;
        }, "Result must be > 0");
        return __return;
    }

As you can see the code block has been wrapped in an anonymous function, the postconditions has been moved below this and has been rewritten so that they take the result as an argument.

We now have both pre- and postconditions checking our code!

The framework handles nested functions just as you would expect it to and the only real change to your code is the extra anonymous function that is inserted when the parser finds a postcondition in use.

But now you might be wondering, how do we get the instrumented code in to our applications?

For this you have several options

  • Use tools like this to convert the code for you before pasting it into a js file
  • Use it as a part of you build process for automated generation
    • a commandline tool will be available shortly
  • Use dynamic loading and instrumentation at runtime

The last option is only viable for development scenarios, but that is mainly when code contracts are needed anyways.
To load scripts dynamically you can either use your own AJAX code, or use the built in Contract.load method

The following code is taken from the  example available with the framework

var instrument = (location.search && location.search.indexOf("instrument=true") !== -1);
Contract.load("MyClass.js", instrument, function(){
    try {
        var myClass = new MyClass({
            mode: "multiply"
        });

        var result = myClass.publicMethod(34, 5, 3);
    }
    catch (ex) {
        alert(ex.message);
    }
});

This code loads regular or instrumented code depending on the query string.

Doesn’t it look cool?

Its available at github and will most likely be licensed with an MIT style license.

Anybody want to join in, maybe help with some documentation etc?

Drop me a note if so!

Note: This is the first draft, I started this project today.

The parser is quite naive and strings matching ‘function(‘ etc and unmatched { and } in comments  will break it. But this is a work in progress 🙂

Update 1 04.02: { and } in comments are now safely handled, and several small issues has been corrected.

Now I only need to validate that the functions the parser finds are not part of a comment.

Update 2 04.02: The parser has now been fixed, it now completely ignores anything in the comments. As far as I know this means that as long as the code validates the parser should be solid as a rock!

]]>
https://kinsey.no/blog/index.php/2010/02/03/jscontract-code-contracts-for-javascript/feed/ 11
easyXDM just became even easier to use! https://kinsey.no/blog/index.php/2010/01/02/easyxdm-just-became-even-easier-to-use/ https://kinsey.no/blog/index.php/2010/01/02/easyxdm-just-became-even-easier-to-use/#comments Sat, 02 Jan 2010 19:56:04 +0000 http://kinsey.no/blog/?p=201 To accommodate older browsers that does not implement the postMessage interface, easyXDM is able to fall back to using the URI fragment trick, and until now this has meant that the provided hash.html file had to be uploaded to the local domain (the ‘calling’ domain).

This seems to be a dealbreaker for many as they are unable to upload files to the server, either due to special systems, or because they just want to present an API in the form of ‘just include this javascript file’ etc..

With the new 1.5.5 release, this has all changed.

For scenarios where you do not want to upload the hash.html file, you can now point the local attribute to any file present on the local domain, like robots.txt or favicon.ico, and supply a readyAfter attribute with the number of milliseconds to wait before assuming the local file to be loaded and the library to be ready for interaction.

{
local: "/robots.txt",
readyAfter: 1000,
remote: "http://.........",
...
}

Update: Just released 1.6.0 which makes it possible to utilize the current document instead of loading a new one from the local domain. This makes it very easy to integrate, but does mean that you will be modifying the documents location when falling back to the HashTransport – and this might interfere with for instance history managers etc.

{
local: window,
remote: "http://.........",
...
}

The hash.html file is still the recommended approach for stable
implementations as it is unobtrusive and it guarantees that the library is indeed ready
when transitioning into a ready state.
Using hash.html also shortens the time needed to initialize easyXDM
as there is no need for the delay to give the local file time to
properly load.

All the different ways to set up easyXDM can now be viewed at http://easyxdm.net/wiki/Documentation.ashx

]]>
https://kinsey.no/blog/index.php/2010/01/02/easyxdm-just-became-even-easier-to-use/feed/ 4
Modifying privileges stored binary using ExtJs https://kinsey.no/blog/index.php/2009/11/17/modifying-privileges-stored-binary-using-extjs/ https://kinsey.no/blog/index.php/2009/11/17/modifying-privileges-stored-binary-using-extjs/#comments Tue, 17 Nov 2009 18:37:03 +0000 http://kinsey.no/blog/?p=180 In an earlier post I showed you how to use binary operators to store multiple privileges/settings in a single integer field. Now I will present to you a simple control for visualizing and modifying such a value.

Ext.namespace("Ext.ux");
Ext.ux.Privileges = function(config){
    var _formPanel = this;
    var items = [];

    for (var key in config.privileges) {
        if (config.privileges.hasOwnProperty(key)) {
            items.push({
                name: "privilege_" + config.privileges[key],
                fieldLabel: key
            });
        }
    }

    Ext.apply(config, {
        defaultType: "checkbox",
        items: items,
		/**
		 * Updates the form according to the current privileges
		 * @param {Integer} p The integer containing all set privileges
		 */
        setValue: function(p){
            var field, values = {}, privilege;
			for (var key in config.privileges) {
				// Loop over all the privileges, set the value to true if set
                if (config.privileges.hasOwnProperty(key)) {
                    privilege = config.privileges[key];
                    values["privilege_" + privilege] = (p == (p | privilege));
                }
            }
			// Update the form
            _formPanel.form.setValues(values);
        },
		/**
		 * Returns an integer representing all set privileges
		 * @return Integer
		 */
        getValue: function(){
            var p = 0, field, privilege;
			for (var key in config.privileges) {
				// Loop over all the privileges and see if it is set
                if (config.privileges.hasOwnProperty(key)) {
                    privilege = config.privileges[key];
                    field = _formPanel.form.findField("privilege_" + privilege);
                    if (field.getValue()) {
						// The privilege is set, lets add it to p
                        p = p | privilege;
                    }
                }
            }
            return p;
        },
		/**
		 * Resets the form
		 */
        clear: function(){
            _formPanel.form.reset();
        }
    });
    Ext.ux.Privileges.superclass.constructor.call(this, config);
};
Ext.extend(Ext.ux.Privileges, Ext.form.FormPanel);

Using the following code

var _pnlPrivileges= new Ext.ux.Privileges({
	height: 180,
	privileges: {
	    Read: 1,
	    Write: 2,
	    Create: 4,
	    Delete: 8,
	    List: 16,
	    SetPrivileges: 32,
	    Publish: 64
	}
});

you end up with something like this

privileges

The controll exposes its functionality in two methods, setValue and getValue – both of these should be easy to understand 🙂

]]>
https://kinsey.no/blog/index.php/2009/11/17/modifying-privileges-stored-binary-using-extjs/feed/ 2
Storing multiple privileges/settings in a single integer https://kinsey.no/blog/index.php/2009/11/17/storing-multiple-privilegessettings-in-a-single-integer/ https://kinsey.no/blog/index.php/2009/11/17/storing-multiple-privilegessettings-in-a-single-integer/#comments Tue, 17 Nov 2009 18:20:10 +0000 http://kinsey.no/blog/?p=168 In many applications you have the need to set users privileges , and while there are many ways to do so, I prefer to using a single integer value to store a users privileges on any single entity.

This has many advantages,

  • you only have a single value representing all privileges
  • you can add and remove available privileges without altering the schema/entity model/storage logic
  • checking for privileges are very simple

Now you might be wondering, how is it possible to store any number of privileges in a single integer?
One of the keys to doing this are the values that you assign each privilege, these must each be twice the previous value.

For example

  • Read = 1
  • Write = 2
  • Delete = 4
  • … = 8

To understand why we do it like this we need to take a look at the individual integers binary representation

1 = 00000001
2 = 00000010
4 = 00000100
8 = 00001000

Anyone see the pattern?

And if you were to sum some of these, say Write (2) + Delete(4)

00000010
+
00000100
=
00000110

Again, you see the pattern?

Each privilege is being stored as a single bit in the integer, and each bit can be checked against even if you add multiple values together.

So, now that we have some of the theory covered kiwi gambling, how do we utilize this?

If you have an integer you can easily check for any fraction using a simple statement

In JavaScript

var allPrivileges = 6;
var hasWrite = (allPrivileges  == (allPrivileges  | 2));

In VB.net

Dim allPrivileges As Integer = 6
Dim hasWrite As Boolean = allPrivileges = (allPrivileges Or 2)

Here we are using the bitwise operator | (or) to check that allPrivileges (6) binary or‘ed with 2 equals 6, meaning that 2 is a contained fraction of 6.

Now if you want to add a new privilege (or existing one) you just binary or the current integer with the new integer
In JavaScript

var allPrivileges = 4;
allPrivileges = allprivileges | 2;
// allPrivileges equals 6
allPrivileges= allprivileges | 2;
// allPrivileges still equals 6

In VB.net

Dim allPrivileges As Integer = 4
allPrivileges = (allPrivileges Or 2)
' allPrivileges equals 6
allPrivileges = (allPrivileges Or 2)
' allPrivileges still equals 6

Wasn’t that easy?

In an upcoming post I will show you a simple ExtJs control for visualizing and modifying a users privileges.

]]>
https://kinsey.no/blog/index.php/2009/11/17/storing-multiple-privilegessettings-in-a-single-integer/feed/ 10
How to restrict your web app to a single instance https://kinsey.no/blog/index.php/2009/11/15/how-to-restrict-your-web-app-to-a-single-instance/ https://kinsey.no/blog/index.php/2009/11/15/how-to-restrict-your-web-app-to-a-single-instance/#comments Sun, 15 Nov 2009 15:37:07 +0000 http://kinsey.no/blog/?p=157 When building complex web applications it is often necessary to restrict the user to keeping only a single instance open, and to do this you need to hire web development Salt Lake City to check for the presence of an existing instance, either directly or indirectly.

One way of doing this indirectly would be to set a cookie using javascript when the page loads and then use the unload event to remove the cookie. This means that as long as there is an instance open, the cookie will be set, and this can be tested for when the page loads.

window.onload = function(){
    if (document.cookie.indexOf("_instance=true") === -1) {
        document.cookie = "_instance=true";
        // Set the onunload function
        window.onunload = function(){
            document.cookie ="_instance=true;expires=Thu, 01-Jan-1970 00:00:01 GMT";
        };
        // Load the application
    }
    else {
        // Notify the user
    }
};

The disadvantage of doing it this way is that you increase the amount of data being sent to the server with each request as all cookies are being sent, but the cookie could be restricted to the documents path so that it would not be sent with non-matching requests.

The direct way would be to try to get a reference to the existing window using its name, but this does involve using window.open, which means the method could be blocked and rendered unreliable by popup blockers casinoluck. But then again, complex application often need popups to be enabled and one could use this to check for and alert the user about the popup blocker.

window.onload = function(){
    var doLoad = false, name = "unique_name", existing = window.open("", name, "");
    if (!existing) {
        // Notify the user about allowing popups
        alert("Popup blocker detected\nPlease allow popups for this domain.");
        return;
    }
    if (window === existing) {
        doLoad = true;
    }
    else {
        if (existing.document.title !== window.document.title) {
            // The referenced window is not an existing instance
            doLoad = true;
            existing.close();
            window.name = name;
        }
    }
    if (doLoad) {
        // Load the application
    }
    else {
        // Notify user
    }
};

Which way you choose is entirely up to you.
If you know any other ways, feel free to add it in the comments 🙂

]]>
https://kinsey.no/blog/index.php/2009/11/15/how-to-restrict-your-web-app-to-a-single-instance/feed/ 3
Upcoming book review – “Ext JS 3.0 Cookbook” https://kinsey.no/blog/index.php/2009/11/11/upcoming-book-review-ext-js-3-0-cookbook/ https://kinsey.no/blog/index.php/2009/11/11/upcoming-book-review-ext-js-3-0-cookbook/#respond Wed, 11 Nov 2009 14:03:35 +0000 http://kinsey.no/blog/?p=143 Ext JS 3.0 CookbookThe nice people at Packt Publishing has asked me to do a book review of  Jorge Ramons “Ext JS 3.0 Cookbook“.

According to the book description the following subjects will be covered

  • Work with different browsers, platforms, and the DOM, as well as determine and understand the different ExtJS data types
  • Create your own custom Ext JS data types as you extend their functionality
  • Build great-looking and friendly forms by using client and server-side field validation, form loading, submission, field customization, and layout techniques using different type of servers you can compare at servermania.com/kb/articles/hyperv-vs-vmware/.
  • Explore the different layouts provided by the Ext JS library as well as create your own, and understand their common uses
  • Display, edit, and group tabular data generated by the server using Grid Panels
  • Explore the advantages and the efficiency tradeoffs of widgets such as Combo boxes
  • Use the drag and drop features of the grid component, data editing with the new RowEditor Class, and the new lightweight ListView component
  • Explore multiple ways of displaying master-details relationships
  • Group components or information under the same container to build hierarchical views of information by using TabPanel components
  • Use patterns to build a au casinos online solid and flexible application architecture and implement additional design patterns such as auto-saving form elements, component state management, and code modules to build robust and flexible applications with Ext JS
  • Build your own custom components on top of the Ext framework and enhance the custom components created by the Ext JS users’ community

I’m looking forward to this as Ext and JavaScript are two things that I am quite passionate about 🙂

]]>
https://kinsey.no/blog/index.php/2009/11/11/upcoming-book-review-ext-js-3-0-cookbook/feed/ 0
Widget support added to easyXDM! https://kinsey.no/blog/index.php/2009/09/06/119/ https://kinsey.no/blog/index.php/2009/09/06/119/#comments Sun, 06 Sep 2009 14:37:39 +0000 http://kinsey.no/blog/?p=119 The newest version of easyXDM (v1.5.3) now includes two new classes, the easyXDM.WidgetManager, and easyXDM.Widget.

These make it extremely easy to make mashups based on the subscribe/publish architecture.

To read more about easyXDM check out this blog post.

The widget demo can be found at http://consumer.easyxdm.net/current/example/widgets.html,  and if you want to, just copy the code for the widget found here, modify the src for the scripts and save it to your own domain – you should now be able to add it from the WidgetManager!

The WidgetManager

To set up a page to contain widgets we need an instance of the WidgetManager:

var _widgetManager = new easyXDM.WidgetManager({
    local: "../hash.html",
    container: document.getElementById("widgets")
 });

And with the widgetmanager set up we continue by adding widgets by their url

_widgetManager.addWidget("http://provider.easyxdm.net/example/widget.html",{});

And thats it 🙂

The widgets

Creating a widget isn’t much more work

The following is a skeleton widget

var widget = new easyXDM.Widget({
    subscriptions: ["testtopic"],
    initialize: function(widget, widgetManager){
        // Set up the widget

        // Render the UI

        // Register the handler for incoming messages
        widget.registerMessageHandler(function(url, topic, data){
            // Do something
        });
    },
    initialized: function(widget, widgetManager){
        //This is called after the widget has been initialized by the widgetmanager
    }
});

To create a custom widget you only need to select the internet slots canada topics to subscribe to, build the UI, and handle the incoming messages the way you see fit.

To publish your own messages you simply use widget.publish  like this

widget.publish("position", {
    latitude: "60.378776",
    longitude: "5.337811"
});

and all subscribers will get this.

It’s that easy!

]]>
https://kinsey.no/blog/index.php/2009/09/06/119/feed/ 2
easyXDM – extremely easy cross-domain scripting https://kinsey.no/blog/index.php/2009/08/20/easyxdm/ https://kinsey.no/blog/index.php/2009/08/20/easyxdm/#comments Thu, 20 Aug 2009 15:03:02 +0000 http://kinsey.no/blog/?p=84 easyXDM is a javascript library that uses available techniques to provide a means of transporting messages and/or method calls between windows in different domains, in short, by-passing the same-origin policy and letting you call methods across the domain boundry.

This is perfect if you plan to provide a client-side API (e.g Facebook Connect) on your web site as you can expose a method in as little as 7 lines of code.

var remote = new easyXDM.Interface({}, {
    local: {
        doMagic:{
            method: _privateMethod
        }
    }
});

This can be consumed by a client by using

var remote = new easyXDM.Interface({
   local: &quot;../hash.html&quot;,
   remote: &quot;http://apiprovidersdomain.com/api.html&quot;
},{
    remote: {
        doMagic: {}
    }
});

and can then be called by using

remote.doMagic('argument1',2,function(result){
    alert(result)
}

In this CodeProject article I present an example on how easy it is to do this, and in the extensive documentation there are links to several demos showing everything from sending simple strings to letting two applications from different domains send arbitrary objects back and forth, even using older browsers like IE6.

The demos are repeated here

This library was earlier on called easyXSS, but due to the name being kinda ambiguous (someone say vulnerability), I decided to change it to easyXDM, short for easy cross domain messaging.

If you want to sneak a peek at the sourcecode, you can see the fully documented debug version here. The minified version weighs in at only 1.46KB gzipped.

The library is very flexible, allowing you you choose exactly how much of the work you want to handle yourself, the base functionality is transferring string messages.

Some of the features are

  • transport classes for transmitting strings
    • postMessage where supported OR
    • hash fragment using the resize event for invisible iframes
    • hash fragment using polling for visible frames
  • channel class for transmitting aribitrary data
  • interface class for setting up methods to be exposed/consumed
  • debug build with extensive logging for easy debugging
  • works in all browser (run the test suite)

The library also support both visible and invisible iframes, so you can either access the aussies casino online remote domain transparently, or you can expose the remote domains document for direct interaction (sign in etc.).

<ul>
<li>
<a href=”http://consumer.easyxdm.net/example/transport.html”>Sending plain string messages using the easyXDM.Transport.BestAvailableTransport class</a>
</li>
<li>
<a href=”http://consumer.easyxdm.net/example/data.html”>Sending data (objects)  using the easyXDM.Channel class</a>
</li>
<li>
<a href=”http://consumer.easyxdm.net/example/methods.html”>Exposing and invoking methods using the easyXDM.Interface class</a>
</li>
<li>
<a href=”http://consumer.easyxdm.net/example/xhr.html”>Calling an ajax method from the remote domain</a>
</li>
<li>
<a href=”http://consumer.easyxdm.net/example/index.html”>Bridging two web applications</a>
</li>
</ul>
]]>
https://kinsey.no/blog/index.php/2009/08/20/easyxdm/feed/ 88
easyXSS https://kinsey.no/blog/index.php/2009/06/24/easyxss/ https://kinsey.no/blog/index.php/2009/06/24/easyxss/#comments Wed, 24 Jun 2009 16:39:38 +0000 http://kinsey.no/blog/?p=44 Please see easyXDM for updated info!

I’ve just completed the first version of my cross-site scripting library easyXSS. It is available at http://code.google.com/p/easyxss/ under a MIT-license.

As it is now it supports simple messaging between windows of different domains, but it also supports proxying method calls and results between them making it well-suited for creating API’s.

I’ve prepared several examples and demo’s at http://code.google.com/p/easyxss/ and look forward to getting feedback!

To show you a quick example, here is the code needed to have a method ‘doMagic’ that is located on domainA available in a window from domainB.

This is placed in the document api.html at domainA

var channel = easyXSS.createChannel({
onReady: function(){
remote = easyXSS.createInterface(channel, {
local: {
doMagic: _privateMethodDoingMagic
}
});
}
});

and this is placed in the document at domainB

var remote;
var channel = easyXSS.createChannel({
local: &quot;/hash.html&quot;,
remote: &quot;http://domaina.com/api.html&quot;,
onReady: function(){
remote = easyXSS.createInterface(channel, {
remote: {
doMagic: {}
}
});
}
});

The medhod doMagic can now be called from domainB using

remote.doMagic('argument1',2,'three',function(result){
// Consume the result
});
]]>
https://kinsey.no/blog/index.php/2009/06/24/easyxss/feed/ 12