RSS

Category Archives: Extending K2

Hosting K2 forms in iFrames

Sometimes you want to host a K2 form in another html page. SharePoint is a great example of this. The issue is that you want it to be nice and seamless with no scrollbars. Using JQuery you can resize the frame to fit the contents, but thanks to security requirements the hosting page is not allowed to access the contents of the page it’s hosting. This means your hosting page can’t access the height of the contents, so you don’t know how to resize the frame.

Luckily there’s a very simple way to accomplish this.

Let’s say you have a SharePoint page that needs to host a K2 SmartForm. Your html would contain something like this:

<iframe id="k2iFrame" style="width: 100%;" src="https://k2.smartflow.solutions/Designer/Runtime/Form/Home" width="300" height="150" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>

If you run it like this, you’re going to get a frame with the default height and most of the form is cut off. Here’s the solution:

Step 1: Have the K2 form send it’s height to the parent

  1. Add a data label to the form and check the ‘Literal’ button
  2. Add a rule on the form that executes when the form is initialized
  3. In the rule, transfer the following to the data label:
    <script>
    $(document).ready(function() {
    var body = document.body,
    html = document.documentElement,
    height = Math.max(body.scrollHeight, body.offsetHeight,
    html.clientHeight, html.scrollHeight, html.offsetHeight);
    if (parent.postMessage) {
    parent.postMessage(height, "*");
    }
    });
    </script>

Step 2: Add the event handler on the parent page

<iframe src="https://k2.smartflow.solutions/Designer/Runtime/Form/Home" id="k2iFrame" style="width: 100%;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0" vspace="0" hspace="0"></iframe>
<script type="text/javascript">
var k2Resize_resize = function (event) {
var k2iFrame = document.getElementById('k2iFrame');
if (k2iFrame) {
k2iFrame.style.height = event.data + "px";
}
};
if (window.addEventListener) {
window.addEventListener("message", k2Resize_resize, false);
} else if (window.attachEvent) {
window.attachEvent("onmessage", k2Resize_resize);
}
</script>

That’s it. Obviously this won’t handle resizing forms, but this should get you started. Hope that helps.

 

Pass through authentication (AKA the end of kerberos?)

K2 released pass through authentication in 1290 (the version, not the year) and many people are hailing it’s coming as the end of Kerberos trouble. In many ways they are correct, but not all. This is a VERY brief outline of what pass througth authentication is (and isn’t) which will hopefully let you decide if this is something you need to consider in your environment.

Kerberos, as I’m sure you know, is a black art which is only understood by a select group of monks who live in complete isolation and probably charge ridiculous consulting rates. For the rest of us, we have to make do with hours (or days) of fighting with Kerberos before we get a fully working architecture. In simple terms, when you make a call from one server to another your credentials are passed on to the next server so that the next server knows who you are. For example, if a user (named James) makes a request which hits your web server and your web server needs to make a call to your application server, this works just fine because your application server knows the call originated with James. However the default way of passing these credentials on (NTLM) only passes them on for 1 ‘hop’. In the example I gave, if the application server needed to make a call to a database server the database server wouldn’t have a clue who you the call originated with, and instead of the caller being identified as James the caller would be anonymous. Kerberos solves this issue by allowing your credentials to be passed along as many hops as you like.

K2’s pass through authentication lets you bypass the need for Kerberos by basically doing the following:

  1. User makes a call to the web server which in turn makes a call to the K2 server.
  2. The K2 server needs to make a call to the database. However, when it does the database server identifies the user as ‘anonymous’.
  3. K2 realises that Kerberos isn’t enabled, so it tells the database server who the user is and then makes the call again, and voila – no more anonymous user.

This is great, but you need to realise that this only works for servers which have k2 components on them. If there are 2 hops anywhere in the call stack and there are no K2 components, then pass through authentication will (obviously) not work and you’ll need to have Kerveros enabled anyway.

I have confirmed that this extra bit of handshaking will only happen when you’re opening a connection – once the connection is open there’s no extra chatter to slow things down.

p.s. a hop is actually across a security boundary, not just across a server, but for the sake of illustration it makes sense to call a server a hop.

 
2 Comments

Posted by on April 20, 2011 in Extending K2, Security

 

Configuring and Deploying a Custom Security Provider

There are times when AD just isn’t going to work for you and you need to use your own authentication system. K2 provides an excellent pluggable architecture which you can extend to allow you to do this. Writing a customer security provider is not a challenging task at all – there are some interfaces you need to implement and that’s about it. Once you’ve done that you need to deploy your security provider to each K2 server, configure it and turn your hard work into a security label. This article is focused on deploying and configuring a security label.

(If you would like an article on creating a custom security provider, contact me. If there’s enough interest I’ll put one together).

Before you go about deploying your security provider there are some properties we need to check up on in your Visual Studio project:

  1. Make sure your class is strongly typed.
  2. Make sure the assembly is signed by doing the following:
    1. Right-click your project and select properties
    2. Select the ‘Signing’ tab
    3. Check ‘Sign the assembly’
    4. In the drop down, select <New…>
    5. Type in a name (you don’t need it to be password protected)
  3. Get your assembly’s public key token:
    1. Run the Visual Studio Command Prompt and navigate to the bin/Debug folder where your security provider dll is.
    2. Run the following command: sn.exe -Tp MySecurityProvider.dll

Now you’re ready to deploy your security provider. From a high level perspective, here’s what you’re going to do:

  1. Copy the dll(s) to the K2 server
  2. Edit the K2HostServer.config file
  3. Run a SQL script to register and configure the security label
  4. Restart K2

1. Copy the dll(s) to the K2 Server

Build your project and then locate the resulting dll in your bin\Debug folder. Copy this dll (and the pdb file as well) and paste it into your K2 server’s security provider folder (by default it is [C:\Program Files (x86)\K2 blackpearl\Host Server\Bin\securityproviders])

2. Edit the K2HostServer.config file

Set the useassemblyregistration appSetting in the [K2 Install]\Host Server\bin\K2HostServer.config file as follows:

< appSettings >
...
< add key=”useassemblyregistration” value=”true” / >
...
< /appSettings >

3. Insert some entries into K2’s databases

Before you can run the SQL and register your security label, make sure you have the following information on hand:
Your assembly’s public key token
Your security provider dll filename (without the .dll of course).
Your security provider’s fully qualified name (ProjectName.ClassName).
What you want to call your security label.

Open SQL Management Studio and run the following SQL:

-- Replace the following text with your values. You don't need to add any apostrophes - if I haven't included it you don't need it.
-- SECURITYPROVIDER_FILENAME: Your security provider dll filename (without the .dll of course).
-- ASSEMBLY_TOKEN: Your assembly’s public key token.
-- SECURITYPROVIDER_FQN: Your security provider’s fully qualified name (ProjectName.ClassName).
-- LABEL_NAME: What you want to call your security label.

USE K2HostServer
GO

DECLARE @UNIQUE_ID UNIQUEIDENTIFIER
SET @UNIQUE_ID = NEWID()

-- Step 1: Add the dll to the Assembly Registration table.
INSERT INTO [dbo].[AssemblyRegistration]
	([AssemblyID]
	,[AssemblyName]
	,[PublicKeyToken]
	,[Enabled])
VALUES
	(NEWID()
	, 'SECURITYPROVIDER_FILENAME'
	, 'ASSEMBLY_TOKEN'
	, 1)

-- Step 2: Add the security provider to the list of available providers.
INSERT INTO [dbo].[SecurityProviders]
	([SecurityProviderID]
	,[ProviderClassName])
VALUES
	(@UNIQUE_ID
	, 'SECURITYPROVIDER_FQN')

-- Step 2: Create a security label by configuring an instance of the provider you just added
INSERT INTO [dbo].[SecurityLabels]
	([SecurityLabelID]
	,[SecurityLabelName]
	,[AuthSecurityProviderID]
	,[AuthInit]
	,[RoleSecurityProviderID]
	,[RoleInit]
	,[DefaultLabel])
VALUES
	(NEWID()
	,'LABEL_NAME'
	,@UNIQUE_ID
	,''
	,@UNIQUE_ID
	,''
	,0)
GO

If you ever want to roll your system back and remove the security label you need to stop the K2 service, run the following SQL and then start K2 up again.

-- Replace the following text with your values. You don't need to add any apostrophes - if I haven't included it you don't need it.
-- ASSEMBLY_TOKEN: Your assembly’s public key token.
-- SECURITYPROVIDER_FQN: Your security provider’s fully qualified name (ProjectName.ClassName).
-- LABEL_NAME: What you want to call your security label.

use K2HostServer
delete from AssemblyRegistration where PublicKeyToken = 'ASSEMBLY_TOKEN'
delete from SecurityLabels where SecurityLabelName = 'LABEL_NAME'
delete from SecurityProviders where ProviderClassName = 'SECURITYPROVIDER_FQN'
 
Leave a comment

Posted by on April 4, 2011 in Extending K2, Security