Saturday, January 17, 2009

OAM (Oracle Access Manager) and SharePoint Integration using custom HTTPModule

OAM's integration guide has step by step instructions on OAM and SharePoint integration. However, it works only if Active Directory is the User base for your SharePoint. If your OAM is having LDAP user base you are out of luck for a quick integration. Considering the LDAP as OAM backend and Active Directory as SharePoint user base, the integration still can be done by user data reconciliation from LDAP to Active Directory before the integration and a real time provisioning mechanism afterwards.

What if your organization decided to have SharePoint with LDAP instead of Active Directory? (Our organization has set up SharePoint server for external users (non - employee) who are not in our Active Directory. All our externals users are already available in Sun LDAP). In this unusual scenario, OAM cannot be integrated as it is. Here is how we did it.



Overview of the Integration
(1) User access the SharePoint URL.
(2) OAM's webgate (IIS plug-in/ ISAPI filter developed by Oracle responsible for checking Access policy and authentication etc) intercepts the URL and display our generic login page to user. User put his credentials. OAM webgate then validate it and allow the user to access SharePoint URL. It also set the SSO token in the browser so user can have single sign on with other applications.
(3) At this point SharePoint does not know about the authenticated user even our SharePoint already has LDAPmembership to the same LDAP that used by OAM.
(4) Now the HTTPModule will come to the rescue. It will

a. read the USER_ID from header (set by OAM after the authentication) and
b. create a GenericPrincipal for SharePoint.

fig1.JPG

The outcome of this model is,

(1) Share point will not display its login page to the user.

(2) The user -to-role assignment can still be possible inside SharePoint as SharePoint is also connected to the same LDAP that is used by OAM for authentication (which is also the user db for OAM) through LDAP-membership.
1. Writing an Http Module
My assumption is reader is familiar with OAM set up and knows how to set up a Webgate for IIS server that hosts SharePoint. LDAP set up. My other blog already detailed out on how to set up SharePoint with LDAP as user base. I will focus more on the point 4 mentioned in the overview section which require writing an HttpModule for SharePoint.
The HttpModule does the followings:-

1. Reads the USER_ID from header (set by OAM after the authentication). This header variable (say HTTP_OBLIX_UID) is set by OAM after successful authentication and authorization. This can be defined in 'authorization success event' in the SharePoint URL policy inside OAM.

2. Create a GenericPrincipal for SharePoint.
Step 1: Write an HttpModule Code
If you are a java guy like me, you need to learn little bit of c# programming. Install visual studio or Visual studio C# express as an IDE for compiling the code below.

using System;
using System.Security;
using System.Security.Principal;
using System.Web;
using System.Web.Security;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.IO;

namespace OamHttpModule {
class OamAuthenticator : IHttpModule {
public void Init(HttpApplication app) {
app.AuthenticateRequest +=(new EventHandler(this.Application_AuthenticateRequest));
app.PreSendRequestHeaders +=(new EventHandler
this.Application_PreSendRequestHeaders));
}

private void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (HttpContext.Current.Request.Headers["HTTP_OBLIX_UID"] != null)
{
NameValueCollection coll = HttpContext.Current.Request.Headers;
string midmsUser = coll["HTTP_OBLIX_UID"];
HttpApplication app = (HttpApplication)sender;

string[] roles = new string[1];
roles[0] = "viewer";
GenericIdentity id = new GenericIdentity(midmsUser, "Forms");
GenericPrincipal p = new GenericPrincipal(id, roles);
app.Context.User = p;
}
}
private void Application_PreSendRequestHeaders(object sender, EventArgs e) {
HttpApplication app = (HttpApplication)sender;

if (app.Response.RedirectLocation != null) {
if (app.Response.RedirectLocation.Contains("AccessDenied.aspx?Source") &&
app.User.Identity.Name == "Visitor") {
app.Response.Redirect("/_layouts/login.aspx?ReturnUrl=" + app.Request.RawUrl);
}
}
}

public void Dispose() {
}
}
}

Now, create a strong name key for this module. This key will be used later in webconfig, so SharePoint will honor this code. The snaps shot is taken from Visual C# express studio. Select the Project Properties :-


fig2.JPG


Enter the KeyName here.



From the dropdown select new and enter the Key file name (say OamHttpModule) in the popup box. Next build the solution. Building the solution will result a .dll file (say OAMHttpModule.dll). Now register this key in Window Assembly. From command prompt type "assembly". Drop the OAMHttpModule.dll to assembly window (shown below) from the solution area.


Right click to get "OamHttpModule" properties , note down the generated public key token.


This Public key token value will be used in webconfig file.

Step 2 : Web.config Changes
We have completed building the OAMHttpModule.dll. Let's include it webconfig so SharePoint will able to access it.
Step a : Include HttpModule in webconfigAdd HttpModule class name under <httpModules> tag

<httpModules>
:
:
<add name="OamAuthenticator" type="OamHttpModule.OamAuthenticator,
OamHttpModule,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=57773ac73696c406" />
</httpModules>

Mention the Public Key Token copied from Assembly window. SharePoint will not allow this code to run inside without this public key token.

Step b: Change the error display setting in webconfigCHANGE under <SharePoint><SafeMode… tag

<SafeMode MaxControls="200" CallStack=" false " DirectFileDependencies="10" TotalFileDependencies="50" AllowPageLevelTrace="false">
TO
<SafeMode MaxControls="200" CallStack=" true " DirectFileDependencies="10" TotalFileDependencies="50" AllowPageLevelTrace="false">

CHANGE under <system.web> tag

<customErrors mode="On" />
TO
<customErrors mode="Off" />

Step c: Change the trust level in webconfig so the HttpModule can be executed
In the web.config

CHANGE under <system.web> tag
<trust level="WSS_Minimal" originUrl="" />
TO
<trust level="WSS_Medium" originUrl="" />

Restart the IIS server.
2.OAM IntegrationI am assuming that you are familiar with Webgate setup for IIS server. After completing the Webgate set up for IIS (that hosts SharePoint), define appropriate URL policy for SharePoint on OAM access manager.

Let's test the setup.

Step 1: user enters the SharePoint URL http://mde-mossdev:87/ protected by Oracle's form authentication.



Step 2: The webgate then intercept the URL and check for the authentication policy. Since the authentication policy is defined as a form, it displays the configured form based authentication screen. User put his credentials; webgate then validate it and allow the user to access SharePoint URL.

Step 3: At this point our custom HTTPModule read the USER_ID from header (set by OAM after the authentication) and creates a GenericPrincipal for SharePoint and set the SSO token in the browser so user can have single sign on with other applications. Below is the screen, which shows the SP home page with the above said user already, logged in (see "Welcome Celuser1" in the screen top right hand side corner).



Yep, we are done ….

10 comments:

  1. If I read correctly you are creating a FBA. FBA loses office integration.

    ReplyDelete
  2. You have to keep the option "Sign me Automatically" checked all the time to make FBA works with Office integration.

    ReplyDelete
  3. I have done the same and using FBA. However, after login to OAM, I still get FBA login screen and it doesn't log me in using my credentials when I have given appropriate permissions.

    ReplyDelete
  4. I have done integration between OAM and Sharepoint. Authentication and Authorization is working fine so far. But user is unable to retrieve all the roles he has access to. For Example, on the home page, the user is unable to see site actions link and when tried to click on sign in as different user/help link it says 401 unauthorized. Any ideas?

    ReplyDelete
  5. Where the roles are defined ? inside the Sharepoint ?
    I have not done fine grained authorization inside sharepoint using OAM. I still have the roles defined inside sharepoint and OAM is just doing authentication. You have to provision the Sharepoint role to OAM's LDAP, if you would like to do a coarse grained authorization to Sharepoint site thru OAM.

    ReplyDelete
  6. Great work ... nice reading .... nice workaround
    Regards
    VM

    ReplyDelete
  7. Hi Pankaj,
    I did the same, but I am getting the windows logon screen after successfully login through OAM.Do I have to do something else to get rid of the second windows logon screen and use the generic user we created in http module.
    Thanks,
    Hemant

    ReplyDelete
  8. Do you know if this will work with Sun Access Manager integrating with Sharepoint 2007. Sharepoint is running on IIS7.5 and windows 2008r2.
    Thanks.

    ReplyDelete
  9. Also along with Sharepoint is running on IIS7.5 and windows 2008r2 I already tried doing integration with Policy agent 3.0-01 but getting access denied. At this point I don't have any custom code.
    Thanks,
    Neha

    ReplyDelete
  10. Can you please re-post the image of "Enter KeyName Here"

    Appreciated

    ReplyDelete