jump to navigation

ASP.Net Windows Authentication: Authorization by Group January 20, 2011

Posted by codinglifestyle in ASP.NET, C#, CodeProject, Security.
Tags: , , , , , , , ,
4 comments

Often in this line of work it’s the simple things that take the longest time. A seemingly simple question came up yesterday on how to lock access to a customer’s website to a specific Windows group. There are a couple of simple gotchas worth documenting in a relatively simple solution presented below.

First, let’s start with the basics. By default ASP.NET executes code using a fixed account. Assuming you are using IIS 6 or greater, the identity is specified in the application pool. However, if we set impersonation to true ASP.NET assumes the user’s identity. Combined with Windows authentication, our code will run within the context of the user’s Windows identity.

To achieve this, in the web.config we set authentication to Windows and impersonate to true. Now we will have an authenticated Windows user, we next need to focus on authorization or what rights and restrictions apply to that user. Our requirement in this case is simple, if you belong to a specified Windows group you have access, otherwise you do not. When using Windows authentication, roles within ASP.NET translate to Windows groups. To allow a specific Windows group, allow that role within the authorization tag in the web.config. We could add additional lines to allow further roles or users. In this case, we simply want to deny everyone else, so notice the deny users * wildcard below.

Web.config

<system.web>
<authentication mode=Windows/>
<identity impersonate=true/>
<authorization>
<allow roles=BUILTIN\Administrators/>
<deny users=*/>
</authorization>
</system.web>

Here’s a handy tip: When testing use the whoami command. This will show you all the groups the logged in user belongs to which is handy when testing.

If you are making modifications to local or domain groups for the current user (probably your own account for testing) ensure that you see the group information you expect with the whoami /groups command. If you have just added yourself to a test group, remember that you must logout and log back in to see these changes.

Now you could stop here, you’re website is secured. However, if you do the user will get IIS’s rather nasty 401 error page. It would be much nicer to show our own custom error or possibly redirect the user to a registration page of some sort. The problem is we’ve restricted the entire website, so even a harmless error page requires authorization. What we need is an exception, which we can do be adding the snippet below the system.web closing tag.

<location path=AccessDenied.aspx>
<system.web>
<authorization>
<allow users=*/>
</authorization>
</system.web>
</location>

What this has done is specify a specific file to have different authorization requirements to the rest of the website.  Optionally we could have specified a directory where we can place CSS, image files, a masterpage, or other resources we may want to allow access to.  In this example, we are only allowing all users to see the AccessDenied.aspx page.

You might think that using the customErrors section in the web.config would be the last step to redirect the user to the AccessDenied.aspx page. However, IIS has other ideas!  IIS catches the 401 before it ever consults with ASP.Net and therefore ignores your customErrors section for a 401. Use the below workaround in your global.asax.cs to catch the 401 and redirect the user to our error page before IIS has a chance to interfere.

Global.asax.cs

protected void Application_EndRequest(Object sender, EventArgs e)
{
if (HttpContext.Current.Response.Status.StartsWith(“401”))
{
HttpContext.Current.Response.ClearContent();
Server.Execute(AccessDenied.aspx);
}
}

If we have further security requirements, we can do further checks any time by getting the IPrincipal from Page.User or HttpContext.Current.User. We could enable a button in our UI with a simple statement such as:

adminButton.Enabled = Page.User.IsInRole(@“domain\domainadmins”);

While the solution seems obvious and elegant, it took a bit of searching and playing to get it to work just right. There are other ways of centrally enforcing security such as Application_AuthenticateRequest in global.asax. However in this case it is far more configurable to take full advantage of the settings available to us in the web.config.

Tech-ed 2008 November 17, 2008

Posted by codinglifestyle in ASP.NET, C#, IIS, jQuery, Parallelism, Security, SharePoint, Visual Studio 2010.
Tags: , , , , , , , , , , , , , , , , ,
3 comments

Last week I had the opportunity to attend TechEd 2008.  I have compiled a set of notes from the keynote and sessions I attended below.  Most of the information presented at these conferences is not really instructive for addressing today’s problems but talks about future problems and the technologies we will use to address them.  There are some interesting technologies coming down the pipe in the not so distant future and these notes may provide you with enough information to google more information about the topics which interest you.

 

I skipped a lot of older information about the VS2008 release, C# v3.0, and Linq which can all be found here.

 

Keynote

·         Testing Activity Center application

o   Pillar: No more no-repro

o   Generate test cases that tester can click off

o   Bug recording including video, call stack, system information

o   Generate a bug integrated in to Team System

§  Can start up debugger and reproduce tester’s scenario

§  Captures line of code, call stack, everything

·         Code buffering

o   Method shows history of changes (graphically too)

o   Integrates SCC versions in to IDE

·         MVC design pattern

o   Model                   =              data

o   View                     =              web page / UI

o   Controller             =              logic

·         SharePoint Integration

o   Server explorer includes lists, ect

o   Webpart template automatically contains ascx control for design support

o   SharePoint LINQ

o   List Event wizard

§  Auto-generate XML for site def??

·         Performance Profiler

o   Pillar: Leverage multi-core systems

o   See which method is taking time and core utilization

§  Graphically shows core usage including drill down

·         Will help with concurrency, deadlock debugging, ect

VS2008 Service Pack 1 Overview

·         ADO.NET Entity Framework release

o   Very similar to Linq To SQL

o   Generate data model

§  conceptual model static (actual db) model

o   Data Services

§  Data centric abstraction over web services (WFC)

§  Exposes and takes IQueryable so datasets very easy to work with in a LINQ like way

§  Routing lets URI act like a Linq query

·         http://Root/my.svc/Customers/35/FirstName

o   Dynamic Data

§  Given a data model will create aspx accessibility to defined objects

·         Security: all objects off by default but can dynamically access entire data model

·         Allow CRUD access via ASPX templates applied to all objects

o   CRUD = create, read, update, delete

o   Can create individual page for certain object

o   Can customize template to affect all objects

·         Ajax / other enhancements

o   Ajax

§  History Points

·         Addresses problem that users lose ability to hit back button

§  Script combining

·         To improve performance allows to dynamically combine js libraries

o   Improves javascript intellisense

o   Improves web designer performance (bugs/regressions addressed)

C# v4.0

·         History

o   V1 – Managed Code big emphasis

o   V2 – Generics; finished the language

o   V3 – LINQ

·         Pillars

o   Declarative programming: we are moving from “what?” to “how?”

§  LINQ is an example of this

o   Concurrency: Some of the parallelism extensions we will be getting

o   Co-Evolution: VB and C# will more closely evolve together vs. Features hitting languages at different times

o   Static vs. Dynamic Languages: aren’t necessarily a dichotomy

§  Static: C++, C#, VB – anything compiles

§  Dynamic: IronRuby, IronPython, Javascript

·         New keyword: dynamic

o   Call any method of a dynamic object and the compiler won’t complain

§  No intellisense possible

§  Will call during runtime

§  i.e.

·         dynamic calc = GetCalculator();

·         calc.Add(10,20);   //We know nothing about calc object

§  Lots of power to  be explored here

o   Optional Parameters

§  Like in C++ (and apparently VB)

§  Named parameters

·         Can also skip optional parameters

·         Public StreamReader OpenTextFile(string sFile, bool bReadOnly = true, int nBufferSize = 1024);

·         sr = OpenTextFile(“foo.txt”, buffersize:4096);

o   COM Interoperability

§  No more “ref dummy”!

·         Will get: doc.SaveAs(“Test.docx”);  //Winword saveas

·         Versus:   doc.SaveAs(“Test.docx”, ref dummy, ref dummy, ref dummy, ref dummy, ref dummy, ref dummy, ref dummy, ref dummy, ref dummy, ref dummy, ref dummy, ref dummy, ref dummy, ref dummy);

§  Automatic dynamic mapping so less unnecessary casting

§  Interop type embedding

·         No more bringing in PIA

o   Safe Co and Contra-variance

o   Compiler as a service

§  Compiler black box opened up to be used and extended

§  In example created a command window with C#> prompt

·         Was able to define variables, functions, ect like in IronPython

Ajax v4.0

·         Introduction

o   Web app definition

§  Web site is a static collection of pages (such a BBC news)

§  Web application is something which replaces a traditional windows app

o    Traditional Server-Side ASP.NET vs. AJAX

§  Pros

·         Safe: Guaranteed browser compatibility

·         Powerful: All the power of a .NET language in code-behind

§  Cons

·         Response: User must wait for postback

·         Performance: All page content rendered for each interaction

·         Update Panels: Use Wisely

o   An update panel uses sneaky postbacks so while it looks better it is still as bad as traditional server side asp.net

o   Don’t wrap an entire page in an update panel

§  Wrap the smallest region required

§  Use triggers to set what controls will fire a sneaky postback

o   Turn ViewState OFF

§  Down the line this will not be on by default

§  We often send a lot of unnecessary information over the wire in ViewState

·         Ajax Calls (Services)

o   Consider using an Ajax control to update data as needed

o   Calling a web service from javascript is not considered dangerous or bad practice

o   Example

§  Have a datagrid with postback bound to a dropdown list.  Instead of a postback on ddlist use Ajax call

·         Instead of a datagrid use a straight html table

·         Via script we make a call to the web service

·         Use stringbuilder to format return to build up new rows

§  Kinda horrible!  Too much mixing of mark-up and script

·         Client Side Controls

o   Clean way of separating Ajax related script from the web page

o   Allows you to bind to Ajax calls in a template way

o   Example

§  From above we now separate js in to a client side control which is now cleanly referenced on our web page

·         Declarative Client Side Controls

o   “X” in XML stands for extensible; but not often extended!

o   Use XML to bring in namespaces like System and DataView

o   Can define a datagrid purely in html by adding attributes to the

tag in a table

·         Fail over

o   Problem with Ajax is not it is not always supported for reasons of accessibility, search engines, or disabled javascript (mobile devices)

o   Does require double implementation of Ajax and traditional solution but it is an option when needed

·         New features in SP1

o   Back button support!

§  As of VS2008 SP1 Ajax now has back button support

§  ScriptManager property EnableHistory=true and onNavigate event

§  AddHistoryPoint(key,value);

§  AddHistoryPoint(key,value,“Text seen in back button history instead of url”)

§  Process

·         Enable history and add event

·         When page event fires store value (index, ect) with AddHistoryPoint() in provided history cache

·         Use history event to set page back up with value retrieved from HistoryEventArgs

o   Example: set a form to display an item from the last selected index

o   Script Combining

§  Combine scripts for better performance

·         Example showed initial 15sec down to 3

§  Must tell ScriptManager all libraries and it will combine/compress them in to one server call

§  Must explicitly tell which scripts to use – even separate AJAX libraries

·         ScriptReferenceProfiler

o   Free webcontrols which will tell you all the libraries a page uses to make the above less painful

·         Factoids

o   Ajax initiative started to address Outlook Web Access (OWA); a good example of a web application

o   Script Manager is just a way to make sure the page includes the Ajax javascript libraries

§  Ajax script commands prefixed with $

·         $get(“my id”) looks to be handy

§  Can dynamically add event handlers in javascript using Ajax js library

·         $addHandler($get(“dropdownlist1”), “change”, myFunc);

·         Cool “must have” tools

o   Fiddler (www.fiddler2.com)

§  Shows response time, requests/responses, statistics

§  Tip: must place a dot in uri for Fiddler to capture localhost

·         http://localhost./default.aspx

o   Firebug – Firefox extension

 

Visual Studio Tips & Tricks

·         Ppt slides: http://code.msdn.microsoft.com/karenliuteched08

·         A lot more keyboard shortcuts: http://blogs.msdn.com/karenliu/

·         MS and partnered with DevExpress which is offering CodeRush Express for free

o   Required for a lot of the shortcuts and refactoring shown

·         Editing

o   Tools>Options>Editors>C#>Formatting>Set Other Spacing Options>Ignore Spaces

o   Keyboard tricks

§  Ctrl M,O               Toggle collapse all

§  Ctrl M,M              Expand region

§  F12                         Go to definition

§  Shift F12              Final all references

§  Ctrl Shift F8        Jump up Go to definition stack

§  Ctrl [ or ]              Jump between brackets

§  Ctrl Alt = or –      Smart Select

§  Ctrl .                      See smart tag (Implement a missing function, add using statements)

§   

o   Snippets

§  Lots of boilerplate goodies are there.  Really need to start using them

·         Ctor

§  Lots more smart HTML snippets coming

·         Debugging

o   Step OVER properties (r-click at breakpoint to check option)

o   Step into Specific – list of all functions down the chain you can jump to step in to

o   Tools

§  Tinyget – mini stress test

§  Adphang – get memory dump of w3wp

§  Windbg – open dump

·         Loadby SOS mscorwks

o   Need sos.dll for windbg to interpret stack

·         Deployment

o   Web.config transform for release, uat, ect

o   Powerful web deployment publishing options

§  Http, ftp, fpse

§  Msdeploypublish

·         New MS protocol for host supporting includes database, iis settings, access control lists (ACL), ect

·         Free test account at http://labs.discountasp.net/msdeploy

·         Other

o   www.VisualStudioGallery.com  – IDE extensions gallery

§  PowerCommands for VS08

o   VS2008 SDK application

§  Samples tab

·         Click to open sample straight in VS ready to go

Silverlight v2 101

·         XAML

o   A subset of WPF

o   Read-only designer view

§  Must edit  XAML by hand

§  Proper designer on the way

o   Can at least drag XAML text templates for many controls

·         Silverlight Controls

o   Greatly extended in Silverlight v2

§  Visit: www.silverlight.net for a demo

§  Most of what you’d expect in ASP.NET is available in Silverlight

o   Of Note

§  StackPanel

·         Previously on Canvas available requiring static x,y position designation

·         Operates like a panel with z-order

·         Security

o   Lives in a sandbox which can’t be extended for security reasons

o   There are ways to safe access local (isolated) storage, have a file dialog, sockets, cross domain access

·         Nifty

o   Can easily stream media content with one line of XAML

o   Can easily spin any element

Parallelism

·         Introduction

o   Sequential performance has plateaued

o   When we have 30 cores this may lead to dumber cores where we have a situation that today’s software runs slower on tomorrow’s hardware

o   Need  to start thinking about parallelism

§  Understand goals vs. usage

§  Measure existing performance.  VS2010 has tools to do this

§  Tuning Performance

·         Typically we start with sequential programming and add parallelism later

·         VS2010 has Profiler tool for tuning performance

§  Identify opportunities for parallelism

§  Use realistic datasets from the outset; not only on site with the customer

§  Parallelize only when necessary, but PLAN for it as it does introduce race conditions, non-determinism, timing issues, and a slew of other potential bugs

§  Once code is written for parallelism it can scale to any size automatically without any code changes

·         New technologies to help

o   Parallel API

§  Task

·         Like a thread but more optimal with a richer API

o   Has a value for threads which must return a value

§  Accessing the value automatically the same as Thread.Join or Task.Wait

§  ThreadPool

·         Just pass a delegate and let Microsoft worry about the hardware and how to best allocate and spawn threads

·         The ideal number of threads = number of cores

§  TimingBlock class makes it easy to test performance

·         No more: (end time – start time) / 1000

§  Decorate code w/ measurement blocks which appear in Profiler

o   Parallel Extensions

§  First class citizen in VS2010 (SDK today?)

§  Parallel.For and Parallel.ForEach

·         Still need to use critical sections around shared resources inside loop

·         Tip: Best practice is to parallelize the outer for loop only

·         Automatically adds measurement blocks to profiler to see results

§  Parallel.Invoke

§  Parallel extended IEnumerable to perform queries much faster

·         var q = from n in arr.AsParallel() where IsPrime(n) select n;

§  Task group

·         i.e.  For a quick sort instead of using a recursive algorithm use task groups to leverage parallelism with little change to code

o   Debugging – Parallel Stacks

§  Richer API to display tasks or threads and view a holistic mapping of their execution

o   Tools

§  Performance Wizard

·         CPU sampling, timing, ect

§  Profiler

·         Thread Blocking Analysis

o   Shows each thread’s parallel execution revealing race conditions affecting performance

§  Displays information about critical sections in tooltip

§  Can show dependencies for resources/locks across threads

jQuery

·         Ships in future VS but available now

·         Will not be changed by Microsoft but will be supported so we can use it with customers requiring support

·         VS intellisense available from jquery.com

·         Selectors

1.       $(“:text”)             tag          Select all text boxes

2.       $(.required)       class      Select any element with this class tag

3.       $(“#name”)        id            Select with this ID

·         Animations

1.       $(…).Show()

2.       $(…).Hide()

3.       $(…).slideDown()

4.       $(…).slideUp()

5.       $(…).fadeIn()

6.       $(…).fadeOut

7.       Massive open source libraries with hundreds more

§  Plugins.jquery.com

MVC 101

·         MVC

o   Controller (input) pushes to model and view

o   View (UI)

o   Model (logic)

·         An alternative, not replacement, to traditional web forms

·         Easier to test

o   No dependencies on request/response or viewstate as this everything is explicit and therefore testable

·         No server side controls (or designer support), postbacks, or events.

o   Think back to classic ASP

o   What is all this by-hand crap?  XAML (WPF and Silverlight) is only notepad as well

·         Action, instead of event, fires not in View but in the Controller. 

o   The View, aka aspx page, has no code behind.

·         In Controller can define a action and use wizard to create it’s view (web page)

·         ViewUserControl is a collection of html and inline asp which is reusable

IIS v7

·         Modules

o   ASP.NET managed HttpModules can be plugged in directly to IIS v7

§  No more unmanaged ISAPI filters

o   Modules can be managed within IIS v7 Manager

o   Configuration for modules can be exposed through manager

§  Customer WinForm configuration can also be exposed

·         Config

o   No more meta-base

§  All settings exists in central applicationHost.config – similar to a web.config

·         C:\windows\system32\inetsrv\config\schema

§  Can share IIS config for farm scenario

o   www.iis.net contains a configuration pack which allows you to show the config file within the IIS manager

Security

·         Concept of Security Development Lifecycle (SDL)

·         Threat Modelling – package available for formalized  security reviews

o   Talks about prioritizing risks

·         Multi-Pass Review Model

o   1 – Run fuzz and code analysis tools

o   2 – Look for ‘patterns’ in riskier code

o   3 – Deep review of riskiest code

·         Golden rule: What does the bad guy control?

o   What if he controls x & j (resources obtained from user, port, pipeline, compromised file system or database)

§  Char [] f = new char[3];

§  f[3] = 0;                                 bug

§  f[x] = 0;                                 can write a null to anywhere in memory

§  f[x] = y;                                 can write anything anywhere in memory

·         Accepted encryption

o   AES and SHAXXX only

o   Everything else is banned!  So long TripleDES

·         Do not use:  try { } catch (Exception ex) { }

o   Hides bugs and security flaws

o   Catch only exceptions we can handle

IE v8

·         Debug tools included out of the box

o   Hit F12

§  Debug javascript

§  Solve style issues

·         Compatibility – new rendering engine following widely-accepted standard

o   Get prepared for our apps look and feel to break

o   www.msdn.com/iecompat

o   Set meta-tag to tell IE8 to continue to render using v7 engine

·         Accelerators

o   Can develop own accelerators which can highlight a name and pass to a website as a parameter.  Employee staff directory, for example.

Cool Stuff

·         Ctrl-,

o   Quick search feature in 2010

·         Ctrl-.

o   Refactoring: infers using statement.  Generate a new method as your developing

·         Web.config

o   Release version compiles debug/standard web.config and turns off debug, hardens security, replaces config and connection strings

o   Part of the installer

Other Stuff

·         Ribbon support in VS2008 Feature Pack

·         Vista Bridge

o   Wrapper to get access to Vista controls and features

o   TaskDialog and CommandLinks

§  Standard now so will be seen in Win v7

§  Backwards compatible, just extra messages to standard native button

o   Restart/Recovery API

§  Get notified of a reboot

§  Register delegate called in separate thread when app crashes/reboots

§  OS will run app with a command line argument you catch to load saved info

o   Power Management

§  Get notified about all power related info, low battery, ect

Biz Stuff

·         StepUp Program

o   Allows customers to upgrade current SKU

§  i.e. VS Pro to Team Foundation Server

§  30% discount until June 2009

SecurityException when Remote Debugging with VS2005 May 31, 2007

Posted by codinglifestyle in Security.
Tags: , , , , , ,
add a comment

You may run in to a situation where you are remote debugging an application (a simple console program in my case) and receive a security exception like this:

System.Security.SecurityException was unhandled

Message: Request for the permission of type ‘Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c’ failed.

The interesting thing was the program executed properly when run directly on the server.  However, when run via the remote debugger the problem cropped up.  I figured .NET v2 Configuration Manager was the right place to fix the problem but we no longer have the wizard which includes “Trust an assembly”.  Before finding the solution I did try caspol.exe –af file.exe but this did not work.  Finally I found the solution as follows:

 

  1. Strongly name your assembly
  2. Open ‘.NET Framework 2.0 Configuration’ from Administrative Tools
  3. Under Runtime Security Policy->Enterprise->Code Groups->All_Code right click and select New
  4. Give the new Code Group a name and description and click Next
  5. Select Strong Name as the condition type
  6. Press the Import button to import the Public Key and click Next
  7. Click Finish to create the code group
  8. Edit the properties of the newly created group
  9. Ensure the ‘Policy levels below this level will not be evaluated’ is checked

 

You should now be able to remotely debug any program strongly named with the specified public key.

IIS Madness: 401, Application Pool identities, and IP addresses March 1, 2007

Posted by codinglifestyle in IIS, Security.
Tags: , , , , , , ,
add a comment
Okay, here’s the situation. Set up a new website using Windows authentication only on any port other than 80. Create a “hello world” default.htm.  So far, so good… you may access the site at http://machinename:port. Now set that site to use an application pool with a domain user as the identity. Ensure you run aspnet_regiis -ga MachineName\AccountName. Now you are challenged and receive a 401. 
 
You are now in an interesting scenario:
http://machine:100/default.htm – does not work
http://192.168.1.234:100/default.htm – does work (assumming machine’s IP is 192.168.1.234)
 
Why?
 
According to Microsoft, IIS’s Integrated Windows authentication uses Kerberos v5 authentication and NTLM authentication. If Active Directory is installed on a domain controller running Windows 2000 Server or Windows Server 2003, and the client browser supports the Kerberos v5 authentication protocol, Kerberos v5 authentication is used. To use Kerberos authentication, a service must register its service principal name (SPN) under the account in the Active Directory directory service that the service is running under.  By default, Active Directory registers the network basic input/output system (NetBIOS) computer name.  But what about the computer name under a different port?
 
In summary, the application pool’s identity is not authenticated correctly because of IIS will try to use Kerberos by default.
 
 
To work around this behavior if you have multiple application pools that run under different domain user accounts, you must force IIS to use NTLM as your authentication mechanism if you want to use Integrated Windows authentication only. To do this, follow these steps on the server that is running IIS:
1.
Start a command prompt.
2.
Locate and then change to the directory that contains the Adsutil.vbs file. By default, this directory is C:\Inetpub\Adminscripts.
3.
Type the following command, and then press ENTER:
cscript adsutil.vbs set w3svc/NTAuthenticationProviders “NTLM”
4.
To verify that the NtAuthenticationProviders metabase property is set to NTLM, type the following command, and then press ENTER:
cscript adsutil.vbs get w3svc/NTAuthenticationProviders
The following text should be returned:
NTAuthenticationProviders : (STRING) “NTLM”
Reference: http://support.microsoft.com/kb/871179

Convert a DLL to have a Strong Name using it’s Type Library and TLBIMP January 24, 2006

Posted by codinglifestyle in Security.
Tags: ,
3 comments

Recently I was adding interop.wialib to a strongly named project.  As wialib wasn’t strongly named I got the following error:

Assembly generation failed – Referenecd assembly ‘Interop.WIALib’ does not have a strong name

I then came across this excellent tip from CodeProject which allows you to strongly name many of Microsoft assemblies:

The steps are
1) Create a key:
     sn -k keypair.snk

2) Rebuild the com object;
tlbimp OldDll.tlb /out:NewDll.dll /keyfile:keypair.snk

3) Remove the OldDll.dll from the project references

4) Add NewDll.dll the project

5) Full rebuild

Sharepoint SPAlert and UnAuthorizedAccessException June 2, 2005

Posted by codinglifestyle in Security, SharePoint.
Tags: , , , ,
add a comment

Sharepoint Portal 2003 has a fairly decent object model to work with.  Once you overcome the various security/permission issues it is quite powerful.  In fact this is the main issue in working with Sharepoint is the rite of passage for Sharepoint developers.  You will see little help and/or pity from other developers on forums when newbies hit these obstacles because most of the information is there in the SDK to be sorted out if you take the time.  However, there comes a time when your understanding is shaken when encountering a new and interesting error.  That time was last week for me when writing a metrics program which gathered statistics portal wide.  Everything was going smoothly, heck I was almost done in 2 days, when I hit a problem with SPAlerts which threw me for 2 days. 

Starting with a SPVirtualServer I iterated through the each SPSite and thus the SPSite.AllWebs.  The first SPWebCollection is for the portal itself (the following are personal and team SPS sites).  When foreaching (and new word?  we’ll see if it catches on) the SPWebs I was attempting to access to Alerts property to gather my stats.  This is where I ran in to trouble and started catching UnAuthorizedAccessException.  Below is the example from the SDK which is really there to just baffle you further because you think if they bother to show an example and I can’t even get that to work SPAlertCollection class has an example I can’t even get to work:

SPSite siteCollection = SPControl.GetContextSite(Context);
SPWebCollection sites = siteCollection.AllWebs;

foreach (SPWeb site in sites)
{
   SPAlertCollection alerts = site.Alerts;

   foreach (SPAlert alert in alerts)
   {
      Label1.Text += SPEncode.HtmlEncode(site.Title) + " :: " + SPEncode.HtmlEncode(alert.Title) + " :: " +
          alert.User.LoginName + "
";
   }
}

The above code is so simple that to have obtained the exception I was certain that it was a simple permissions problem rather than a coding problem.  The siteCollection.CurrentUser was the COMPUTER\Administrator. That user us in the Administrators group. That user was setup as a Sharepoint administrator and as the DB admin. SiteCollection.CurrentUser.IsSiteAdmin == true.

Context.User.Identity.Name
@”VM2003S1\Administrator”
Context.User.Identity.AuthenticationType
“NTLM”
Context.User.Identity.IsAuthenticated
true
Context.User.IsInRole(@”BUILTIN\Administrators”)
true
////////
// First site (the root) from SPSite.AllWebs
////////
site.Url
http://miintranet&#8221;
site.CurrentUser.LoginName
@”VM2003S1\administrator”
site.CurrentUser.IsSiteAdmin
true
site.AuthenticationMode
Windows
site.IsRootWeb
true
site.CurrentUser.Roles.Count
1
site.CurrentUser.Roles[0].Name
“Administrator”
site.Roles[“Administrator”].Users.Count
3
site.Roles[“Administrator”].Users[2].Name
@”VM2003S1\Administrator”
site.UserIsSiteAdmin
true
site.Alerts.Count
0
/////////
// Iterate to next site in SPSite.AllWebs
/////////
site.Url
http://miintranet/C0&#8243;
site.CurrentUser.LoginName
@”VM2003S1\administrator”
site.CurrentUser.IsSiteAdmin
true
site.UserIsSiteAdmin
true
site.AuthenticationMode
Windows
site.IsRootWeb
false
site.CurrentUser.Roles.Count
>UnAuthorizedAccessException
site.Roles.Count
5
site.Roles[“Administrator”].Users.Count
>UnAuthorizedAccessException
site.Alerts.Count
>UnAuthorizedAccessException

In the end it wasn’t a permission problem at all.  It seems what I was hitting is a SharePoint Services vs Sharepoint Portal issue. I may be too new at this to make an accurate assessment, but it seems that the Portal SDK lets us down by not clearly differentiating which technology they are talking about. And furthermore Microsoft let us down by having these technologies side-by-side yet not making them interoperable. This is compounded by the fact that from the Portal context I can access a SPSite.AllWebs[x].Alerts and there seems to be nothing wrong with this on the surface. The only inkling that we’re crossing boundaries is the namespace which I will be much more paranoid of in the future. Note that my “workaround” accessed the Alert (NOT SPAlert) class from the user profile manager. This Alert class is in the Microsoft.SharePoint.Portal.Alerts.Alert namespace. While the example which confounded and frustrated me for 2 days dealt with SPAlerts in the Microsoft.SharePoint.SPAlert namespace. So coder beware the exceptions you see may have more to do with crossing the technology border from Portal->Services or vice-versa. One can only hope that in the future MS will do a better job documenting or even better, making a cohesive object model which doesn’t lead you down these nebulous dead-ends.

The workaround I eventually used was to use to the UserProfileManager.  You will note that this gets you an Alert from the Portal namespace and thus no access issues.

 

 

//Get the root URL and the PortalContext.
string url = GetRootUrl();
SPSite rootSite = SPControl.GetContextSite(Context);
rootSite.AllowUnsafeUpdates=true;
PortalContext portalContext = null;
Uri uri = new Uri(url); 

TopologyManager topologyManager = new TopologyManager();
PortalSiteCollection sites = topologyManager.PortalSites;
portalContext = PortalApplication.GetContext(sites[uri]); 

//Get all the users that have access.
SPUserCollection allUsers = rootSite.RootWeb.AllUsers;
UserProfileManager upm = new UserProfileManager(portalContext); 

foreach (SPUser user in allUsers)
{
	//Get the user profile for the SPUser (from SPUserCollection)
	UserProfile up;
	try
	{
		up = upm.GetUserProfile(user.LoginName);
	}
	catch
	{
		continue;
	}
	int n = up.Alerts.Count;
}