Friday, January 27, 2012

Thinktecture IdentityServer Azure Edition RC

I found some time over the holidays to finalize the Azure edition of IdentityServer.

http://identityserver.codeplex.com/releases/view/81206

The biggest difference to the on-premise version (and earlier Azure betas) is, that by default IdSrv now uses Azure Storage for all data storage (configuration & user data). This means that there is no need anymore for SQL Azure (which is still supported out of the box – just not the default anymore).

The download includes a readme file with setup instructions. In a nutshell:

  • Create a new hosted service and upload your certificates
  • Modify the service configuration file in the download to your needs (signing cert, connection strings to storage…)
  • Deploy the package via the portal or other tools
  • Use the new Powershell scripts to add users

If you encounter any problem, please give me feedback.


IdentityServer
Friday, January 27, 2012 9:20:37 AM UTC  #   
 Monday, January 16, 2012

Google Apps and IdentityServer

nice!


IdentityServer
Monday, January 16, 2012 8:15:17 AM UTC  #   
 Saturday, December 31, 2011

Troopers 2012

My last advice for 2011:

Get a ticket for Troopers 2012 before it is sold out.

If you like to learn about IPv6, Android, iOS, SAP or cloud security (and much more) – that’s the place to be!


Conferences
Saturday, December 31, 2011 11:25:48 AM UTC  #   
 Wednesday, December 21, 2011
 Monday, December 12, 2011

Claims Guide–2nd Edition PDF

 

http://tinyurl.com/claimsguide2


IdentityModel | IdentityServer
Monday, December 12, 2011 4:48:49 AM UTC  #   
 Wednesday, December 07, 2011

Small (and fixed) Bug in IdentityServer v1.0

It was brought to my attention that fedutil does not work anymore with IdSrv v1 metadata. And I can confirm that.

The reason for this bug is my recent change to the XmlWriter factory methods which have a different default behavior when it comes to encoding.

Since there were only 20 downloads so far – I fixed the bug in-place (shame on me). So when you are one of the early adopters and run into this problem – just re-download IdSrv ;)

HTH


IdentityServer
Wednesday, December 07, 2011 8:10:24 AM UTC  #   
 Tuesday, December 06, 2011

Thinktecture IdentityServer v1.0

Yeah – it is finally done. I just uploaded the v1 bits to Codeplex and the documentation to our server. Here’s the official blurb…

Thinktecture IdentityServer is an open source security token service based on Microsoft .NET, ASP.NET MVC, WCF and WIF.

High level features

  • Multiple protocols support (WS-Trust, WS-Federation, OAuth2, WRAP, JSNotify, HTTP GET)
  • Multiple token support (SAML 1.1/2.0, SWT)
  • Out of the box integration with ASP.NET membership, roles and profile
  • Support for username/password and client certificates authentication
  • Support for WS-Federation metadata
  • Support for WS-Trust identity delegation
  • Extensibility points to customize configuration and user management handling

Disclaimer
I did thorough testing of all features of IdentityServer - but keep in mind that this is an open source project and I am the only architect, developer and tester on the team.
IdentityServer also lacks many of the enterprise-level features like configuration services, proxy support, operations integration etc.
I only recommend using IdentityServer if you also understand how it works (to be able to support it). I am offering consulting to help you with customization and lock down - contact me.

Download. Documentation.

Up next is v1 of the Azure version. Have fun!


IdentityServer
Tuesday, December 06, 2011 6:14:20 PM UTC  #   
 Wednesday, November 23, 2011

StarterSTS on IIS 6

Sam Huggill wrote a great post on how to get StarterSTS working on IIS 6.

Thanks Sam!


IdentityServer
Wednesday, November 23, 2011 3:51:49 PM UTC  #   
 Wednesday, November 16, 2011

Token based Authentication for WCF HTTP/REST Services: Authorization

In the previous post I showed how token based authentication can be implemented for WCF HTTP based services.

Authentication is the process of finding out who the user is – this includes anonymous users. Then it is up to the service to decide under which circumstances the client has access to the service as a whole or individual operations. This is called authorization.

By default – my framework does not allow anonymous users and will deny access right in the service authorization manager. You can however turn anonymous access on – that means technically, that instead of denying access, an anonymous principal is placed on Thread.CurrentPrincipal. You can flip that switch in the configuration class that you can pass into the service host/factory.

var configuration = new WebTokenWebServiceHostConfiguration
{
    AllowAnonymousAccess =
true
};

But this is not enough, in addition you also need to decorate the individual operations to allow anonymous access as well, e.g.:

[AllowAnonymousAccess]
public string
GetInfo()
{
    ...
}

Inside these operations you might have an authenticated or an anonymous principal on Thread.CurrentPrincipal, and it is up to your code to decide what to do.

Side note: Being a security guy, I like this opt-in approach to anonymous access much better that all those opt-out approaches out there (like the Authorize attribute – or this.).

Claims-based Authorization
Since there is a ClaimsPrincipal available, you can use the standard WIF claims authorization manager infrastructure – either declaratively via ClaimsPrincipalPermission or programmatically (see also here).

[ClaimsPrincipalPermission(SecurityAction.Demand, 
    Resource =
"Claims"
,
    Operation =
"View"
)]
public ViewClaims
GetClientIdentity()
{
   
return new ServiceLogic().GetClaims();
}

 

In addition you can also turn off per-request authorization (see here for background) via the config and just use the “domain specific” instrumentation.

While the code is not 100% done – you can download the current solution here.

HTH

(Wanna learn more about federation, WIF, claims, tokens etc.? Click here.)


IdentityModel | IdentityServer
Wednesday, November 16, 2011 8:11:50 AM UTC  #   
 Tuesday, November 15, 2011

Token based Authentication for WCF HTTP/REST Services: The Client

If you wondered how a client would have to look like to work with the authentication framework, it is pretty straightfoward:

  1. Request a token
  2. Put that token on the authorization header (along with a registered scheme) and make the service call

e.g.:

var oauth2 = new OAuth2Client(_oauth2Address);
var swt = oauth2.RequestAccessToken(
"username", "password", _baseAddress.AbsoluteUri);
 
var client = new HttpClient { BaseAddress = _baseAddress };
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer"
, swt);
var response = client.Get("identity");
response.EnsureSuccessStatusCode();

HTH


IdentityModel | IdentityServer
Tuesday, November 15, 2011 4:58:37 PM UTC  #   

Token based Authentication for WCF HTTP/REST Services: Authentication

This post shows some of the implementation techniques for adding token and claims based security to HTTP/REST services written with WCF. For the theoretical background, see my previous post.

Disclaimer
The framework I am using/building here is not the only possible approach to tackle the problem. Based on customer feedback and requirements the code has gone through several iterations to a point where we think it is ready to handle most of the situations.

Goals and requirements

  • The framework should be able to handle typical scenarios like username/password based authentication, as well as token based authentication
  • The framework should allow adding new supported token types
  • Should work with WCF web programming model either self-host or IIS hosted
  • Service code can rely on an IClaimsPrincipal on Thread.CurrentPrincipal that describes the client using claims-based identity

Implementation overview
In WCF the main extensibility point for this kind of security work is the ServiceAuthorizationManager. It gets invoked early enough in the pipeline, has access to the HTTP protocol details of the incoming request and can set Thread.CurrentPrincipal. The job of the SAM is simple:

  1. Check the Authorization header of the incoming HTTP request
  2. Check if a “registered” token (more on that later) is present
  3. If yes, validate the token using a security token handler, create the claims principal (including claims transformation) and set Thread.CurrentPrincipal
  4. If no, set an anonymous principal on Thread.CurrentPrincipal. By default, anonymous principals are denied access – so the request ends here with a 401 (more on that later).

To wire up the custom authorization manager you need a custom service host – which in turn needs a custom service host factory. The full object model looks like this:

Token handling
A nice piece of existing WIF infrastructure are security token handlers. Their job is to serialize a received security token into a CLR representation, validate the token and turn the token into claims.

The way this works with WS-Security based services is that WIF passes the name/namespace of the incoming token to WIF’s security token handler collection. This in turn finds out which token handler can deal with the token and returns the right instances.

For HTTP based services we can do something very similar. The scheme on the Authorization header gives the service a hint how to deal with an incoming token. So the only missing link is a way to associate a token handler (or multiple token handlers) with a scheme and we are (almost) done.

WIF already includes token handler for a variety of tokens like username/password or SAML 1.1/2.0. The accompanying sample has a implementation for a Simple Web Token (SWT) token handler, and as soon as JSON Web Token are ready, simply adding a corresponding token handler will add support for this token type, too.

All supported schemes/token types are organized in a WebSecurityTokenHandlerCollectionManager and passed into the host factory/host/authorization manager.

Adding support for basic authentication against a membership provider would e.g. look like this (in global.asax):

var manager = new WebSecurityTokenHandlerCollectionManager();

manager.AddBasicAuthenticationHandler((username, password) =>
Membership.ValidateUser(username, password));

 

Adding support for Simple Web Tokens with a scheme of Bearer (the current OAuth2 scheme) requires passing in a issuer, audience and signature verification key:

manager.AddSimpleWebTokenHandler(
   
"Bearer"
,
   
"http://identityserver.thinktecture.com/trust/initial"
,
   
"https://roadie/webservicesecurity/rest/"
,
   
"WFD7i8XRHsrUPEdwSisdHoHy08W3lM16Bk6SCT8ht6A=");

In some situations, SAML token may be used as well. The following configures SAML support for a token coming from ADFS2:

var registry = new ConfigurationBasedIssuerNameRegistry();
registry.AddTrustedIssuer(
"d1 c5 b1 25 97 d0 36 94 65 1c e2 64 fe 48 06 01 35 f7 bd db", "ADFS"
); var adfsConfig = new SecurityTokenHandlerConfiguration();
adfsConfig.AudienceRestriction.AllowedAudienceUris.Add(
new Uri("https://roadie/webservicesecurity/rest/"
));
adfsConfig.IssuerNameRegistry = registry;
adfsConfig.CertificateValidator =
X509CertificateValidator
.None; // token decryption (read from config) adfsConfig.ServiceTokenResolver =
IdentityModelConfiguration
.ServiceConfiguration.CreateAggregateTokenResolver();            
manager.AddSaml11SecurityTokenHandler(
"SAML", adfsConfig);

 

Transformation
The custom authorization manager will also try to invoke a configured claims authentication manager. This means that the standard WIF claims transformation logic can be used here as well. And even better, can be also shared with e.g. a “surrounding” web application.

Error handling
A WCF error handler takes care of turning “access denied” faults into 401 status codes and a message inspector adds the registered authentication schemes to the outgoing WWW-Authenticate header when a 401 occurs.

The next post will conclude with authorization as well as the source code download.

 

(Wanna learn more about federation, WIF, claims, tokens etc.? Click here.)


IdentityModel | IdentityServer
Tuesday, November 15, 2011 4:04:12 PM UTC  #   

Token based Authentication and Claims for Restful Services

WIF as it exists today is optimized for web applications (passive/WS-Federation) and SOAP based services (active/WS-Trust). While there is limited support for WCF WebServiceHost based services (for standard credential types like Windows and Basic), there is no ready to use plumbing for RESTful services that do authentication based on tokens.

This is not an oversight from the WIF team, but the REST services security world is currently rapidly changing – and that’s by design. There are a number of intermediate solutions, emerging protocols and token types, as well as some already deprecated ones. So it didn’t make sense to bake that into the core feature set of WIF.

But after all, the F in WIF stands for Foundation. So just like the WIF APIs integrate tokens and claims into other hosts, this is also (easily) possible with RESTful services. Here’s how.

HTTP Services and Authentication
Unlike SOAP services, in the REST world there is no (over) specified security framework like WS-Security. Instead standard HTTP means are used to transmit credentials and SSL is used to secure the transport and data in transit.

For most cases the HTTP Authorize header is used to transmit the security token (this can be as simple as a username/password up to issued tokens of some sort). The Authorize header consists of the actual credential (consider this opaque from a transport perspective) as well as a scheme. The scheme is some string that gives the service a hint what type of credential was used (e.g. Basic for basic authentication credentials). HTTP also includes a way to advertise the right credential type back to the client, for this the WWW-Authenticate response header is used.

So for token based authentication, the service would simply need to read the incoming Authorization header, extract the token, parse and validate it. After the token has been validated, you also typically want some sort of client identity representation based on the incoming token. This is regardless of how technology-wise the actual service was built. In ASP.NET (MVC) you could use an HttpModule or an ActionFilter. In (todays) WCF, you would use the ServiceAuthorizationManager infrastructure. The nice thing about using WCF’ native extensibility points is that you get self-hosting for free.

This is where WIF comes into play. WIF has ready to use infrastructure built-in that just need to be plugged into the corresponding hosting environment:

  • Representation of identity based on claims. This is a very natural way of translating a security token (and again I mean this in the widest sense – could be also a username/password) into something our applications can work with.
  • Infrastructure to convert tokens into claims (called security token handler)
  • Claims transformation
  • Claims-based authorization

So much for the theory. In the next post I will show you how to implement that for WCF – including full source code and samples.

(Wanna learn more about federation, WIF, claims, tokens etc.? Click here.)


IdentityModel | IdentityServer
Tuesday, November 15, 2011 9:25:32 AM UTC  #   
 Wednesday, November 09, 2011

Need WIF Training?

I spend numerous hours every month answering questions about WIF and identity in general. This made me realize that this is still quite a complicated topic once you go beyond the standard fedutil stuff.

My good friend Brock and I put together a two day training course about WIF that covers everything we think is important. The course includes extensive lab material where you take standard application and apply all kinds of claims and federation techniques and technologies like WS-Federation, WS-Trust, session management, delegation, home realm discovery, multiple identity providers, Access Control Service, REST, SWT and OAuth. The lab also includes the latest version of the thinktecture identityserver and you will learn how to use and customize it.

If you are looking for an open enrollment style of training, have a look here or here. Or contact me directly!

The course outline looks as follows:

Day 1
Intro to Claims-based Identity & the Windows Identity Foundation
WIF introduces important concepts like conversion of security tokens and credentials to claims, claims transformation and claims-based authorization. In this module you will learn the basics of the WIF programming model and how WIF integrates into existing .NET code.

Externalizing Authentication for Web Applications
WIF includes support for the WS-Federation protocol. This protocol allows separating business and authentication logic into separate (distributed) applications. The authentication part is called identity provider or in more general terms - a security token service. This module looks at this scenario both from an application and identity provider point of view and walks you through the necessary concepts to centralize application login logic both using a standard product like Active Directory Federation Services as well as a custom token service using WIF’s API support.

Externalizing Authentication for SOAP Services
One big benefit of WIF is that it unifies the security programming model for ASP.NET and WCF. In the spirit of the preceding modules, we will have a look at how WIF integrates into the (SOAP) web service world. You will learn how to separate authentication into a separate service using the WS-Trust protocol and how WIF can simplify the WCF security model and extensibility API.

Day 2
Advanced Topics:  Security Token Service Architecture, Delegation and Federation
The preceding modules covered the 80/20 cases of WIF in combination with ASP.NET and WCF. In many scenarios this is just the tip of the iceberg. Especially when two business partners decide to federate, you usually have to deal with multiple token services and their implications in application design. Identity delegation is a feature that allows transporting the client identity over a chain of service invocations to make authorization decisions over multiple hops. In addition you will learn about the principal architecture of a STS, how to customize the one that comes with this training course, as well as how to build your own.

Outsourcing Authentication:  Windows Azure & the Azure AppFabric Access Control Service
Microsoft provides a multi-tenant security token service as part of the Azure platform cloud offering. This is an interesting product because it allows to outsource vital infrastructure services to a managed environment that guarantees uptime and scalability. Another advantage of the Access Control Service is, that it allows easy integration of both the “enterprise” protocols like WS-* as well as “web identities” like LiveID, Google or Facebook into your applications. ACS acts as a protocol bridge in this case where the application developer doesn’t need to implement all these protocols, but simply uses a service to make it happen.

Claims & Federation for the Web and Mobile World
Also the web & mobile world moves to a token and claims-based model. While the mechanics are almost identical, other protocols and token types are used to achieve better HTTP (REST) and JavaScript integration for in-browser applications and small footprint devices. Also patterns like how to allow third party applications to work with your data without having to disclose your credentials are important concepts in these application types. The nice thing about WIF and its powerful base APIs and abstractions is that it can shield application logic from these details while you can focus on implementing the actual application.

HTH


IdentityModel | IdentityServer
Wednesday, November 09, 2011 8:18:16 AM UTC  #   
 Sunday, November 06, 2011

Fiddling with ADFS Traffic

ADFS uses SSL extended protection which made observing traffic with Fiddler harder to impossible.

Fortunately, this can be fixed – Eric Lawrence writes about it here.


IdentityModel
Sunday, November 06, 2011 12:01:23 PM UTC  #   
 Wednesday, November 02, 2011

Updated IdentityServer Sample Relying Party

I just uploaded a new version of the sample relying party. The three changes are:

  • Added a session token diagnostics page. This allows to look at cookie sizes, details and the raw contents
  • Sample code to switch to session mode
  • Sample code to implement sliding expiration

This was already included since 1.0:

  • WS-Federation example
  • Claims viewer
  • Token viewer
  • Active sign in via WS-Trust
  • Delegation

HTH


IdentityModel | IdentityServer
Wednesday, November 02, 2011 6:28:55 PM UTC  #   

Switching to WIF SessionMode in ASP.NET

To make it short: to switch to SessionMode (cache to server) in ASP.NET, you need to handle an event and set a property. Sounds easy – but you need to set it in the right place.

The most popular blog post about this topic is from Vittorio. He advises to set IsSessionMode in WSFederationAuthenticationModule_SessionSecurityTokenCreated.

Now there were some open questions on forum, like this one. So I decided to try it myself – and indeed it didn’t work for me as well. So I digged a little deeper, and after some trial and error I found the right place (in global.asax):

void WSFederationAuthenticationModule_SecurityTokenValidated(
object sender, SecurityTokenValidatedEventArgs
e)
{
   
FederatedAuthentication.SessionAuthenticationModule.IsSessionMode = true;
}

Not sure if anything has changed since Vittorio’s post – but this worked for me.

While playing around, I also wrote a little diagnostics tool that allows you to look into the session cookie (for educational purposes). Will post that soon.

HTH


IdentityModel
Wednesday, November 02, 2011 3:55:40 PM UTC  #   
 Friday, October 28, 2011

Guide to Claims-based Identity and Access Control (2nd Edition)

This fell through the cracks over the summer holiday time:

The 2nd edition of the Patterns & Practices “claims guide” has been released. This is excellent!

We added a lot of content around ADFS, Access Control Service, REST and SharePoint. All source code is available as well!

Grab it from: http://msdn.microsoft.com/en-us/library/ff423674.aspx

Or use my vanity URL: http://tinyurl.com/claimsguide


IdentityModel
Friday, October 28, 2011 7:49:30 AM UTC  #   
 Monday, October 24, 2011

IdentityServer and SharePoint Walkthrough

Brian has posted a great walkthrough on how to setup idsrv in conjunction with SharePoint. Thanks!

http://sharepintblog.com/2011/10/23/sharepoint-claims-based-authentication-with-thinktecture-identity-server-walkthrough/


IdentityServer
Monday, October 24, 2011 2:13:14 PM UTC  #   
 Friday, October 21, 2011

Thinktecture.IdentityServer RC

I just uploaded the RC of IdentityServer to Codeplex.

This release is feature complete and if I don’t get any bug reports this is also pretty much the final V1.

Changes from B1

  • The configuration data access is now based on EF 4.1 code first. This makes it much easier to use different data stores. For RTM I will also provide a SQL script for SQL Server so you can move the configuration to a separate machine (e.g. for load balancing scenarios).
  • I included the ASP.NET Universal Providers in the download. This adds official support for SQL Azure, SQL Server and SQL Compact for the membership, roles and profile features. Unfortunately the Universal Provider use a different schema than the original ASP.NET providers (that sucks btw!) – so I made them optional. If you want to use them go to web.config and uncomment the new provider.
  • The relying party registration entries now have added fields to add extra data that you want to couple with the RP. One use case could be to give the UI a hint how the login experience should look like per RP. This allows to have a different look and feel for different relying parties. I also included a small helper API that you can use to retrieve the RP record based on the incoming WS-Federation query string.
  • WS-Federation single sign out is now conforming to the spec.
  • Certificate based endpoint identities for SSL endpoints are optional now.
  • Added a initial configuration “wizard”. This sets up the signing certificate, issuer URI and site title on the first run.

Installation

This is still a “developer” release – that means it ships with source code that you have to build it etc. But from that point it should be a little more straightforward as it used to be:

  • Make sure SSL is configured correctly for IIS
  • Map the WebSite directory to a vdir in IIS
  • Run the web site. This should bring up the initial configuration
  • Make sure the worker process account has access to the signing certificate private key
  • Make sure all your users are in the “IdentityServerUsers” role in your role store. Administrators need the “IdentityServerAdministrators” role

That should be it. A proper documentation will be hopefully available soon (any volunteers?).

Please provide feedback! thanks!


IdentityServer
Friday, October 21, 2011 6:43:14 AM UTC  #   
 Thursday, October 06, 2011

Roadmap for Thinktecture IdentityServer

I got asked today if I could publish a roadmap for thinktecture IdentityServer (idrsv in short).

Well – I got a lot of feedback after B1 and one of the biggest points here was the data access layer. So I made two changes:

  • I moved to configuration database access code to EF 4.1 code first. That makes it much easier to change the underlying database. So it is now just a matter of changing the connection string to use real SQL Server instead of SQL Compact. Important when you plan to do scale out.
  • I included the ASP.NET Universal Providers in the download. This adds official support for SQL Azure, SQL Server and SQL Compact for the membership, roles and profile features. Unfortunately the Universal Provider use a different schema than the original ASP.NET providers (that sucks btw!) – so I made them optional. If you want to use them go to web.config and uncomment the new provider.

Then there are some other small changes:

  • The relying party registration entries now have added fields to add extra data that you want to couple with the RP. One use case could be to give the UI a hint how the login experience should look like per RP. This allows to have a different look and feel for different relying parties. I also included a small helper API that you can use to retrieve the RP record based on the incoming WS-Federation query string.
  • WS-Federation single sign out is now conforming to the spec.
  • I made certificate based endpoint identities for SSL endpoints optional. This caused some problems with configuration and versioning of existing clients.

I hope I can release the RC in the next days. If there are no major issues, there will be RTM very soon!


IdentityServer
Thursday, October 06, 2011 5:01:09 PM UTC  #   
 Thursday, September 29, 2011

IdentityServer Installation Walkthrough

Claudio Sanchez has created a little walkthrough for installing IdentityServer. While he uses B1 refresh, I anticipate no changes for RTM (which is sitting here on my hard drive almost ready for publishing).

Thanks Claudio!


IdentityServer
Thursday, September 29, 2011 10:35:13 PM UTC  #   
 Tuesday, September 20, 2011

WIF in .NET 4.5–First Observations (2)

 

  • WindowsIdentity, FormsIdentity and GenericIdentity now derive from ClaimsIdentity
  • WindowsIdentity.GetCurrent() converts Windows token details (groups for the current Windows versions) to claims.
  • Claims for Windows identities now distinguish between user claims and device claims (Windows 8 feature)
  • WCF now populates Thread.CurrentPrincipal with a ClaimsPrincipal derived type

IdentityModel
Tuesday, September 20, 2011 12:32:00 PM UTC  #   
 Monday, September 19, 2011

WIF in .NET 4.5–First Observations

 

  • System.Security.Claims has ClaimsIdentity & ClaimsPrincipal
  • IClaimsIdentity & IClaimsPrincipal are gone. The classes implement IIdentity & IPrincipal now directly
  • All the token handler and low level plumbing is now in System.IdentityModel

IdentityModel
Monday, September 19, 2011 6:20:42 PM UTC  #   
 Saturday, September 17, 2011

Claims-based Identity in .NET 4.5 and Windows 8

There was not a ton of new information about WIF and related technologies at Build, but Samuel Devasahayam did a great talk about claims-based access control that contained some very interesting bits of information with regards to future directions.

From his slides:

Windows 8

  • Bring existing identity claims model into the Windows platform
  • Domain controller issues groups & claims
  • Claims (user and device) sourced from identity attributes in AD
  • Claims delivered in Kerberos PAC
  • NT Token has a new claims section
  • Enhanced SDDL API’s to work with claims
  • Enhanced user mode CheckAccess API’s to work with claims
  • New ACL-UX
  • Target audits with claims-based expressions

WIF & .NET 4.5

  • WIF is in the box with .NET Framework 4.5
  • Every principal in .NET 4.5 is a ClaimsPrincipal

ADFS 2.1

  • ADFS 2.1 is available now as a in-box server role in Windows 8
  • Adds support for issuing device claims from Kerberos ticket

IdentityModel
Saturday, September 17, 2011 6:30:36 AM UTC  #   
 Wednesday, July 06, 2011

Sample Relying Party for Thinktecture.IdentityServer

I uploaded a sample RP for IdentityServer. It shows some basic things like connecting a web application via WS-Federation and a SOAP service via WS-Trust.


IdentityModel | IdentityServer
Wednesday, July 06, 2011 6:59:33 AM UTC  #   
 Monday, July 04, 2011
 Thursday, June 23, 2011

Me on LockDown Radio

Seems to be radio week this week…

Another interview I did quite a while ago with Michele and Patrick…

http://www.lockdownpodcast.com/default.aspx?ShowNum=4


Misc
Thursday, June 23, 2011 8:50:39 PM UTC  #   

Access Control Service: Passive/Active Transition Sample

Here you can find my updated ACS2 sample. In addition to the existing front ends (web [WS-Federation], console [SOAP & REST], Silverlight [REST]) and error handling, it now also includes a WPF client that shows the passive/active transition with a SOAP service as illustrated here.

All the ACS interaction is encapsulated in a WPF user control that:

  • retrieves the JSON feed
  • displays a list of supported identity providers
  • triggers the sign in via a browser control
  • retrieves the token response
  • packages the token as a GenericXmlSecurityToken (to be used directly with the WIF ChannelFactory extensions methods)

All you need to supply is the ACS namespace and the realm.

Have fun!


Azure | IdentityModel
Thursday, June 23, 2011 10:46:06 AM UTC  #   

Access Control Service: Programmatically Accessing Identity Provider Information and Redirect URLs

In my last post I showed you that different redirect URLs trigger different response behaviors in ACS. Where did I actually get these URLs from?

The answer is simple – I asked ACS ;)

ACS publishes a JSON encoded feed that contains information about all registered identity providers, their display names, logos and URLs. With that information you can easily write a discovery client which, at the very heart, does this:

public void GetAsync(string protocol)
{
   
var url = string.Format(
"https://{0}.{1}/v2/metadata/IdentityProviders.js?protocol={2}&realm={3}&version=1.0"
,
        AcsNamespace,
       
"accesscontrol.windows.net"
,
        protocol,
        Realm);

    _client.DownloadStringAsync(
new Uri(url));
}

The protocol can be one of these two values: wsfederation or javascriptnotify. Based on that value, the returned JSON will contain the URLs for either the redirect or notify method.

Now with the help of some JSON serializer you can turn that information into CLR objects and display them in some sort of selection dialog.

The next post will have a demo and source code.


Azure | IdentityModel
Thursday, June 23, 2011 5:24:27 AM UTC  #   

More Claims on DotNetRocks

I met Carl and Richard at NDC, so we took the chance to have another chat about my favourite topic: claims ;)

http://www.dotnetrocks.com/default.aspx?showNum=674

Have fun!


Conferences | Misc
Thursday, June 23, 2011 5:00:20 AM UTC  #   
 Wednesday, June 22, 2011

Access Control Service: Transitioning between Active and Passive Scenarios

As I mentioned in my last post, ACS features a number of ways to transition between protocol and token types. One not so widely known transition is between passive sign ins (browser) and active service consumers. Let’s see how this works.

We all know the usual WS-Federation handshake via passive redirect. But ACS also allows driving the sign in process yourself via specially crafted WS-Federation query strings. So you can use the following URL to sign in using LiveID via ACS. ACS will then redirect back to the registered reply URL in your application:

GET /login.srf?
  wa=wsignin1.0&
  wtrealm=https%3a%2f%2faccesscontrol.windows.net%2f&
  wreply=https%3a%2f%2fleastprivilege.accesscontrol.windows.net%3a443%2fv2%2fwsfederation&
  wp=MBI_FED_SSL&
  wctx=pr%3dwsfederation%26rm%3dhttps%253a%252f%252froadie%252facs2rp%252frest%252f

The wsfederation bit in the wctx parameter indicates, that the response to the token request will be transmitted back to the relying party via a POST.

So far so good – but how can an active client receive that token now?

ACS knows an alternative way to send the token request response. Instead of doing the redirect back to the RP, it emits a page that in turn echoes the token response using JavaScript’s window.external.notify. The URL would look like this:

GET /login.srf?
  wa=wsignin1.0&
  wtrealm=https%3a%2f%2faccesscontrol.windows.net%2f&
  wreply=https%3a%2f%2fleastprivilege.accesscontrol.windows.net%3a443%2fv2%2fwsfederation&
  wp=MBI_FED_SSL&
  wctx=pr%3djavascriptnotify%26rm%3dhttps%253a%252f%252froadie%252facs2rp%252frest%252f

ACS would then render a page that contains the following script block:

<script type="text/javascript">
    try{
        window.external.Notify('token_response');
    }
    catch(err){
        alert("Error ACS50021: windows.external.Notify is not registered.");
    }
</script>

Whereas token_response is a JSON encoded string with the following format:

{
  "appliesTo":"...",
  "context":null,
  "created":123,
  "expires":123,
  "securityToken":"...",
  "tokenType":"..."
}

OK – so how does this all come together now?

As an active client (Silverlight, WPF, WP7, WinForms etc). application, you would host a browser control and use the above URL to trigger the right series of redirects. All the browser controls support one way or the other to register a callback whenever the window.external.notify function is called. This way you get the JSON string from ACS back into the hosting application – and voila you have the security token.

When you selected the SWT token format in ACS – you can use that token e.g. for REST services. When you have selected SAML, you can use the token e.g. for SOAP services.

In the next post I will show how to retrieve these URLs from ACS and a practical example using WPF.


Azure | IdentityModel
Wednesday, June 22, 2011 6:04:27 PM UTC  #   

OT: Nice Photo Blog

My good friend Heimo started blogging. Given his vast arsenal of cameras and lenses, this should be an interesting read…

http://monoflop.blogspot.com/


Misc
Wednesday, June 22, 2011 9:18:37 AM UTC  #   

Access Control Service: Protocol and Token Transition

ACS v2 supports a number of protocols (WS-Federation, WS-Trust, OpenId, OAuth 2 / WRAP) and a number of token types (SWT, SAML 1.1/2.0) – see Vittorio’s Infographic here. Some protocols are designed for active client (WS-Trust, OAuth / WRAP) and some are designed for passive clients (WS-Federation, OpenID).

One of the most obvious advantages of ACS is that it allows to transition between various protocols and token types. Once example would be using WS-Federation/SAML between your application and ACS to sign in with a Google account. Google is using OpenId and non-SAML tokens, but ACS transitions into WS-Federation and sends back a SAML token. This way you application only needs to understand a single protocol whereas ACS acts as a protocol bridge (see my ACS2 sample here).

Another example would be transformation of a SAML token to a SWT. This is achieved by using the WRAP endpoint – you send a SAML token (from a registered identity provider) to ACS, and ACS turns it into a SWT token for the requested relying party, e.g. (using the WrapClient from Thinktecture.IdentityModel):

[TestMethod]
public void
GetClaimsSamlToSwt()
{
   
// get saml token from idp
    var samlToken = Helper
.GetSamlIdentityTokenForAcs();

   
// send to ACS for SWT converion
    var swtToken = Helper
.GetSimpleWebToken(samlToken);

   
var client = new HttpClient(Constants
.BaseUri);
    client.SetAccessToken(swtToken,
WebClientTokenSchemes
.OAuth);

   
// call REST service with SWT
    var response = client.Get("wcf/client"
);

   
Assert.AreEqual<HttpStatusCode>(HttpStatusCode.OK, response.StatusCode);
}

There are more protocol transitions possible – but they are not so obvious. A popular example would be how to call a REST/SOAP service using e.g. a LiveId login. In the next post I will show you how to approach that scenario.


Azure | IdentityModel
Wednesday, June 22, 2011 6:49:32 AM UTC  #   
 Friday, June 17, 2011

Updates for Thinktecture.IdentityModel

I just uploaded a new version to codeplex and nuget (Thinktecture.IdentityModel).

Besides some bug fixes and clean up I added the ProtectedCookie feature and some more extension methods.


IdentityModel
Friday, June 17, 2011 2:48:34 PM UTC  #   

Useful Extensions for SecurityToken Handling - Convert a SecurityToken to Claims

That’s a very common one:

public static IClaimsPrincipal ToClaimsPrincipal(
this SecurityToken token, X509Certificate2
signingCertificate)
{
   
var
configuration = CreateStandardConfiguration(signingCertificate);
   
return token.ToClaimsPrincipal(configuration.CreateDefaultHandlerCollection());
}
 
public static IClaimsPrincipal ToClaimsPrincipal(this SecurityToken token, 
X509Certificate2 signingCertificate, string
audienceUri)
{
   
var
configuration = CreateStandardConfiguration(signingCertificate);

    configuration.AudienceRestriction.AudienceMode =
AudienceUriMode
.Always;
    configuration.AudienceRestriction.AllowedAudienceUris.Add(
new Uri
(audienceUri));

   
return token.ToClaimsPrincipal(configuration.CreateDefaultHandlerCollection());
}
 
public static IClaimsPrincipal ToClaimsPrincipal(
this SecurityToken token, SecurityTokenHandlerCollection
handler)
{
   
var
ids = handler.ValidateToken(token);
   
return ClaimsPrincipal.CreateFromIdentities(ids);
}
 
private static SecurityTokenHandlerConfiguration CreateStandardConfiguration(
X509Certificate2
signingCertificate)
{
   
var configuration = new SecurityTokenHandlerConfiguration
();

    configuration.AudienceRestriction.AudienceMode =
AudienceUriMode
.Never;
    configuration.IssuerNameRegistry = signingCertificate.CreateIssuerNameRegistry();
    configuration.IssuerTokenResolver = signingCertificate.CreateSecurityTokenResolver();
    configuration.SaveBootstrapTokens =
true
;

   
return configuration;
}
 
private static IssuerNameRegistry CreateIssuerNameRegistry(this X509Certificate2 certificate)
{
   
var registry = new ConfigurationBasedIssuerNameRegistry
();
    registry.AddTrustedIssuer(certificate.Thumbprint, certificate.Subject);

   
return registry;
}
 
private static SecurityTokenResolver CreateSecurityTokenResolver(
this X509Certificate2
certificate)
{
   
var tokens = new List<SecurityToken
>
    {
       
new X509SecurityToken
(certificate)
    };

   
return SecurityTokenResolver.CreateDefaultSecurityTokenResolver(tokens.AsReadOnly(), true);
}
 
private static SecurityTokenHandlerCollection CreateDefaultHandlerCollection(
this SecurityTokenHandlerConfiguration
configuration)
{
   
return 
SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection(configuration);
}
 

IdentityModel
Friday, June 17, 2011 6:50:51 AM UTC  #   
 Thursday, June 09, 2011

Migrating a Local IdentityServer Membership Database to SQL Azure

This is a useful tool to accomplish this:

http://sqlazuremw.codeplex.com


Azure | IdentityServer
Thursday, June 09, 2011 12:22:03 PM UTC  #   
 Monday, June 06, 2011

IdentityServer Azure Edition Screencast

I recorded a short screencast about the Windows Azure Edition of IdentityServer. It includes a quick walkthrough of the solution and setup instructions.

http://identity.thinktecture.com/download/identityserver/WindowsAzureEditionB1.wmv


IdentityServer
Monday, June 06, 2011 8:55:09 PM UTC  #   
 Wednesday, June 01, 2011

Protecting Cookies: Once and For All

Every once in a while you run into a situation where you need to temporarily store data for a user in a web app. You typically have two options here – either store server-side or put the data into a cookie (if size permits).

When you need web farm compatibility in addition – things become a little bit more complicated because the data needs to be available on all nodes. In my case I went for a cookie – but I had some requirements

  • Cookie must be protected from eavesdropping (sent only over SSL) and client script
  • Cookie must be encrypted and signed to be protected from tampering with
  • Cookie might become bigger than 4KB – some sort of overflow mechanism would be nice

I really didn’t want to implement another cookie protection mechanism – this feels wrong and btw can go wrong as well.

WIF to the rescue. The session management feature already implements the above requirements but is built around de/serializing IClaimsPrincipals into cookies and back. But if you go one level deeper you will find the CookieHandler and CookieTransform classes which contain all the needed functionality.

public class ProtectedCookie
{
   
private List<CookieTransform
> _transforms;
   
private ChunkedCookieHandler _handler = new ChunkedCookieHandler
();

   
// DPAPI protection (single server)
    public
ProtectedCookie()
    {
        _transforms =
new List<CookieTransform
>
            {
               
new DeflateCookieTransform
(),
               
new ProtectedDataCookieTransform
()
            };
    }

   
// RSA protection (load balanced)
    public ProtectedCookie(X509Certificate2
protectionCertificate)
    {
        _transforms =
new List<CookieTransform
>
            {
               
new DeflateCookieTransform
(),
               
new RsaSignatureCookieTransform
(protectionCertificate),
               
new RsaEncryptionCookieTransform
(protectionCertificate)
            };
    }

   
// custom transform pipeline
    public ProtectedCookie(List<CookieTransform
> transforms)
    {
        _transforms = transforms;
    }

   
public void Write(string name, string value, DateTime
expirationTime)
    {
       
byte
[] encodedBytes = EncodeCookieValue(value);

        _handler.Write(encodedBytes, name, expirationTime);
    }

   
public void Write(string name, string value, DateTime expirationTime,
string domain, string
path)
    {
       
byte
[] encodedBytes = EncodeCookieValue(value);

        _handler.Write(encodedBytes,
name,
path,
domain,
expirationTime,
true,
true,
HttpContext
.Current);
    }

   
public string Read(string
name)
    {
       
var
bytes = _handler.Read(name);

       
if (bytes == null
|| bytes.Length == 0)
        {
           
return null
;
        }

       
return
DecodeCookieValue(bytes);
    }

   
public void Delete(string
name)
    {
        _handler.Delete(name);
    }

   
protected virtual byte[] EncodeCookieValue(string
value)
    {
       
var bytes = Encoding
.UTF8.GetBytes(value);
       
byte
[] buffer = bytes;

       
foreach (var transform in
_transforms)
        {
            buffer = transform.Encode(buffer);
        }

       
return
buffer;
    }

   
protected virtual string DecodeCookieValue(byte
[] bytes)
    {
       
var
buffer = bytes;

       
for (int
i = _transforms.Count; i > 0; i—)
        {
            buffer = _transforms[i - 1].Decode(buffer);
        }

       
return Encoding.UTF8.GetString(buffer);
    }
}

HTH


ASP.NET | IdentityModel
Wednesday, June 01, 2011 5:04:53 AM UTC  #   
 Tuesday, May 31, 2011

IdentityServer Beta 1 Refresh & Windows Azure Support

I just uploaded two new releases to Codeplex.

IdentityServer B1 refresh
A number of bug fixes and streamlined extensibility interfaces. Mostly a result of adding the Windows Azure support.

Nothing has changed with regards to setup. Make sure you watch the intro video on the Codeplex site.

IdentityServer B1 (Windows Azure Edition)
I have now implemented all repositories for Windows Azure backed data storage. The default setup assumes you use the ASP.NET SQL membership provider database in SQL Azure and Table Storage for relying party, client certificates and delegation settings.

The setup is simple:

  • Upload your SSL/signing certificate via the portal
  • Adjust the .cscfg file – you need to insert your storage account, certificate thumbprint and distinguished name
    • There is a setup tool that can automatically insert the certificate distinguished names into your config file
  • Adjust the connection string for the membership database in WebSite\configuration\connectionString.config
  • Deploy

Feedback
Feature-wise this looks like the V1 release to me. It would be great if you could give me feedback, when you find a bug etc. – especially:

  • Do the built-in repository implementations work for you (both on-premise and Azure)?
  • Are the repository interfaces enough to add you own data store or feature?

IdentityServer
Tuesday, May 31, 2011 8:55:47 PM UTC  #   

Weird 302 Redirects in Windows Azure

In IdentityServer I don’t use Forms Authentication but the session facility from WIF. That also means that I implemented my own redirect logic to a login page when needed.

To achieve that I turned off the built-in authentication (authenticationMode="none") and added an Application_EndRequest handler that checks for 401s and does the redirect to my sign in route. The redirect only happens for web pages and not for web services.

This all works fine in local IIS – but in the Azure Compute Emulator and Windows Azure many of my tests are failing and I suddenly see 302 status codes where I expected 401s (the web service calls). After some debugging kung-fu and enabling FREB I found out, that there is still the Forms Authentication module in effect turning 401s into 302s. My EndRequest handler never sees a 401 (despite turning forms auth off in config)!

Not sure what’s going on (I suspect some inherited configuration that gets in my way here). Even if it shouldn’t be necessary, an explicit removal of the forms auth module from the module list fixed it, and I now have the same behavior in local IIS and Windows Azure. strange.

<modules>
  <remove name="FormsAuthentication" />
</modules>

HTH

Update: Brock ran into the same issue, and found the real reason. Read here.


Azure | IdentityServer
Tuesday, May 31, 2011 4:42:55 AM UTC  #   
 Sunday, May 29, 2011

Access Control Service: Handling Errors

Another common problem with external authentication is how to deal with sign in errors. In active federation like WS-Trust there are well defined SOAP faults to communicate problem to a client.

But with web applications, the error information is typically generated and displayed on the external sign in page. The relying party does not know about the error, nor can it help the user in any way.

The Access Control Service allows to post sign in errors to a specified page. You setup this page in the relying party registration. That means that whenever an error occurs in ACS, the error information gets packaged up as a JSON string and posted to the page specified. This way you get structued error information back into you application so you can display a friendlier error message or log the error.

I added error page support to my ACS2 sample, which can be downloaded here.

How to turn the JSON error into CLR types
The JSON schema is reasonably simple, the following class turns the JSON into an object:

[DataContract]
public class AcsErrorResponse
{
    [
DataMember(Name = "context"
, Order = 1)]
   
public string Context { get; set
; }

    [
DataMember(Name = "httpReturnCode"
, Order = 2)]
   
public string HttpReturnCode { get; set
; }

    [
DataMember(Name = "identityProvider"
, Order = 3)]   
   
public string IdentityProvider { get; set
; }

    [
DataMember(Name = "timeStamp"
, Order = 4)]
   
public string TimeStamp { get; set
; }

    [
DataMember(Name = "traceId"
, Order = 5)]
   
public string TraceId { get; set
; }

    [
DataMember(Name = "errors"
, Order = 6)]
   
public List<AcsError> Errors { get; set
; }

   
public static AcsErrorResponse Read(string
json)
    {
       
var serializer = new DataContractJsonSerializer(
typeof(AcsErrorResponse
));
       
var response = serializer.ReadObject(
new MemoryStream(Encoding.Default.GetBytes(json))) as AcsErrorResponse
;

       
if (response != null
)
        {
           
return
response;
        }
       
else
        {
           
throw new ArgumentException("json"
);
        }
    }
}

[
DataContract
]
public class AcsError
{
    [
DataMember(Name = "errorCode"
, Order = 1)]
   
public string Code { get; set
; }
       
    [
DataMember(Name = "errorMessage"
, Order = 2)]
   
public string Message { get; set; }
}

Retrieving the error information
You then need to provide a page that takes the POST and deserializes the information. My sample simply fills a view that shows all information. But that’s for diagnostic/sample purposes only. You shouldn’t show the real errors to your end users.

public class SignInErrorController : Controller
{
    [
HttpPost
]
   
public ActionResult
Index()
    {
       
var errorDetails = Request.Form["ErrorDetails"
];
       
var response = AcsErrorResponse
.Read(errorDetails);
       
return View("SignInError", response);
    }
}

Also keep in mind that the error page is an anonymous page and that you are taking external input. So all the usual input validation applies.


IdentityModel
Sunday, May 29, 2011 8:16:05 AM UTC  #   
 Tuesday, May 24, 2011

Access Control Service: Home Realm Discovery (HRD) Gotcha

I really like ACS2. One feature that is very useful is home realm discovery. ACS provides a Nascar style list as well as discovery based on email addresses. You can take control of the home realm selection process yourself by downloading the JSON feed or by manually setting the home realm parameter.

Plenty of options – the only option missing is turning it off…

In other words, when you setup your ACS namespace and realm and register identity provider, there is no way to keep the list of identity providers secret. An interested “user” can always retrieve all registered identity provider (using the browser or download the JSON feed).

This may not be an issue with web identity providers, but when you use ACS to federate with customers or business partners, you maybe don’t want to disclose that list to the public (or to other customers). This is an adoption blocker for certain situations.

I hope this feature will be added soon.

In addition I would also like to see a feature I call “home realm aliases”. Some random string that I can use as a whr parameter instead of using the real issuer URI.


Azure | IdentityModel
Tuesday, May 24, 2011 6:58:59 PM UTC  #   

Access Control Service: Walkthrough Videos of Web Application, SOAP, REST and Silverlight Integration

Over the weekend I worked a little more on my ACS2 sample. Instead of writing it all down, I decided to quickly record four short videos that cover the relevant features and code. Have fun ;)

Part 1 – Overview
This video does a quick walkthrough of the solution and shows the web application part. This includes driving the sign in UI via JavaScript (thanks Matias) as well as the registration logic I wrote about here.

watch

Part 2 – SOAP Service and Client
The sample app also exposes a WCF SOAP service. This video shows how to wire up the service to ACS and hows how to create a client that first requests a token from an IdP and then sends this token to ACS.

watch

Part 3 – REST Service and Client
This part shows how to set up a WCF REST service that consumes SWT tokens from ACS. Unfortunately there is currently no standard WIF plumbing for REST. For the service integration I had to combine a lot of code from different sources (kzu, zulfiq) as well as the WIF SDK and OAuth CTPs together. But it is working.

watch

Part 4 – Silverlight and Web Identity Integration
This part took by far the most time to write. The Silverlight Client shows ho to sign in to the application using a registered identity provider (including web identities) and using the resulting SWT token to call our REST service. This is designed to be a desktop (OOB) client application (thanks to Jörg for the UI magic).

watch

code download


IdentityModel
Tuesday, May 24, 2011 11:40:27 AM UTC  #   

Requesting Delegation (ActAs) Tokens using WSTrustChannel (as opposed to Configuration Madness)

Delegation using the ActAs approach has some interesting security features

  • A security token service can make authorization and validation checks before issuing the ActAs token.
  • Combined with proof keys you get non-repudiation features.
  • The ultimate receiver sees the original caller as direct caller and can optionally traverse the delegation chain.
  • Encryption and audience restriction can be tied down

Most samples out there (including the SDK sample) use the CreateChannelActingAs extension method from WIF to request ActAs tokens. This method builds on top of the WCF binding configuration which may not always be suitable for your situation.

You can also use the WSTrustChannel to request ActAs tokens. This allows direct and programmatic control over bindings and configuration and is my preferred approach.

The below method requests an ActAs token based on a bootstrap token. The returned token can then directly be used with the CreateChannelWithIssued token extension method.

private SecurityToken GetActAsToken(SecurityToken bootstrapToken)
{
   
var factory = new WSTrustChannelFactory
(
       
new UserNameWSTrustBinding(SecurityMode
.TransportWithMessageCredential),
       
new EndpointAddress
(_stsAddress));
    factory.TrustVersion =
TrustVersion
.WSTrust13;

    factory.Credentials.UserName.UserName =
"middletier"
;
    factory.Credentials.UserName.Password =
"abc!123"
;


   
var rst = new RequestSecurityToken
    {
        AppliesTo =
new EndpointAddress
(_serviceAddress),

        RequestType =
RequestTypes
.Issue,
        KeyType =
KeyTypes
.Symmetric,
        ActAs =
new SecurityTokenElement
(bootstrapToken)
    };

   
var
channel = factory.CreateChannel();
   
var
delegationToken = channel.Issue(rst);

   
return delegationToken;
}

 

HTH


IdentityModel
Tuesday, May 24, 2011 6:53:11 AM UTC  #   
 Saturday, May 21, 2011

Access Control Service v2: Registering Web Identities in your Applications [code]

You can download the full solution here.

The relevant parts in the sample are:

Configuration
I use the standard WIF configuration with passive redirect. This kicks automatically in, whenever authorization fails in the application (e.g. when the user tries to get to an area the requires authentication or needs registration).

Checking and transforming incoming claims
In the claims authentication manager we have to deal with two situations. Users that are authenticated but not registered, and registered (and authenticated) users. Registered users will have claims that come from the application domain, the claims of unregistered users come directly from ACS and get passed through. In both case a claim for the unique user identifier will be generated. The high level logic is as follows:

public override IClaimsPrincipal Authenticate(
string resourceName, IClaimsPrincipal
incomingPrincipal)
{
   
// do nothing if anonymous request
    if
(!incomingPrincipal.Identity.IsAuthenticated)
    {
       
return base
.Authenticate(resourceName, incomingPrincipal);
    }

    string uniqueId = GetUniqueId(incomingPrincipal);

   
// check if user is registered
    RegisterModel
data;
   
if (Repository.TryGetRegisteredUser(uniqueId, out
data))
    {
       
return
CreateRegisteredUserPrincipal(uniqueId, data);
    }

   
// authenticated by ACS, but not registered
    // create unique id claim
    incomingPrincipal.Identities[0].Claims.Add(
new Claim(Constants.ClaimTypes
.Id, uniqueId));
   
return incomingPrincipal;
}

User Registration
The registration page is handled by a controller with the [Authorize] attribute. That means you need to authenticate before you can register (crazy eh? ;). The controller then fetches some claims from the identity provider (if available) to pre-fill form fields.

After successful registration, the user is stored in the local data store and a new session token gets issued. This effectively replaces the ACS claims with application defined claims without requiring the user to re-signin.

Authorization
All pages that should be only reachable by registered users check for a special application defined claim that only registered users have. You can nicely wrap that in a custom attribute in MVC:

[RegisteredUsersOnly]
public ActionResult
Registered()
{
   
return View();
}

HTH


IdentityModel
Saturday, May 21, 2011 4:51:56 PM UTC  #   

Access Control Service v2: Registering Web Identities in your Applications [concepts]

ACS v2 support two fundamental types of client identities– I like to call them “enterprise identities” (WS-*) and “web identities” (Google, LiveID, OpenId in general…).

I also see two different “mind sets” when it comes to application design using the above identity types:

  • Enterprise identities – often the fact that a client can present a token from a trusted identity provider means he is a legitimate user of the application. Trust relationships and authorization details have been negotiated out of band (often on paper).
  • Web identities – the fact that a user can authenticate with Google et al does not necessarily mean he is a legitimate (or registered) user of an application. Typically additional steps are necessary (like filling out a form, email confirmation etc).

Sometimes also a mixture of both approaches exist, for the sake of this post, I will focus on the web identity case.

I got a number of questions how to implement the web identity scenario and after some conversations it turns out it is the old authentication vs. authorization problem that gets in the way.

Many people use the IsAuthenticated property on IIdentity to make security decisions in their applications (or deny user=”?” in ASP.NET terms). That’s a very natural thing to do, because authentication was done inside the application and we knew exactly when the IsAuthenticated condition is true. Been there, done that. Guilty ;)

The fundamental difference between these “old style” apps and federation is, that authentication is not done by the application anymore. It is done by a third party service, and in the case of web identity providers, in services that are not under our control (nor do we have a formal business relationship with these providers).

Now the issue is, when you switch to ACS, and someone with a Google account authenticates, indeed IsAuthenticated is true – because that’s what he is! This does not mean, that he is also authorized to use the application. It just proves he was able to authenticate with Google. Now this obviously leads to confusion.

How can we solve that?
Easy answer: We have to deal with authentication and authorization separately. Job done ;)

For many application types I see this general approach:

  • Application uses ACS for authentication (maybe both enterprise and web identities, we focus on web identities but you could easily have a dual approach here)
  • Application offers to authenticate (or sign in) via web identity accounts like LiveID, Google, Facebook etc.
  • Application also maintains a database of its “own” users. Typically you want to store additional information about the user

In such an application type it is important to have a unique identifier for your users (think the primary key of your user database). What would that be?

Most web identity provider (and all the standard ACS v2 supported ones) emit a NameIdentifier claim. This is a stable ID for the client (scoped to the relying party – more on that later). Furthermore ACS emits a claims identifying the identity provider (like the original issuer concept in WIF). When you combine these two values together, you can be sure to have a unique identifier for the user, e.g.:

Facebook-134952459903700\799880347

You can now check on incoming calls, if the user is already registered and if yes, swap the ACS claims with claims coming from your user database. One claims would maybe be a role like “Registered User” which can then be easily used to do authorization checks in the application. The WIF claims authentication manager is a perfect place to do the claims transformation.

If the user is not registered, show a register form. Maybe you can use some claims from the identity provider to pre-fill form fields. (see here where I show how to use the Facebook API to fetch additional user properties). After successful registration (which may include other mechanisms like a confirmation email), flip the bit in your database to make the web identity a registered user.

This is all very theoretical. In the next post I will show some code and provide a download link for the complete sample.

More on NameIdentifier
Identity providers “guarantee” that the name identifier for a given user in your application will always be the same. But different applications (in the case of ACS – different ACS namespaces) will see different name identifiers. This is by design to protect the privacy of users because identical name identifiers could be used to create “profiles” of some sort for that user. In technical terms they create the name identifier approximately like this:

name identifier = Hash((Provider Internal User ID) + (Relying Party Address))

Why is this important to know? Well – when you change the name of your ACS namespace, the name identifiers will change as well and you will will lose your “connection” to your existing users.

Oh an btw – never use any other claims (like email address or name) to form a unique ID – these can often be changed by users.


IdentityModel
Saturday, May 21, 2011 4:07:53 PM UTC  #   
 Friday, May 20, 2011

Thinktecture.IdentityServer Beta 1

I just upload beta 1 to codeplex. Please test this version and give me feedback.

Some quick notes on setup

  • Watch the intro screencast on the codeplex site.
  • Use the setup tool to set the signing and SSL certificate. You can now also set the ACLs on the private key for your worker pool account.
  • IIS is required .
  • SSL for the IIS site the STS runs in is required.
  • Users of the STS must be in the 'IdentityServerUsers' role.
  • Admins of the STS must be in the 'IdentityServerAdministrators' roles.

What’s new?
Mainly smaller bits and pieces and some refactoring. The biggest under the cover change is a new authorization model for the STS itself. If, e.g. you don’t like the new roles I introduced, you can easily change the behavior in the claims authorization manager in the STS web site project.

What’s missing?
The big one is Azure support. Not that I ran into unforeseeable problems here, I just wanted to wait until the on-premise version is more stabilized. Now with B1 I can start adding Azure support back.


IdentityServer
Friday, May 20, 2011 2:23:27 PM UTC  #   
 Thursday, May 12, 2011

Small Gotcha when Adding ADFS as an Identity Provider in ACS v2

It turns out that ACS v2 currently supports two “types” of signing certificates for identity providers:

  • self signed certificates
  • certificates that chain up to a trusted root (from Microsoft’s perspective), e.g. VeriSign

In other words, when you use a signing certificate in ADFS that comes from your internal PKI, it won’t work.

I hope this will get fixed – err – changed soon.


IdentityModel
Thursday, May 12, 2011 12:20:49 PM UTC  #   
 Tuesday, May 10, 2011

UIs? Only with Annotations!

I don’t really know what I am talking about here ;) But Jörg does.

http://headwriteline.blogspot.com/2011/05/just-released-thinktecture.html


Misc
Tuesday, May 10, 2011 6:47:31 AM UTC  #   
 Wednesday, May 04, 2011

Improving WIF’s Claims-based Authorization - Part 3 (Usage)

In the previous posts I showed off some of the additions I made to WIF’s authorization infrastructure. I now want to show some samples how I actually use these extensions.

The following code snippets are from Thinktecture.IdentityServer on Codeplex.

The following shows the MVC attribute on the WS-Federation controller:

[ClaimsAuthorize(Constants.Actions.Issue, Constants.Resources.WSFederation)]
public class WSFederationController :
Controller

or…

[ClaimsAuthorize(Constants.Actions.Administration, Constants.Resources.RelyingParty)]
public class RelyingPartiesAdminController :
Controller

In other places I used the imperative approach (e.g. the WRAP endpoint):

if (!ClaimsAuthorize.CheckAccess(principal, Constants.Actions.Issue, Constants.Resources.WRAP))
{
   
Tracing.Error("User not authorized"
);
   
return new UnauthorizedResult("WRAP", true);
}

For the WCF WS-Trust endpoints I decided to use the per-request approach since the SOAP actions are well defined here. The corresponding authorization manager roughly looks like this:

public class AuthorizationManager : ClaimsAuthorizationManager
{
   
public override bool CheckAccess(AuthorizationContext
context)
    {
       
var
action = context.Action.First();
       
var
id = context.Principal.Identities.First();

       
// if application authorization request
        if (action.ClaimType.Equals(ClaimsAuthorize
.ActionType))
        {
           
return AuthorizeCore(action, context.Resource, context.Principal.Identity as IClaimsIdentity
);
        }

       
// if ws-trust issue request
        if (action.Value.Equals(WSTrust13Constants.Actions
.Issue))
        {
           
return AuthorizeTokenIssuance(new Collection<Claim>
{
new Claim(ClaimsAuthorize.ResourceType, Constants.Resources
.WSTrust) }, id);
        }

       
return base.CheckAccess(context);
    }
}

You see that it is really easy now to distinguish between per-request and application authorization which makes the overall design much easier.

HTH


IdentityModel
Wednesday, May 04, 2011 1:23:21 PM UTC  #   

Improving WIF’s Claims-based Authorization - Part 2

In the last post I showed you how to take control over the invocation of ClaimsAuthorizationManager. Then you have complete freedom over the claim types, the amount of claims and the values.

In addition I added two attributes that invoke the authorization manager using an “application claim type”. This way it is very easy to distinguish between authorization calls that originate from WIF’s per-request authorization and the ones from “within” you application.

The attribute comes in two flavours: a CAS attribute (invoked by the CLR) and an ASP.NET MVC attribute (for MVC controllers, invoke by the MVC plumbing). Both also feature static methods to easily call them using the application claim types.

The CAS attribute is part of Thinktecture.IdentityModel on Codeplex (or via NuGet: Install-Package Thinktecture.IdentityModel). If you really want to see that code ;) There is also a sample included in the Codeplex donwload.

The MVC attribute is currently used in Thinktecture.IdentityServer – and I don’t currently plan to make it part of the library project since I don’t want to add a dependency on MVC for now.

You can find the code below – and I will write about its usage in a follow-up post.

public class ClaimsAuthorize : AuthorizeAttribute
{
   
private string
_resource;
   
private string
_action;
   
private string
[] _additionalResources;

   
/// <summary>
    /// Default action claim type.
    /// </summary>
    public const string ActionType = "http://application/claims/authorization/action"
;


   
/// <summary>
    /// Default resource claim type
    /// </summary>
    public const string ResourceType = "http://application/claims/authorization/resource"
;

   
/// <summary>
    /// Additional resource claim type
    /// </summary>
    public const string AdditionalResourceType = "http://application/claims/authorization/additionalresource"

    

    public ClaimsAuthorize(string action, string resource, params string[] additionalResources)
    {
        _action = action;
        _resource = resource;
        _additionalResources = additionalResources;
    }

   
public static bool CheckAccess(
     
string action, string resource, params string
[] additionalResources)
    {
       
return
CheckAccess(
           
Thread.CurrentPrincipal as IClaimsPrincipal
,
            action,
            resource,
            additionalResources);
    }

   
public static bool CheckAccess(
     
IClaimsPrincipal principal, string action, string resource, params string
[] additionalResources)
    {
       
var
context = CreateAuthorizationContext(
            principal,
            action,
            resource,
            additionalResources);

       
return ClaimsAuthorization
.CheckAccess(context);
    }

   
protected override bool AuthorizeCore(HttpContextBase
httpContext)
    {
       
return
CheckAccess(_action, _resource, _additionalResources);
    }

   
private static WIF.AuthorizationContext CreateAuthorizationContext(
     
IClaimsPrincipal principal, string action, string resource, params string
[] additionalResources)
    {
       
var actionClaims = new Collection<Claim
>
        {
           
new Claim
(ActionType, action)
        };

       
var resourceClaims = new Collection<Claim
>
        {
           
new Claim
(ResourceType, resource)
        };

       
if (additionalResources != null
&& additionalResources.Length > 0)
        {
            additionalResources.ToList().ForEach(ar => resourceClaims.Add(
             
new Claim
(AdditionalResourceType, ar)));
        }

       
return new WIF.AuthorizationContext(
            principal,
            resourceClaims,
            actionClaims);
    }
}


IdentityModel
Wednesday, May 04, 2011 10:05:20 AM UTC  #   
 Tuesday, May 03, 2011

Improving WIF’s Claims-based Authorization - Part 1

As mentioned in my last post, I made several additions to WIF’s built-in authorization infrastructure to make it more flexible and easy to use.

The foundation for all this work is that you have to be able to directly call the registered ClaimsAuthorizationManager. The following snippet is the universal way to get to the WIF configuration that is currently in effect:

public static ServiceConfiguration ServiceConfiguration
{
   
get
    {
       
if (OperationContext.Current == null
)
        {
           
// no WCF
            return FederatedAuthentication
.ServiceConfiguration;
        }

       
// search message property
        if (OperationContext.Current.IncomingMessageProperties.
ContainsKey(
"ServiceConfiguration"
))
        {
           
var configuration = OperationContext.Current.
IncomingMessageProperties[
"ServiceConfiguration"] as ServiceConfiguration
;

            if (configuration != null)
            {
               
return
configuration;
            }
        }

       
// return configuration from configuration file
        return new ServiceConfiguration();
    }
}  

From here you can grab ServiceConfiguration.ClaimsAuthoriationManager which give you direct access to the CheckAccess method (and thus control over claim types and values).

I then created the following wrapper methods:

public static bool CheckAccess(string resource, string action)
{
    return CheckAccess(resource, action, Thread.CurrentPrincipal as IClaimsPrincipal);
}


public
 static bool CheckAccess(string resource, string action, IClaimsPrincipal
principal)
{
    var context = new AuthorizationContext(principal, resource, action);

   
return
AuthorizationManager.CheckAccess(context);
}

public
 static bool CheckAccess(Collection<Claim> actions, Collection<Claim
> resources)
{
    return CheckAccess(new AuthorizationContext(
       
Thread
.CurrentPrincipal.AsClaimsPrincipal(), resources, actions));
}

public
 static bool CheckAccess(AuthorizationContext
context)
{
    return AuthorizationManager.CheckAccess(context);
}

I also created the same set of methods but called DemandAccess. They internally use CheckAccess and will throw a SecurityException when false is returned.

All the code is part of Thinktecture.IdentityModel on Codeplex – or via NuGet (Install-Package Thinktecture.IdentityModel).



Tuesday, May 03, 2011 8:55:20 AM UTC  #   
 Saturday, April 30, 2011

What I don’t like about WIF’s Claims-based Authorization

In my last post I wrote about what I like about WIF’s proposed approach to authorization – I also said that I definitely would build upon that infrastructure for my own systems. But implementing such a system is a little harder as it could be. Here’s why (and that’s purely my perspective):

First of all WIF’s authorization comes in two “modes”

  • Per-request authorization.
    When an ASP.NET/WCF request comes in, the registered authorization manager gets called. For SOAP the SOAP action gets passed in. For HTTP requests (ASP.NET, WCF REST) the URL and verb.
  • Imperative authorization
    This happens when you explicitly call the claims authorization API from within your code. There you have full control over the values for action and resource.

In ASP.NET per-request authorization is optional (depends on if you have added the ClaimsAuthorizationHttpModule). In WCF you always get the per-request checks as soon as you register the authorization manager in configuration.

I personally prefer the imperative authorization because first of all I don’t believe in URL based authorization. Especially in the times of MVC and routing tables, URLs can be easily changed – but then you also have to adjust your authorization logic every time. Also – you typically need more knowledge than a simple “if user x is allowed to invoke operation x”.

One problem I have is, both the per-request calls as well as the standard WIF imperative authorization APIs wrap actions and resources in the same claim type. This makes it hard to distinguish between the two authorization modes in your authorization manager. But you typically need that feature to structure your authorization policy evaluation in a clean way.

The second problem (which is somehow related to the first one) is the standard API for interacting with the claims authorization manager. The API comes as an attribute (ClaimsPrincipalPermissionAttribute) as well as a class to use programmatically (ClaimsPrincipalPermission). Both only allow to pass in simple strings (which results in the wrapping with standard claim types mentioned earlier). Both throw a SecurityException when the check fails.

The attribute is a code access permission attribute (like PrincipalPermission). That means it will always be invoked regardless how you call the code. This may be exactly what you want, or not. In a unit testing situation (like an MVC controller) you typically want to test the logic in the function – not the security check.

The good news is, the WIF API is flexible enough that you can build your own infrastructure around their core. For my own projects I implemented the following extensions:

  • A way to invoke the registered claims authorization manager with more overloads, e.g. with different claim types or a complete AuthorizationContext.
  • A new CAS attribute (with the same calling semantics as the built-in one) with custom claim types.
  • A MVC authorization attribute with custom claim types.
  • A way to use branching – as opposed to catching a SecurityException.

I will post the code for these various extensions here – so stay tuned.


IdentityModel
Saturday, April 30, 2011 6:45:09 AM UTC  #   

What I like about WIF’s Claims-based Authorization

In “traditional” .NET with its IPrincipal interface and IsInRole method, developers were encouraged to write code like this:

public void AddCustomer(Customer customer)
{
   
if (Thread.CurrentPrincipal.IsInRole("Sales"
))
    {
       
// add customer

    }
}

In code reviews I’ve seen tons of code like this. What I don’t like about this is, that two concerns in your application get tightly coupled: business and security logic.

But what happens when the security requirements change – and they will (e.g. members of the sales role and some other people from different roles need to create customers)? Well – since your security logic is sprinkled across your project you need to change the security checks in all relevant places (and make sure you don’t forget one) and you need to re-test, re-stage and re-deploy the complete app. This is clearly not what we want.

WIF’s claims-based authorization encourages developers to separate business code and authorization policy evaluation. This is a good thing. So the same security check with WIF’s out-of-the box APIs would look like this:

public void AddCustomer(Customer customer)
{
   
try

    {
       
ClaimsPrincipalPermission.CheckAccess("Customer", "Add");
 
       
// add customer

    }
   
catch (SecurityException ex)
    {
       
// access denied

    }
}

You notice the fundamental difference? The security check only describes what the code is doing (represented by a resource/action pair) – and does not state who is allowed to invoke the code. As I mentioned earlier – the who is most probably changing over time – the what most probably not.

The call to ClaimsPrincipalPermission hands off to another class called the ClaimsAuthorizationManager. This class handles the evaluation of your security policy and is ideally in a separate assembly to allow updating the security logic independently from the application logic (and vice versa).

The claims authorization manager features a method called CheckAccess that retrieves three values (wrapped inside an AuthorizationContext instance) – action (“add”), resource (“customer”) and the principal (including its claims) in question. CheckAccess then evaluates those three values and returns true/false.

I really like the separation of concerns part here. Unfortunately there is not much support from Microsoft beyond that point. And without further tooling and abstractions the CheckAccess method quickly becomes *very* complex. But still I think that is the way to go.

In the next post I will tell you what I don’t like about it (and how to fix it).


IdentityModel
Saturday, April 30, 2011 5:40:00 AM UTC  #   
 Wednesday, April 27, 2011

Kryptographie für .NET Entwickler auf Channel9

Der zweite Schwung Videos von meinem Besuch bei Microsoft in München ist nun auch fertig.

Teil 1 - Historie, symmetrische Kryptografie und Hashing
(http://channel9.msdn.com/Blogs/Lori/Kryptografie-Teil-1)

Teil 2 – asymmetrische Krypografie, X.509 Zertifikate, PKCS und SSL
(http://channel9.msdn.com/Blogs/Lori/Kryptografie-Teil-2)


Conferences
Wednesday, April 27, 2011 7:59:46 PM UTC  #   
 Friday, April 22, 2011

Access Control Service V2 and Facebook Integration

I haven’t been blogging about ACS2 in the past because it was not released and I was kinda busy with other stuff. Needless to say I spent quite some time with ACS2 already (both in customer situations as well as in the classroom and at conferences).

ACS2 rocks! It’s IMHO the most interesting and useful (and most unique) part of the whole Azure offering!

For my talk at VSLive yesterday, I played a little with the Facebook integration. See Steve’s post on the general setup.

One claim that you get back from Facebook is an access token. This token can be used to directly talk to Facebook and query additional properties about the user. Which properties you have access to depends on which authorization your Facebook app requests. You can specify this in the identity provider registration page for Facebook in ACS2. In my example I added access to the home town property of the user.

Once you have the access token from ACS you can use e.g. the Facebook SDK from Codeplex (also available via NuGet) to talk to the Facebook API.

In my sample I used the WIF ClaimsAuthenticationManager to add the additional home town claim. This is not necessarily how you would do it in a “real” app. Depends ;)

The code looks like this (sample code!):

public class ClaimsTransformer : ClaimsAuthenticationManager
{
   
public override IClaimsPrincipal Authenticate(
string resourceName, IClaimsPrincipal
incomingPrincipal)
    {
       
if
(!incomingPrincipal.Identity.IsAuthenticated)
        {
           
return base
.Authenticate(resourceName, incomingPrincipal);
        }

       
string
accessToken;
       
if (incomingPrincipal.TryGetClaimValue(
"http://www.facebook.com/claims/AccessToken", out
accessToken))
        {
           
try
            {
               
var
home = GetFacebookHometown(accessToken);
               
if (!string
.IsNullOrWhiteSpace(home))
                {
                    incomingPrincipal.Identities[0].Claims.Add(
new Claim("http://www.facebook.com/claims/HomeTown"
, home));
                }
            }
           
catch
{ }
        }

       
return
incomingPrincipal;
    }

     private string GetFacebookHometown(string token)
    {
       
var client = new FacebookClient
(token);
       
dynamic parameters = new ExpandoObject
();
        parameters.fields =
"hometown"
;
       
dynamic result = client.Get("me"
, parameters);

       
return result.hometown.name;
    }
}

 

IdentityModel
Friday, April 22, 2011 3:12:03 PM UTC  #   
 Sunday, April 17, 2011

TechDays 2011 Sweden Videos

All the videos from the excellent Örebro event are now online.

  • Dominick Baier: A Technical Introduction to the Windows Identity Foundation (watch)
  • Dominick Baier & Christian Weyer: Securing REST-Services and Web APIs on the Windows Azure Platform (watch)
  • Christian Weyer: Real World Azure - Elasticity from on-premise to the cloud and back (watch)
  • Our interview with Robert (watch)

Conferences
Sunday, April 17, 2011 7:18:02 AM UTC  #   
 Monday, April 11, 2011

IdentityServer CTP 1 Refresh

I uploaded a small refresh of IdentityServer to Codeplex.

Mostly bug fixes and an experimental OAuth 2 (WRAP) endpoint. I also included a sample RP to go along.


IdentityServer
Monday, April 11, 2011 11:29:47 AM UTC  #   

Using Robocopy to Backup to a NAS

When using Robocopy to backup data to a NAS, I always had the problem that most files were considered “old” on the NAS device (even if they weren’t) – that kind of defeats the purpose of the /MIR switch.

Today I finally decided to search for a solution – and it was remarkably easy. Most NAS devices use Samba or something similar to provide “NTFS shares” – but most of them only implement FAT-style file times with a 2-second-granularity.

You can force robocopy to use FAT file time as well using the /FFT switch. Now my backup script works again as expected.

See also here.


Misc
Monday, April 11, 2011 11:27:20 AM UTC  #   
 Wednesday, April 06, 2011

Windows Security Videos auf Channel 9

Ich habe vor ein paar Wochen mit Lori drei Videos zum Thema Windows Security für Entwickler aufgenommen – die sind nun Online.

Der erste Teil beschäftigt sich mit den absoluten Grundlagen der Windows Sicherheit. Was ist ein Konto? Was ist eine SID? Was ist ein Windows Token? Weiterhin wird gezeigt, wie sich diese grundlegenden Windows Einrichtungen über Managed Code anprogrammieren lassen. Der Vortrag endet mit einem kleinen Einblick in die Vorgehensweise von UAC, und wie dieses programmatisch verwendet werden kann.
http://channel9.msdn.com/Blogs/Lori/Windows-Security-fr-Developers-Teil-1

Teil zwei beschäfitgt sich mit Zugriffs-Kontrolllisten, und wie diese mit .NET Code gelesen und geschrieben werden können. Weiterhin werden die beiden verwandten Konzepte Logon Session und Impersonierung besprochen. Beide Einrichtungen erzeugen einen neuen Token, sind aber grundlegend verschieden in ihren Einsatzgebieten.
http://channel9.msdn.com/Blogs/Lori/Windows-Security-fr-Developers-Teil-2

Teil drei stellt das Kerberos Netzwerk-Authentifizierungsprotokoll vor. Da dieses Protokoll standardmäßig in Active Directory verwendet wird, sollten man es in den Grundzügen kennen. Natürlich kann auch Kerberos aus Managed Code verwendet werden – die abschließende Demo zeigt wie dies funktioniert.
http://channel9.msdn.com/Blogs/Lori/Windows-Security-fr-Developers-Teil-3

…und noch ein kleines Interview
http://channel9.msdn.com/Blogs/Lori/Interview-mit-Dominick-Baier

Viel Spaß ;)


Conferences
Wednesday, April 06, 2011 2:11:12 PM UTC  #   
 Friday, April 01, 2011

TechDays Sweden 2011

We had a really good time in Sweden. Thanks for Microsoft and the organizers/staff!

Robert did a short interview with Christian and me. Enjoy ;)

http://www.youtube.com/watch?v=cGFaX_2GIPw


Conferences
Friday, April 01, 2011 10:07:10 AM UTC  #   

Progress on Thinktecture IdentityServer

I just uploaded the very first CTP1 of thinktecture IdentityServer to codeplex. I wanted to make this code available to gather feedback and extended review. Keep in mind it is not done yet.

I also recorded an intro screencast that briefly walks through the new codebase.

Have fun!


IdentityServer
Friday, April 01, 2011 6:56:06 AM UTC  #   
 Friday, March 11, 2011

StarterSTS 1.5 Download and thinktecture IdentityServer

The source code for StarterSTS 1.5 can be found here.

The new Codeplex space is http://identityserver.codeplex.com (not published yet).


IdentityServer
Friday, March 11, 2011 10:45:21 AM UTC  #   

StarterSTS 1.5

I have the 1.5 version of StarterSTS sitting here for quite some time now. But I was always reluctant to release it. Some of the reasons are:

  • too many new features for a single (small) version change.
  • to many features that are optional, like bridged authentication and thus make the code very complex.
  • the way I implemented Azure integration adds a dependency on the Azure SDK, even for “on-premise” installations. I don’t like that.
  • the fact I am using some WebForms bits and some WCF bits, the URL structure got messy. WebForms also don’t help a lot in testability

All of the above reasons together plus the fact that I am the only architect, developer and tester on this project made me come to the conclusion that I will cancel this release. But wait…

  • StarterSTS 1.5 is fully functional. We use both the on-premise and Azure versions internally “in production”.
  • Cancelling means I will release the latest source code on Codeplex – but will not mark it as a “recommended release”. I also won’t produce updated screen casts and docs. Bu the setup is very similar to earlier versions.
  • Feel free to use and customize 1.5 and give me feedback.

On the good news front, I am working on a new version – welcome thinktecture IdentityServer. This version is based on MVC3 and the routing architecture, removed a lot of the clutter, has a SQL CE4 based configuration system, is more extensible – and in overall just cleaner.

I will be able to upload CTPs very soon.


Azure | IdentityModel | IdentityServer
Friday, March 11, 2011 9:17:00 AM UTC  #   
 Friday, March 04, 2011

Logging Output of Azure Startup Tasks to the Event Log

This can come in handy when troubleshooting:

using System;

using System.Diagnostics;

using System.Text;

 

namespace Thinktecture.Azure

{

    class Program

    {

        static EventLog _eventLog = new EventLog("Application", ".", "StartupTaskShell");

        static StringBuilder _out = new StringBuilder(64);

        static StringBuilder _err = new StringBuilder(64);

 

        static int Main(string[] args)

        {

            if (args.Length != 1)

            {

                Console.WriteLine("Invalid arguments: " + String.Join(", ", args));

                _eventLog.WriteEntry("Invalid arguments: " + String.Join(", ", args));

               

                return -1;

            }

 

            var task = args[0];

 

            ProcessStartInfo info = new ProcessStartInfo()

            {

                FileName = task,

                WorkingDirectory = Environment.CurrentDirectory,

                UseShellExecute = false,

                ErrorDialog = false,

                CreateNoWindow = true,

                RedirectStandardOutput = true,

                RedirectStandardError = true

            };

 

            var process = new Process();

            process.StartInfo = info;

 

            process.OutputDataReceived += (s, e) =>

                {

                    if (e.Data != null)

                    {

                        _out.AppendLine(e.Data);

                    }

                };

            process.ErrorDataReceived += (s, e) =>

                {

                    if (e.Data != null)

                    {

                        _err.AppendLine(e.Data);

                    }

                };

 

            process.Start();

            process.BeginOutputReadLine();

            process.BeginErrorReadLine();

            process.WaitForExit();

 

            var outString = _out.ToString();

            var errString = _err.ToString();

 

            if (!string.IsNullOrWhiteSpace(outString))

            {

                outString = String.Format("Standard Out for {0}\n\n{1}", task, outString);

                _eventLog.WriteEntry(outString, EventLogEntryType.Information);

            }

 

            if (!string.IsNullOrWhiteSpace(errString))

            {

                errString = String.Format("Standard Err for {0}\n\n{1}", task, errString);

                _eventLog.WriteEntry(errString, EventLogEntryType.Error);

            }

 

            return 0;

        }

    }

}

You then wrap your startup tasks with the StartupTaskShell and you’ll be able to see stdout and stderr in the application event log.


Azure
Friday, March 04, 2011 9:24:44 AM UTC  #   
 Tuesday, March 01, 2011

Adding a Certificate to the Root Certificate Store from the Command Line (e.g. as an Azure Startup Task)

The title says it all ;)

certutil -addstore root LeastPrivilegeCA.cer


Azure
Tuesday, March 01, 2011 2:25:16 PM UTC  #   
 Friday, February 25, 2011

Windows Phone 7 and WS-Trust

A question that I often hear these days is: “Can I connect a Windows Phone 7 device to my existing enterprise services?”.

Well – since most of my services are typically issued token based, this requires support for WS-Trust and WS-Security on the client. Let’s see what’s necessary to write a WP7 client for this scenario.

First I converted the Silverlight library that comes with the Identity Training Kit to WP7. Some things are not supported in WP7 WCF (like message inspectors and some client runtime hooks) – but besides that this was a simple copy+paste job. Very nice!

Next I used the WSTrustClient to request tokens from my STS:

private WSTrustClient GetWSTrustClient()
{
   
var client = new WSTrustClient
(
       
new WSTrustBindingUsernameMixed
(),
       
new EndpointAddress("https://identity.thinktecture.com/…/issue.svc/mixed/username"
),
       
new UsernameCredentials
(_txtUserName.Text, _txtPassword.Password));
   
return
client;
}

private void _btnLogin_Click(object sender, RoutedEventArgs e)
{
    _client = GetWSTrustClient();
 
   
var rst = new RequestSecurityToken(WSTrust13Constants.KeyTypes
.Bearer)
    {
        AppliesTo =
new EndpointAddress("https://identity.thinktecture.com/rp/"
)
    };
 
    _client.IssueCompleted += client_IssueCompleted;
    _client.IssueAsync(rst);
}

I then used the returned RSTR to talk to the WCF service.

Due to a bug in the combination of the Silverlight library and the WP7 runtime – symmetric key tokens seem to have issues currently. Bearer tokens work fine. So I created the following binding for the WCF endpoint specifically for WP7.

<customBinding>


  <binding name="mixedNoSessionBearerBinary">     <security authenticationMode="IssuedTokenOverTransport"               messageSecurityVersion="WSSecurity11 WSTrust13 WSSecureConversation13 WSSecurityPolicy12 BasicSecurityProfile10">       <issuedTokenParameters keyType="BearerKey" />     </security>     <binaryMessageEncoding />     <httpsTransport/>   </binding>
</customBinding>

The binary encoding is not necessary, but will speed things up a little for mobile devices.

I then call the service with the following code:

private void _btnCallService_Click(object sender, RoutedEventArgs e)
{
    var binding = new CustomBinding(
        new BinaryMessageEncodingBindingElement(),
        new HttpsTransportBindingElement());
 
 
    _proxy = new StarterServiceContractClient(
        binding,
        new EndpointAddress("…"));
 
    using (var scope = new OperationContextScope(_proxy.InnerChannel))
    {
        OperationContext.Current.OutgoingMessageHeaders.Add(new IssuedTokenHeader(Globals.RSTR));
        _proxy.GetClaimsAsync();
    }
}

works.

download


IdentityModel
Friday, February 25, 2011 8:35:12 AM UTC  #   
 Tuesday, February 15, 2011
 Monday, January 31, 2011

DevWeek 2011

Grats to Nick for the biggest DevWeek ever! Looking forward to it!


Conferences
Monday, January 31, 2011 7:12:36 AM UTC  #   
 Wednesday, January 26, 2011

Get your annual reality check

http://www.troopers.de/

‘nuff said – be there ;)


Conferences
Wednesday, January 26, 2011 6:10:58 AM UTC  #   
 Friday, January 21, 2011

Thinktecture.IdentityModel is now available from NuGet

You can add my WIF helper library now via NuGet.

Simply type “Install-Package Thinktecture.IdentityModel” into the Package Manager Console. Or use the “Add Library Package Reference” dialog.


IdentityModel
Friday, January 21, 2011 10:56:47 AM UTC  #   
 Monday, January 10, 2011

StarterSTS 1.5 is now officially powered by Windows Azure

…and will be released soon ;)


IdentityModel
Monday, January 10, 2011 9:16:21 PM UTC  #   
 Thursday, December 30, 2010

Windows Azure Root CAs and SSL Client Certificates

I ran into some problems while trying to make SSL client certificates work for StarterSTS 1.5. In theory you have to do two things (via startup tasks):

  • Unlock the SSL section in IIS
  • Install all the root certificates for the client certs you want to accept

I did that. But it still does not work. While inspecting the event log, I stumbled over an schannel error message that I’ve never seen before:

“When asking for client authentication, this server sends a list of trusted certificate authorities to the client. The client uses this list to choose a client certificate that is trusted by the server. Currently, this server trusts so many certificate authorities that the list has grown too long. This list has thus been truncated. The administrator of this machine should review the certificate authorities trusted for client authentication and remove those that do not really need to be trusted.”

WTF? And indeed standard Azure (web role) VMs trust 275 root CAs (see attached list). Including kinda obscure ones. I don’t really know why MS made this design decision. It seems just wrong (including breaking the SSL client cert functionality).

Deleting like 60% of them made SSL client certs from my CA work. So I guess I now have to find an automated way to attach CTLs to my site…joy.

Exported list of trusted CA (as of 30th Dec 2010)
AC Raíz Certicámara S.A. (4/2/2030 9:42:02 PM)
AC RAIZ FNMT-RCM (1/1/2030 12:00:00 AM)
A-CERT ADVANCED (10/23/2011 2:14:14 PM)
Actalis Authentication CA G1 (6/25/2022 2:06:00 PM)
Agence Nationale de Certification Electronique (8/12/2037 9:03:17 AM)
Agence Nationale de Certification Electronique (8/12/2037 9:58:14 AM)
Agencia Catalana de Certificacio (NIF Q-0801176-I) (1/7/2031 10:59:59 PM)
America Online Root Certification Authority 1 (11/19/2037 8:43:00 PM)
America Online Root Certification Authority 2 (9/29/2037 2:08:00 PM)
ANCERT Certificados CGN (2/11/2024 5:27:12 PM)
ANCERT Certificados Notariales (2/11/2024 3:58:26 PM)
ANCERT Corporaciones de Derecho Publico (2/11/2024 5:22:45 PM)
A-Trust-nQual-01 (11/30/2014 11:00:00 PM)
A-Trust-nQual-03 (8/17/2015 10:00:00 PM)
A-Trust-Qual-01 (11/30/2014 11:00:00 PM)
A-Trust-Qual-02 (12/2/2014 11:00:00 PM)
A-Trust-Qual-03a (4/24/2018 10:00:00 PM)
Austria Telekom-Control Kommission (9/24/2005 12:40:00 PM)
Austrian Society for Data Protection (2/12/2009 11:30:30 AM)
Austrian Society for Data Protection GLOBALTRUST Certification Service (9/18/2036 2:12:35 PM)
Autoridad Certificadora Raiz de la Secretaria de Economia (5/9/2025 12:00:00 AM)
Autoridad de Certificacion de la Abogacia (6/13/2030 10:00:00 PM)
Autoridad de Certificacion Firmaprofesional CIF A62634068 (10/24/2013 10:00:00 PM)
Autoridade Certificadora Raiz Brasileira (11/30/2011 11:59:00 PM)
Baltimore CyberTrust Root (5/12/2025 11:59:00 PM)
BIT AdminCA-CD-T01 (1/25/2016 12:36:19 PM)
BIT Admin-Root-CA (11/10/2021 7:51:07 AM)
Buypass Class 2 CA 1 (10/13/2016 10:25:09 AM)
Buypass Class 3 CA 1 (5/9/2015 2:13:03 PM)
CA Disig (3/22/2016 1:39:34 AM)
CertEurope (3/27/2037 11:00:00 PM)
CERTICAMARA S.A. (2/23/2015 5:10:37 PM)
Certicámara S.A. (5/23/2011 10:00:00 PM)
Certigna (6/29/2027 3:13:05 PM)
Certipost E-Trust Primary Normalised CA (7/26/2020 10:00:00 AM)
Certipost E-Trust Primary Qualified CA (7/26/2020 10:00:00 AM)
Certipost E-Trust Primary TOP Root CA (7/26/2025 10:00:00 AM)
Certisign Autoridade Certificadora AC1S (6/27/2018 12:00:00 AM)
Certisign Autoridade Certificadora AC2 (6/27/2018 12:00:00 AM)
Certisign Autoridade Certificadora AC3S (7/9/2018 8:56:32 PM)
Certisign Autoridade Certificadora AC4 (6/27/2018 12:00:00 AM)
CertPlus Class 1 Primary CA (7/6/2020 11:59:59 PM)
CertPlus Class 2 Primary CA (7/6/2019 11:59:59 PM)
CertPlus Class 3 Primary CA (7/6/2019 11:59:59 PM)
CertPlus Class 3P Primary CA (7/6/2019 11:59:59 PM)
CertPlus Class 3TS Primary CA (7/6/2019 11:59:59 PM)
CertRSA01 (3/3/2010 2:59:59 PM)
certSIGN Root CA (7/4/2031 5:20:04 PM)
Certum (6/11/2027 10:46:39 AM)
Certum Trusted Network CA (12/31/2029 12:07:37 PM)
Chambers of Commerce Root - 2008 (7/31/2038 12:29:50 PM)
Chambersign Chambers of Commerce Root (9/30/2037 4:13:44 PM)
Chambersign Global Root (9/30/2037 4:14:18 PM)
Chambersign Public Notary Root (9/30/2037 4:14:49 PM)
Chunghwa Telecom Co. Ltd. (12/20/2034 2:31:27 AM)
Cisco Systems (5/14/2029 8:25:42 PM)
CNNIC Root (4/16/2027 7:09:14 AM)
Common Policy (10/15/2027 4:08:00 PM)
COMODO (12/31/2028 11:59:59 PM)
COMODO (1/18/2038 11:59:59 PM)
COMODO (12/31/2029 11:59:59 PM)
ComSign Advanced Security CA (3/24/2029 9:55:55 PM)
ComSign CA (3/19/2029 3:02:18 PM)
ComSign Secured CA (3/16/2029 3:04:56 PM)
Correo Uruguayo - Root CA (12/31/2030 2:59:59 AM)
Cybertrust Global Root (12/15/2021 8:00:00 AM)
DanID (2/11/2037 9:09:30 AM)
DanID (4/5/2021 5:03:17 PM)
Deutsche Telekom Root CA 2 (7/9/2019 11:59:00 PM)
DigiCert (11/10/2031 12:00:00 AM)
DigiCert (11/10/2031 12:00:00 AM)
DigiCert (11/10/2031 12:00:00 AM)
DigiNotar Root CA (3/31/2025 6:19:21 PM)
DIRECCION GENERAL DE LA POLICIA (2/8/2036 10:59:59 PM)
DST (ABA.ECOM) CA (7/9/2009 5:33:53 PM)
DST (ANX Network) CA (12/9/2018 4:16:48 PM)
DST (Baltimore EZ) CA (7/3/2009 7:56:53 PM)
DST (National Retail Federation) RootCA (12/8/2008 4:14:16 PM)
DST (United Parcel Service) RootCA (12/7/2008 12:25:46 AM)
DST ACES CA X6 (11/20/2017 9:19:58 PM)
DST Root CA X3 (9/30/2021 2:01:15 PM)
DST RootCA X1 (11/28/2008 6:18:55 PM)
DST RootCA X2 (11/27/2008 10:46:16 PM)
DSTCA E1 (12/10/2018 6:40:23 PM)
DSTCA E2 (12/9/2018 7:47:26 PM)
DST-Entrust GTI CA (12/9/2018 12:32:24 AM)
D-TRUST GmbH (5/16/2022 5:20:47 AM)
D-TRUST GmbH (6/8/2012 11:47:46 AM)
D-TRUST GmbH (5/16/2022 5:20:47 AM)
EBG Elektronik Sertifika Hizmet Saglayicisi (8/14/2016 12:31:09 AM)
E-Certchile (9/5/2028 7:39:41 PM)
Echoworx Root CA2 (10/7/2030 10:49:13 AM)
ECRaizEstado (6/23/2030 1:41:27 PM)
EDICOM (4/13/2028 4:24:22 PM)
E-GÜVEN Elektronik Sertifika Hizmet Saglayicisi (1/4/2017 11:32:48 AM)
E-ME SSI (RCA) (5/19/2027 8:48:15 AM)
Entrust (11/27/2026 8:53:42 PM)
Entrust (5/25/2019 4:39:40 PM)
Entrust.net (12/7/2030 5:55:54 PM)
Equifax Secure eBusiness CA-1 (6/21/2020 4:00:00 AM)
Equifax Secure eBusiness CA-2 (6/23/2019 12:14:45 PM)
Equifax Secure Global eBusiness CA-1 (6/21/2020 4:00:00 AM)
eSign Australia: eSign Imperito Primary Root CA (5/23/2012 11:59:59 PM)
eSign Australia: Gatekeeper Root CA (5/23/2014 11:59:59 PM)
eSign Australia: Primary Utility Root CA (5/23/2012 11:59:59 PM)
Fabrica Nacional de Moneda y Timbre (3/18/2019 3:26:19 PM)
GeoTrust (8/22/2018 4:41:51 PM)
GeoTrust (7/16/2036 11:59:59 PM)
GeoTrust Global CA (5/21/2022 4:00:00 AM)
GeoTrust Global CA 2 (3/4/2019 5:00:00 AM)
GeoTrust Primary Certification Authority - G2 (1/18/2038 11:59:59 PM)
GeoTrust Primary Certification Authority - G3 (12/1/2037 11:59:59 PM)
GeoTrust Universal CA (3/4/2029 5:00:00 AM)
GeoTrust Universal CA 2 (3/4/2029 5:00:00 AM)
Global Chambersign Root - 2008 (7/31/2038 12:31:40 PM)
GlobalSign (1/28/2028 12:00:00 PM)
GlobalSign (12/15/2021 8:00:00 AM)
Go Daddy Class 2 Certification Authority (6/29/2034 5:06:20 PM)
GTE CyberTrust Global Root (8/13/2018 11:59:00 PM)
GTE CyberTrust Root (4/3/2004 11:59:00 PM)
GTE CyberTrust Root (2/23/2006 11:59:00 PM)
Halcom CA FO (6/5/2020 10:33:31 AM)
Halcom CA PO 2 (2/7/2019 6:33:31 PM)
Hongkong Post Root CA (1/16/2010 11:59:00 PM)
Hongkong Post Root CA 1 (5/15/2023 4:52:29 AM)
I.CA První certifikacní autorita a.s. (4/1/2018 12:00:00 AM)
I.CA První certifikacní autorita a.s. (4/1/2018 12:00:00 AM)
InfoNotary (3/6/2026 5:33:05 PM)
IPS SERVIDORES (12/29/2009 11:21:07 PM)
IZENPE S.A. (1/30/2018 11:00:00 PM)
Izenpe.com (12/13/2037 8:27:25 AM)
Japan Certification Services, Inc. SecureSign RootCA1 (9/15/2020 2:59:59 PM)
Japan Certification Services, Inc. SecureSign RootCA11 (4/8/2029 4:56:47 AM)
Japan Certification Services, Inc. SecureSign RootCA2 (9/15/2020 2:59:59 PM)
Japan Certification Services, Inc. SecureSign RootCA3 (9/15/2020 2:59:59 PM)
Japan Local Government PKI Application CA (3/31/2016 2:59:59 PM)
Japanese Government ApplicationCA (12/12/2017 3:00:00 PM)
Juur-SK AS Sertifitseerimiskeskus (8/26/2016 2:23:01 PM)
KamuSM (8/21/2017 11:37:07 AM)
KISA RootCA 1 (8/24/2025 8:05:46 AM)
KISA RootCA 3 (11/19/2014 6:39:51 AM)
Macao Post eSignTrust (1/29/2013 11:59:59 PM)
MicroSec e-Szigno Root CA (4/6/2017 12:28:44 PM)
Microsoft Authenticode(tm) Root (12/31/1999 11:59:59 PM)
Microsoft Root Authority (12/31/2020 7:00:00 AM)
Microsoft Root Certificate Authority (5/9/2021 11:28:13 PM)
Microsoft Timestamp Root (12/30/1999 11:59:59 PM)
MOGAHA Govt of Korea (4/21/2012 9:07:23 AM)
MOGAHA Govt of Korea GPKI (3/15/2017 6:00:04 AM)
NetLock Arany (Class Gold) Fotanúsítvány (12/6/2028 3:08:21 PM)
NetLock Expressz (Class C) Tanusitvanykiado (2/20/2019 2:08:11 PM)
NetLock Kozjegyzoi (Class A) Tanusitvanykiado (2/19/2019 11:14:47 PM)
NetLock Minositett Kozjegyzoi (Class QA) Tanusitvanykiado (12/15/2022 1:47:11 AM)
NetLock Platina (Class Platinum) Fotanúsítvány (12/6/2028 3:12:44 PM)
NetLock Uzleti (Class B) Tanusitvanykiado (2/20/2019 2:10:22 PM)
Netrust CA1 (3/30/2021 2:57:45 AM)
Network Solutions (12/31/2029 11:59:59 PM)
NLB Nova Ljubljanska Banka d.d. Ljubljana (5/15/2023 12:22:45 PM)
OISTE WISeKey Global Root GA CA (12/11/2037 4:09:51 PM)
Post.Trust Root CA (7/5/2022 9:12:33 AM)
Post.Trust Root CA (8/20/2010 1:56:21 PM)
Posta CA Root (10/20/2028 12:52:08 PM)
POSTarCA (2/7/2023 11:06:58 AM)
QuoVadis Root CA 2 (11/24/2031 6:23:33 PM)
QuoVadis Root CA 3 (11/24/2031 7:06:44 PM)
QuoVadis Root Certification Authority (3/17/2021 6:33:33 PM)
Root CA Generalitat Valenciana (7/1/2021 3:22:47 PM)
RSA Security 2048 V3 (2/22/2026 8:39:23 PM)
SECOM Trust Systems CO LTD (6/6/2037 2:12:32 AM)
SECOM Trust Systems CO LTD (6/25/2019 10:23:48 PM)
SECOM Trust Systems CO LTD (9/30/2023 4:20:49 AM)
Secretaria de Economia Mexico (5/8/2025 12:00:00 AM)
Secrétariat Général de la Défense Nationale (10/17/2020 2:29:22 PM)
SecureNet CA Class B (10/16/2009 9:59:00 AM)
Serasa Certificate Authority I (11/21/2024 2:12:45 PM)
Serasa Certificate Authority II (11/21/2024 12:44:48 PM)
Serasa Certificate Authority III (11/21/2024 1:24:14 PM)
SERVICIOS DE CERTIFICACION - A.N.C. (3/9/2009 9:08:07 PM)
Sigen-CA (6/29/2021 9:57:46 PM)
Sigov-CA (1/10/2021 2:22:52 PM)
Skaitmeninio sertifikavimo centras (12/28/2026 12:05:04 PM)
Skaitmeninio sertifikavimo centras (12/25/2026 12:08:26 PM)
Skaitmeninio sertifikavimo centras (12/22/2026 12:11:30 PM)
Sonera Class1 CA (4/6/2021 10:49:13 AM)
Sonera Class2 CA (4/6/2021 7:29:40 AM)
Spanish Property & Commerce Registry CA (4/27/2012 9:39:50 AM)
Staat der Nederlanden Root CA (12/16/2015 9:15:38 AM)
Staat der Nederlanden Root CA - G2 (3/25/2020 11:03:10 AM)
Starfield Class 2 Certification Authority (6/29/2034 5:39:16 PM)
Starfield Technologies (6/26/2019 12:19:54 AM)
Starfield Technologies Inc. (12/31/2029 11:59:59 PM)
StartCom Certification Authority (9/17/2036 7:46:36 PM)
S-TRUST Authentication and Encryption Root CA 2005:PN (6/21/2030 11:59:59 PM)
Swisscom Root CA 1 (8/18/2025 10:06:20 PM)
SwissSign (10/25/2036 8:30:35 AM)
SwissSign Platinum G2 Root CA (10/25/2036 8:36:00 AM)
SwissSign Silver G2 Root CA (10/25/2036 8:32:46 AM)
TC TrustCenter Class 1 CA (1/1/2011 11:59:59 AM)
TC TrustCenter Class 2 CA (1/1/2011 11:59:59 AM)
TC TrustCenter Class 2 CA II (12/31/2025 10:59:59 PM)
TC TrustCenter Class 3 CA (1/1/2011 11:59:59 AM)
TC TrustCenter Class 3 CA II (12/31/2025 10:59:59 PM)
TC TrustCenter Class 4 CA (1/1/2011 11:59:59 AM)
TC TrustCenter Class 4 CA II (12/31/2025 10:59:59 PM)
TC TrustCenter Time Stamping CA (1/1/2011 11:59:59 AM)
TC TrustCenter Universal CA I (12/31/2025 10:59:59 PM)
TC TrustCenter Universal CA II (12/31/2030 10:59:59 PM)
thawte (12/31/2020 11:59:59 PM)
thawte (7/16/2036 11:59:59 PM)
thawte (12/31/2020 11:59:59 PM)
thawte (12/31/2020 11:59:59 PM)
thawte (12/31/2020 11:59:59 PM)
thawte (12/31/2020 11:59:59 PM)
thawte (12/31/2020 11:59:59 PM)
thawte Primary Root CA - G2 (1/18/2038 11:59:59 PM)
thawte Primary Root CA - G3 (12/1/2037 11:59:59 PM)
Thawte Timestamping CA (12/31/2020 11:59:59 PM)
Trustis EVS Root CA (1/9/2027 11:56:00 AM)
Trustis FPS Root CA (1/21/2024 11:36:54 AM)
Trustwave (1/1/2035 5:37:19 AM)
Trustwave (12/31/2029 7:40:55 PM)
Trustwave (12/31/2029 7:52:06 PM)
TURKTRUST Elektronik Islem Hizmetleri (9/16/2015 12:13:05 PM)
TURKTRUST Elektronik Islem Hizmetleri (3/22/2015 10:04:51 AM)
TURKTRUST Elektronik Sertifika Hizmet Saglayicisi (9/16/2015 10:07:57 AM)
TURKTRUST Elektronik Sertifika Hizmet Saglayicisi (3/22/2015 10:27:17 AM)
TÜRKTRUST Elektronik Sertifika Hizmet Saglayicisi (12/22/2017 6:37:19 PM)
TW Government Root Certification Authority (12/5/2032 1:23:33 PM)
TWCA Root Certification Authority 1 (12/31/2030 3:59:59 PM)
TWCA Root Certification Authority 2 (12/31/2030 3:59:59 PM)
U.S. Government FBCA (10/6/2010 6:53:56 PM)
UCA Global Root (12/31/2037 12:00:00 AM)
UCA Root (12/31/2029 12:00:00 AM)
USERTrust (7/9/2019 6:40:36 PM)
USERTrust (7/9/2019 5:36:58 PM)
USERTrust (6/24/2019 7:06:30 PM)
USERTrust (7/9/2019 6:19:22 PM)
USERTrust (5/30/2020 10:48:38 AM)
UTN - USERFirst-Network Applications (7/9/2019 6:57:49 PM)
ValiCert Class 3 Policy Validation Authority (6/26/2019 12:22:33 AM)
VAS Latvijas Pasts SSI(RCA) (9/13/2024 9:27:57 AM)
VeriSign (5/18/2018 11:59:59 PM)
VeriSign (7/16/2036 11:59:59 PM)
VeriSign (8/1/2028 11:59:59 PM)
VeriSign (12/31/1999 9:37:48 AM)
VeriSign (1/7/2004 11:59:59 PM)
VeriSign (5/18/2018 11:59:59 PM)
VeriSign (1/7/2004 11:59:59 PM)
VeriSign (8/1/2028 11:59:59 PM)
VeriSign (8/1/2028 11:59:59 PM)
VeriSign (1/7/2020 11:59:59 PM)
VeriSign (12/31/1999 9:35:58 AM)
VeriSign (8/1/2028 11:59:59 PM)
VeriSign (7/16/2036 11:59:59 PM)
VeriSign (1/7/2004 11:59:59 PM)
VeriSign (7/16/2036 11:59:59 PM)
VeriSign (1/7/2010 11:59:59 PM)
VeriSign (5/18/2018 11:59:59 PM)
VeriSign (8/1/2028 11:59:59 PM)
VeriSign (1/7/2004 11:59:59 PM)
VeriSign (7/16/2036 11:59:59 PM)
VeriSign (7/16/2036 11:59:59 PM)
VeriSign (8/1/2028 11:59:59 PM)
VeriSign (5/18/2018 11:59:59 PM)
VeriSign Class 3 Public Primary CA (8/1/2028 11:59:59 PM)
VeriSign Class 3 Public Primary Certification Authority - G4 (1/18/2038 11:59:59 PM)
VeriSign Time Stamping CA (1/7/2004 11:59:59 PM)
VeriSign Universal Root Certification Authority (12/1/2037 11:59:59 PM)
Visa eCommerce Root (6/24/2022 12:16:12 AM)
Visa Information Delivery Root CA (6/29/2025 5:42:42 PM)
VRK Gov. Root CA (12/18/2023 1:51:08 PM)
Wells Fargo Root Certificate Authority (1/14/2021 4:41:28 PM)
WellsSecure Public Certificate Authority (12/14/2022 12:07:54 AM)
Xcert EZ by DST (7/11/2009 4:14:18 PM)


Azure
Thursday, December 30, 2010 10:21:18 AM UTC  #   
 Wednesday, December 29, 2010

Windows Azure Diagnostics: Next to Useless?

To quote my good friend Christian:

“Tracing is probably one of the most discussed topics in the Windows Azure world. Not because it is freaking cool – but because it can be very tedious and partly massively counter-intuitive.”

<rant>

The .NET Framework has this wonderful facility called TraceSource. You define a named trace and route that to a configurable listener. This gives you a lot of flexibility – you can create a single trace file – or multiple ones. There is even nice tooling around that. SvcTraceViewer from the SDK let’s you open the XML trace files – you can filter and sort by trace source and event type, aggregate multiple files…blablabla. Just what you would expect from a decent tracing infrastructure.

Now comes Windows Azure. I was already very grateful that starting with the SDK 1.2 we finally had a way to do tracing and diagnostics in the cloud (kudos!). But the way the Azure DiagnosticMonitor is currently implemented – could be called flawed.

The Azure SDK provides a DiagnosticsMonitorTraceListener – which is the right way to go. The only problem is, that way this works is, that all traces (from all sources) get written to an ETW trace. Then the DiagMon listens to these traces and copies them periodically to your storage account. So far so good.

But guess what happens to your nice trace files:

  • the trace source names get “lost”. They appear in your message text at the end. So much for filtering and sorting and aggregating (regex #fail or #win??).
  • Every trace line becomes an entry in an Azure Storage Table – the svclog format is gone. So much for the existing tooling.

To solve that problem, one workaround was to write your own trace listener (!) that creates svclog files inside of local storage and use the DiagMon to copy those. Christian has a blog post about that. OK done that.

Now it turns out that this mechanism does not work anymore in 1.3 with FullIIS (see here). Quoting:

“Some IIS 7.0 logs not collected due to permissions issues...The root cause to both of these issues is the permissions on the log files.”

And the workaround:

“To read the files yourself, log on to the instance with a remote desktop connection.”

Now then have fun with your multi-instance deployments….

So the bottom line is, that currently you cannot copy IIS logs, FREB logs and everything else that gets written by W3WP. Nice…

</rant>


Azure
Wednesday, December 29, 2010 11:53:50 AM UTC  #   
 Tuesday, December 28, 2010

Unlocking the SSL Section in Windows Azure Web Roles

Posting the favourite command line snippet seems to be the newest hobby for Azure developers ;)

Here’s one that is useful to unlock the SSL section (e.g. for client certificates):

%windir%\System32\inetsrv\appcmd.exe unlock config /section:system.webServer/security/access

Azure
Tuesday, December 28, 2010 8:52:25 PM UTC  #   
 Saturday, December 25, 2010

Handling Configuration Changes in Windows Azure Applications

While finalizing StarterSTS 1.5, I had a closer look at lifetime and configuration management in Windows Azure.

(this is no new information – just some bits and pieces compiled at one single place – plus a bit of reality check)

When dealing with lifetime management (and especially configuration changes), there are two mechanisms in Windows Azure – a RoleEntryPoint derived class and a couple of events on the RoleEnvironment class. You can find good documentation about RoleEntryPoint here. The RoleEnvironment class features two events that deal with configuration changes – Changing and Changed.

Whenever a configuration change gets pushed out by the fabric controller (either changes in the settings section or the instance count of a role) the Changing event fires. The event handler receives an instance of the RoleEnvironmentChangingEventArgs type. This contains a collection of type RoleEnvironmentChange. This in turn is a base class for two other classes that detail the two types of possible configuration changes I mentioned above: RoleEnvironmentConfigurationSettingsChange (configuration settings) and RoleEnvironmentTopologyChange (instance count). The two respective classes contain information about which configuration setting and which role has been changed. Furthermore the Changing event can trigger a role recycle (aka reboot) by setting EventArgs.Cancel to true.

So your typical job in the Changing event handler is to figure if your application can handle these configuration changes at runtime, or if you rather want a clean restart. Prior to the SDK 1.3 VS Templates – the following code was generated to reboot if any configuration settings have changed:

private void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)
{
   
// If a configuration setting is changing
    if (e.Changes.Any(change => change is
RoleEnvironmentConfigurationSettingChange))
    {
       
// Set e.Cancel to true to restart this role instance
        e.Cancel = true;
    }
}

This is a little drastic as a default since most applications will work just fine with changed configuration – maybe that’s the reason this code has gone away in the 1.3 SDK templates (more).

The Changed event gets fired after the configuration changes have been applied. Again the changes will get passed in just like in the Changing event. But from this point on RoleEnvironment.GetConfigurationSettingValue() will return the new values. You can still decide to recycle if some change was so drastic that you need a restart. You can use RoleEnvironment.RequestRecycle() for that (more).

As a rule of thumb: When you always use GetConfigurationSettingValue to read from configuration (and there is no bigger state involved) – you typically don’t need to recycle.

In the case of StarterSTS, I had to abstract away the physical configuration system and read the actual configuration (either from web.config or the Azure service configuration) at startup. I then cache the configuration settings in memory. This means I indeed need to take action when configuration changes – so in my case I simply clear the cache, and the new config values get read on the next access to my internal configuration object. No downtime – nice!

Gotcha
A very natural place to hook up the RoleEnvironment lifetime events is the RoleEntryPoint derived class. But with the move to the full IIS model in 1.3 – the RoleEntryPoint methods get executed in a different AppDomain (even in a different process) – see here.. You might no be able to call into your application code to e.g. clear a cache. Keep that in mind! In this case you need to handle these events from e.g. global.asax.


Azure
Saturday, December 25, 2010 6:46:54 AM UTC  #   
 Friday, December 24, 2010

Update to DeployManager

Raf did some updates to his tool. It can now generate WIF/WCF certificateReference sections. Nice.

Blog post: http://www.iamraf.net/Tools/DeployManager-first-release-certificates-management
Direct link: DeployManager.exe


Tools
Friday, December 24, 2010 9:50:26 AM UTC  #   
 Thursday, December 02, 2010

5000 Downloads of StarterSTS

nice ;) thanks for all the feedback and testing!


IdentityModel
Thursday, December 02, 2010 4:25:37 PM UTC  #   
 Sunday, November 14, 2010

TechEd 2010–Architecting Claims-aware Applications

Back from TechEd – was a blast ;)

Here’s the recording of my talk:
http://www.msteched.com/2010/Europe/ARC303


IdentityModel
Sunday, November 14, 2010 5:34:21 PM UTC  #   
 Sunday, October 31, 2010

StarterSTS v1.5 Beta 1

I just uploaded a new drop of StarterSTS.

This release has many changes and new features, e.g.:

  • Built-in support for Windows Azure
  • Caching
  • New REST endpoint
  • Federated Sign-Out
  • Extended tracing (including real time tracing to a WCF service and logging of RST(R)s and tokens)

I will drill deeper into the new features in the forthcoming blog posts.

Please try it out and give me feedback.


IdentityModel
Sunday, October 31, 2010 9:34:37 AM UTC  #   
 Thursday, October 28, 2010

WIF, ADFS 2 and WCF–Part 6: Chaining multiple Token Services

See the previous posts first.

So far we looked at the (simpler) scenario where a client acquires a token from an identity provider and uses that for authentication against a relying party WCF service.

Another common scenario is, that the client first requests a token from an identity provider, and then uses this token to request a new token from a Resource STS or a partner’s federation gateway.

This sounds complicated, but is actually very easy to achieve using WIF’s WS-Trust client support. The sequence is like this:

  1. Request a token from an identity provider. You use some “bootstrap” credential for that like Windows integrated, UserName or a client certificate. The realm used for this request is the identifier of the Resource STS/federation gateway.
  2. Use the resulting token to request a new token from the Resource STS/federation gateway. The realm for this request would be the ultimate service you want to talk to.
  3. Use this resulting token to authenticate against the ultimate service.

Step 1 is very much the same as the code I have shown in the last post. In the following snippet, I use a client certificate to get a token from my STS:

private static SecurityToken GetIdPToken()
{
   
var factory = new WSTrustChannelFactory
(
       
new CertificateWSTrustBinding(SecurityMode
.TransportWithMessageCredential,
        idpEndpoint);
    factory.TrustVersion =
TrustVersion
.WSTrust13;
 
    factory.Credentials.ClientCertificate.SetCertificate(
       
StoreLocation
.CurrentUser,
       
StoreName
.My,
       
X509FindType
.FindBySubjectDistinguishedName,
       
"CN=Client"
);
 
   
var rst = new RequestSecurityToken
    {
        RequestType =
RequestTypes
.Issue,
        AppliesTo =
new EndpointAddress
(rstsRealm),
        KeyType =
KeyTypes
.Symmetric
    };
 
   
var
channel = factory.CreateChannel();
   
return channel.Issue(rst);
}

To use a token to request another token is slightly different. First the IssuedTokenWSTrustBinding is used and second the channel factory extension methods are used to send the identity provider token to the Resource STS:

private static SecurityToken GetRSTSToken(SecurityToken idpToken)
{
   
var binding = new IssuedTokenWSTrustBinding
();
    binding.SecurityMode =
SecurityMode
.TransportWithMessageCredential;
 
   
var factory = new WSTrustChannelFactory
(
        binding,
        rstsEndpoint);
    factory.TrustVersion =
TrustVersion
.WSTrust13;
    factory.Credentials.SupportInteractive =
false
;
 
   
var rst = new RequestSecurityToken
    {
        RequestType =
RequestTypes
.Issue,
        AppliesTo =
new EndpointAddress
(svcRealm),
        KeyType =
KeyTypes
.Symmetric
    };
 
    factory.ConfigureChannelFactory();
   
var
channel = factory.CreateChannelWithIssuedToken(idpToken);
   
return
channel.Issue(rst);
}

For this particular case I chose an ADFS endpoint for issued token authentication (see part 1 for more background). Calling the service now works exactly like I described in my last post.

You may now wonder if the same thing can be also achieved using configuration only – absolutely. But there are some gotchas. First of all the configuration files becomes quite complex. As we discussed in part 4, the bindings must be nested for WCF to unwind the token call-stack. But in this case svcutil cannot resolve the first hop since it cannot use metadata to inspect the identity provider. This binding must be supplied manually.

The other issue is around the value for the realm/appliesTo when requesting a token for the R-STS. Using the manual approach you have full control over that parameter and you can simply use the R-STS issuer URI. Using the configuration approach, the exact address of the R-STS endpoint will be used. This means that you may have to register multiple R-STS endpoints in the identity provider. Another issue you will run into is, that ADFS does only accepts its configured issuer URI as a known realm by default. You’d have to manually add more audience URIs for the specific endpoints using the ADFS Powershell commandlets.

I prefer the “manual” approach.

That’s it. Hope this is useful information.



Thursday, October 28, 2010 10:03:58 AM UTC  #   
 Thursday, October 14, 2010

WIF, ADFS 2 and WCF–Part 5: Service Client (more Flexibility with WSTrustChannelFactory)

See the previous posts first.

WIF includes an API to manually request tokens from a token service. This gives you more control over the request and more flexibility since you can use your own token caching scheme instead of being bound to the channel object lifetime.

The API is straightforward. You first request a token from the STS and then use that token to create a channel to the relying party service. I’d recommend using the WS-Trust bindings that ship with WIF to talk to ADFS 2 – they are pre-configured to match the binding configuration of the ADFS 2 endpoints.

The following code requests a token for a WCF service from ADFS 2:

private static SecurityToken GetToken()
{
   
// Windows authentication over transport security
    var factory = new WSTrustChannelFactory
(
       
new WindowsWSTrustBinding(SecurityMode
.Transport),
        stsEndpoint);
    factory.TrustVersion =
TrustVersion
.WSTrust13;
 
   
var rst = new RequestSecurityToken
    {
        RequestType =
RequestTypes
.Issue,
        AppliesTo =
new EndpointAddress
(svcEndpoint),
        KeyType =
KeyTypes
.Symmetric
    };
 
   
var
channel = factory.CreateChannel();
   
return channel.Issue(rst);
}

Afterwards, the returned token can be used to create a channel to the service. Again WIF has some helper methods here that make this very easy:

private static void CallService(SecurityToken token)
{
   
// create binding and turn off sessions
    var binding = new WS2007FederationHttpBinding
(
       
WSFederationHttpSecurityMode
.TransportWithMessageCredential);
    binding.Security.Message.EstablishSecurityContext =
false
;
 
   
// create factory and enable WIF plumbing
    var factory = new ChannelFactory<IService>(binding, new EndpointAddress
(svcEndpoint));
    factory.ConfigureChannelFactory<
IService
>();
 
   
// turn off CardSpace - we already have the token
    factory.Credentials.SupportInteractive = false
;
 
   
var channel = factory.CreateChannelWithIssuedToken<IService
>(token);
 
    channel.GetClaims().ForEach(c =>
       
Console.WriteLine("{0}\n {1}\n  {2} ({3})\n"
,
            c.ClaimType,
            c.Value,
            c.Issuer,
            c.OriginalIssuer));
}

Why is this approach more flexible? Well – some don’t like the configuration voodoo. That’s a valid reason for using the manual approach. You also get more control over the token request itself since you have full control over the RST message that gets send to the STS.

One common parameter that you may want to set yourself is the appliesTo value. When you use the automatic token support in the WCF federation binding, the appliesTo is always the physical service address. This means in turn that this address will be used as the audience URI value in the SAML token. Well – this in turn means that when you have an application that consists of multiple services, you always have to configure all physical endpoint URLs in ADFS 2 and in the WIF configuration of the service(s).

Having control over the appliesTo allows you to use more symbolic realm names, e.g. the base address or a completely logical name. Since the URL is never de-referenced you have some degree of freedom here.

In the next post we will look at the necessary code to request multiple tokens in a call chain. This is a common scenario when you first have to acquire a token from an identity provider and have to send that on to a federation gateway or Resource STS.

Stay tuned.


IdentityModel
Thursday, October 14, 2010 3:47:04 PM UTC  #   

WIF, ADFS 2 and WCF–Part 4: Service Client (using Service Metadata)

See parts 1, 2 and 3 first.

In this part we will finally build a client for our federated service.

There are basically two ways to accomplish this. You can use the WCF built-in tooling to generate client and configuration via the service metadata (aka ‘Add Service Reference’). This requires no WIF on the client side. Another approach would be to use WIF’s WSTrustChannelFactory to manually talk to the ADFS 2 WS-Trust endpoints. This option gives you more flexibility, but is slightly more code to write. You also need WIF on the client which implies that you need to run on a WIF supported operating system – this rules out e.g. Windows XP clients.

We’ll start with the metadata way. You simply create a new client project (e.g. a console app) – call ‘Add Service Reference’ and point the dialog to your service endpoint. What will happen then is, that VS will contact your service and read its metadata. Inside there is also a link to the metadata endpoint of ADFS 2. This one will be contacted next to find out which WS-Trust endpoints are available. The end result will be a client side proxy and a configuration file. Let’s first write some code to call the service and then have a closer look at the config file.

var proxy = new ServiceClient();
proxy.GetClaims().ForEach(c =>
   
Console.WriteLine("{0}\n {1}\n  {2} ({3})\n",
        c.ClaimType,
        c.Value,
        c.Issuer,
        c.OriginalIssuer));

That’s all. The magic is happening in the configuration file.

When you in inspect app.config, you can see the following general configuration hierarchy:

  • <client /> element with service endpoint information
    • federation binding and configuration containing
      • ADFS 2 endpoint 1 (with binding and configuration)
      • ADFS 2 endpoint n (with binding and configuration)

(where ADFS 2 endpoint 1…n are the endpoints I talked about in part 1)

You will see a number of <issuer /> elements in the binding configuration where simply the first endpoint from the ADFS 2 metadata becomes the default endpoint and all other endpoints and their configuration are commented out. You now need to find the endpoint you want to use (based on trust version, credential type and security mode) and replace that with the default endpoint. That’s it.

When you call the WCF proxy, it will inspect configuration, then first contact the selected ADFS 2 endpoint to request a token. This token will then be used to authenticate against the service.

In the next post I will show you the more manual approach using the WIF APIs.


IdentityModel
Thursday, October 14, 2010 1:37:16 PM UTC  #   
 Tuesday, October 12, 2010

WIF, ADFS 2 and WCF–Part 3: ADFS Setup

In part 1 of this series I briefly gave an overview of the ADFS / WS-Trust infrastructure. In part 2 we created a basic WCF service that uses ADFS for authentication. This part will walk you through the steps to register the service in ADFS 2.

I could provide screenshots for all the wizard pages here – but since this is really easy – I just go through the necessary steps in textual form.

Step 1 – Select Data Source
Here you can decide if you want to import a federation metadata file that describes the service you want to register. In that case all necessary information is inside the metadata document and you are done. FedUtil (a tool that ships with WIF) can generate such metadata for the most simple cases. Another tool to create metadata can be found here. We choose ‘Manual’ here.

Step 2 – Specify Display Name
I guess that’s self explaining.

Step 3 – Choose Profile
Choose ‘ADFS 2 Profile’ here.

Step 4 – Configure Certificate
Remember that we specified a certificate (or rather a private key) to be used to decrypting incoming tokens in the previous post. Here you specify the corresponding public key that ADFS 2 should use for encrypting the token.

Step 5 – Configure URL
This page is used to configure WS-Federation and SAML 2.0p support. Since we are using WS-Trust you can leave both boxes unchecked.

Step 6 – Configure Identifier
Here you specify the identifier (aka the realm, aka the appliesTo) that will be used to request tokens for the service. This value will be used in the token request and is used by ADFS 2 to make a connection to the relying party configuration and claim rules.

Step 7 – Configure Issuance Authorization Rules
Here you can configure who is allowed to request token for the service. I won’t go into details here how these rules exactly work – that’s for a separate blog post. For now simply use the “Permit all users” option.

OK – that’s it. The service is now registered at ADFS 2. In the next part we will finally look at the service client.

Stay tuned…


IdentityModel
Tuesday, October 12, 2010 2:53:56 PM UTC  #   
 Monday, October 11, 2010

WIF, ADFS 2 and WCF–Part 2: The Service

OK – so let’s first start with a simple WCF service and connect that to ADFS 2 for authentication.

The service itself simply echoes back the user’s claims – just so we can make sure it actually works and to see how the ADFS 2 issuance rules emit claims for the service:

[ServiceContract(Namespace = "urn:leastprivilege:samples")]
public interface IService
{
    [
OperationContract
]
   
List<ViewClaim
> GetClaims();
}


public class Service : IService
{
   
public List<ViewClaim
> GetClaims()
    {
       
var id = Thread.CurrentPrincipal.Identity as IClaimsIdentity
;

       
return (from c in
id.Claims
               
select new ViewClaim
                {
                    ClaimType = c.ClaimType,
                    Value = c.Value,
                    Issuer = c.Issuer,
                    OriginalIssuer = c.OriginalIssuer
                }).ToList();
    }
}

The ViewClaim data contract is simply a DTO that holds the claim information.

Next is the WCF configuration – let’s have a look step by step. First I mapped all my http based services to the federation binding. This is achieved by using .NET 4.0’s protocol mapping feature (this can be also done the 3.x way – but in that scenario all services will be federated):

<protocolMapping>
  <add scheme="http" binding="ws2007FederationHttpBinding"
/>
</
protocolMapping
>

Next, I provide a standard configuration for the federation binding:

<bindings>
  <ws2007FederationHttpBinding>
    <
binding
>
      <
security mode="TransportWithMessageCredential"
>
        <
message establishSecurityContext="false"
>
          <
issuerMetadata address="https://server/adfs/services/trust/mex"
/>
        </
message
>
      </
security
>
    </
binding
>
  </
ws2007FederationHttpBinding
>
</
bindings
>

This binding points to our ADFS 2 installation metadata endpoint. This is all that is needed for svcutil (aka “Add Service Reference”) to generate the required client configuration. I also chose mixed mode security (SSL + basic message credential) for best performance. This binding also disables session – you can control that via the establishSecurityContext setting on the binding. This has its pros and cons. Something for a separate blog post, I guess.

Next, the behavior section adds support for metadata and WIF:

<behaviors>
  <serviceBehaviors>
    <
behavior
>
      <
serviceMetadata httpsGetEnabled="true"
/>
      <
federatedServiceHostConfiguration
/>
    </
behavior
>
  </
serviceBehaviors
>
</
behaviors
>

The next step is to add the WIF specific configuration (in <microsoft.identityModel />). First we need to specify the key material that we will use to decrypt the incoming tokens. This is optional for web applications but for web services you need to protect the proof key – so this is mandatory (at least for symmetric proof keys, which is the default):

<serviceCertificate>
  <certificateReference storeLocation="LocalMachine"
                        storeName="My"
                        x509FindType="FindBySubjectDistinguishedName"
                        findValue="CN=Service"
/>
</
serviceCertificate
>

You also have to specify which incoming tokens you trust. This is accomplished by registering the thumbprint of the signing keys you want to accept. You get this information from the signing certificate configured in ADFS 2:

<issuerNameRegistry type="...ConfigurationBasedIssuerNameRegistry">
  <
trustedIssuers
>
    <
add thumbprint="d1 … db"
          name="ADFS"
/>
  </
trustedIssuers
>
</
issuerNameRegistry
>

The last step (promised) is to add the allowed audience URIs to the configuration – WCF clients use (by default – and we’ll come back to this) the endpoint address of the service:

<audienceUris>
  <add value="https://machine/soapadfs/service.svc"
/>
</
audienceUris
>

OK – that’s it – now we have a basic WCF service that uses ADFS 2 for authentication. The next step will be to set-up ADFS to issue tokens for this service. Afterwards we can explore various options on how to use this service from a client.

Stay tuned…

(if you want to have a look at the full source code or peek at the upcoming parts – you can download the complete solution here)


IdentityModel
Monday, October 11, 2010 4:39:03 PM UTC  #   

WIF, ADFS 2 and WCF–Part 1: Overview

A lot has been written already about passive federation and integration of WIF and ADFS 2 into web apps. The whole active/WS-Trust feature area is much less documented or covered in articles and blogs.

Over the next few posts I will try to compile all relevant information about the above topics – but let’s start with an overview.

ADFS 2 has a number of endpoints under the /services/trust base address that implement the WS-Trust protocol. They are grouped by the WS-Trust version they support (/13 and /2005), the client credential type (/windows*, /username*, /certificate*) and the security mode (*transport, *mixed and message). You can see the endpoints in the MMC console under the Service/Endpoints page. So in other words, you use one of these endpoints (which exactly depends on your configuration / system setup) to request tokens from ADFS 2.

The bindings behind the endpoints are more or less standard WCF bindings, but with SecureConversation (establishSecurityContext) disabled. That means that whenever you need to programmatically talk to these endpoints – you can (easily) create client bindings that are compatible.

Another option is to use the special bindings that come with WIF (in the Microsoft.IdentityModel.Protocols.WSTrust.Bindings namespace). They are already pre-configured to be compatible with the ADFS endpoints. The downside of these bindings is, that you can’t use them in configuration. That’s definitely a feature request of mine for the next version of WIF.

The next important piece of information is the so called Federation Service Identifier. This is the value that you (at least by default) have to use as a realm/appliesTo whenever you are requesting a token for ADFS (e.g. in  IdP –> RSTS scenario). Or (even more) technically speaking, ADFS 2 checks for this value in the audience URI restriction in SAML tokens. You can get to this value by clicking the “Edit Federation Service Properties” in the MMC when the Service tree-node is selected.

OK – I will come back to this basic information in the following posts. Basically I want to go through the following scenarios:

  • ADFS in the IdP role
  • ADFS in the R-STS role (with a chained claims provider)
  • Using the WCF bindings for automatic token issuance
  • Using WSTrustChannelFactory for manual token handling

Stay tuned…


IdentityModel
Monday, October 11, 2010 12:40:58 PM UTC  #   
 Wednesday, September 29, 2010

Developer minded Certificate Management Tool

Fellow Developer Security MVP Raffaele Rialdi just released a tool that makes common developer tasks related to certificate a little easier.

His tools e.g. supports setting ACLs on private keys, copying thumbprints and generating WCF <identity /> elements.

Nice work! Download here.


Tools
Wednesday, September 29, 2010 5:22:49 AM UTC  #   
 Friday, September 17, 2010

BASTA!

Wir freuen uns alle schon riesig auf die BASTA! nächste Woche in Mainz.

Thinktecture ist dieses Mal vollständig vertreten und Christian, Jörg und ich haben ne nagelneue Demo-Anwendung, die wir am Freitag im Workshop zum ersten Mal öffentlich zeigen werden…spannend…

Thinktecture Timetable: http://weblogs.thinktecture.com/cnagel/2010/08/basta.html

cu


Conferences
Friday, September 17, 2010 10:42:40 AM UTC  #   
 Sunday, September 12, 2010

StarterSTS v1.5 CTP

I just uploaded a new version of StarterSTS to Codeplex. There have been some dramatic changes since the last public version, so any feedback would be appreciated.

This new version is now a .NET 4.0 web application project, and includes all the necessary plumbing and configuration to deploy StarterSTS to Azure. In fact it is just a configuration change to choose between the Azure and on-premise version.

Download: http://startersts.codeplex.com/releases/view/52214

More info: Moving StarterSTS to the (Azure) Cloud


IdentityModel
Sunday, September 12, 2010 7:51:21 AM UTC  #   
 Saturday, September 11, 2010

Fiddler Inspector for Federation Messages

Fiddler is a very useful tool for troubleshooting all kinds of HTTP(s) communications. It also features various extensibility points to make it even more useful.

Using the inspector extensibility mechanism, I quickly knocked up an inspector for typical federation messages (thanks for Eric Lawrence btw). Below is a screenshot for WS-Federation.

I also added support for SAML 2.0p request/response messages:

The inspector can be downloaded from the identitymodel Codeplex site. Simply copy the binary to the inspector folder in the Fiddler directory.


IdentityModel
Saturday, September 11, 2010 4:33:52 PM UTC  #   
 Saturday, August 14, 2010

Access Control Service v2

A Resource-STS (others call it RP-STS or federation gateway) is a necessity for non-trivial federated identity scenarios. ADFS v2 does an excellent job in fulfilling that role – but (as of now) you have to run ADFS on-premise.

The Azure Access Control Service is a Resource-STS in the cloud (with all the usual scalability/availability) promises. Unfortunately a lot of (the more interesting) features in ACS v1 had to be cut due to constrained time/resources.

The good news is that ACS v2 is now in CTP and brings back a lot of the missing features (like WS* support) and adds some really sweet new ones (out of the box federation with Google, Facebook, LiveID – and OpenId in general). You can read about the details here.

On a related note – ACS v2 works out of the box with StarterSTS – simply choose the ADFS v2 option and point the management portal to the StarterSTS WS-Federation metadata endpoint. Have fun ;)


IdentityModel
Saturday, August 14, 2010 5:20:36 PM UTC  #   
 Thursday, August 12, 2010

Moving StarterSTS to the (Azure) Cloud

Quite some people asked me about an Azure version of StarterSTS. While I kinda knew what I had to do to make the move, I couldn’t find the time. Until recently.

This blog post briefly documents the necessary changes and design decisions for the next version of StarterSTS which will work both on-premise and on Azure.

Provider
Fortunately StarterSTS is already based on the idea of “providers”. Authentication, roles and claims generation is based on the standard ASP.NET provider infrastructure. This makes the migration to different data stores less painful. In my case I simply moved the ASP.NET provider database to SQL Azure and still use the standard SQL Server based membership, roles and profile provider.
In addition StarterSTS has its own providers to abstract resource access for certificates, relying party registration, client certificate registration and delegation. So I only had to provide new implementations. Signing and SSL keys now go in the Azure certificate store and user mappings (client certificates and delegation settings) have been moved to Azure table storage.
The one thing I didn’t anticipate when I originally wrote StarterSTS was the need to also encapsulate configuration. Currently configuration is “locked” to the standard .NET configuration system. The new version will have a pluggable SettingsProvider with versions for .NET configuration as well as Azure service configuration. If you want to externalize these settings into e.g. a database, it is now just a matter of supplying a corresponding provider.
Moving between the on-premise and Azure version will be just a matter of using different providers.

URL Handling
Another thing that’s substantially different on Azure (and load balanced scenarios in general) is the handling of URLs. In farm scenarios, the standard APIs like ASP.NET’s Request.Url return the current (internal) machine name, but you typically need the address of the external facing load balancer.
There’s a hotfix for WCF 3.5 (included in v4) that fixes this for WCF metadata. This was accomplished by using the HTTP Host header to generate URLs instead of the local machine name. I now use the same approach for generating WS-Federation metadata as well as information card files.

New Features
I introduced a cache provider. Since we now have slightly more expensive lookups (e.g. relying party data from table storage), it makes sense to cache certain data in the front end. The default implementation uses the ASP.NET web cache and can be easily extended to use products like memcached or AppFabric Caching.
Starting with the relying party provider, I now also provide a read/write interface. This allows building management interfaces on top of this provider. I also include a (very) simple web page that allows working with the relying party provider data. I guess I will use the same approach for other providers in the future as well.
I am also doing some work on the tracing and health monitoring area. Especially important for the Azure version.

Stay tuned.


IdentityModel
Thursday, August 12, 2010 4:21:52 AM UTC  #   
 Wednesday, August 11, 2010

StarterRP v1.2

A small update for StarterRP is now live on codeplex.

This version is based on .NET v4 and includes two sample Silverlight clients. Major update to StarterSTS coming soon…


IdentityModel
Wednesday, August 11, 2010 5:16:44 PM UTC  #   
 Saturday, July 24, 2010

WIF, ASP.NET 4.0 and Request Validation

Since the response of a WS-Federation sign-in request contains XML, the ASP.NET built-in request validation will trigger an exception. To solve this, request validation needs to be turned off for pages receiving such a response message.

Starting with ASP.NET 4.0 you can plug in your own request validation logic. This allows letting WS-Federation messages through, while applying all standard request validation to all other requests. The WIF SDK (v4) contains a sample validator that does exactly that:

public class WSFedRequestValidator : RequestValidator
{

    protected override bool IsValidRequestString(
      HttpContext context,
      string value,
      RequestValidationSource requestValidationSource,
      string collectionKey,
      out int validationFailureIndex)
    {
        validationFailureIndex = 0;


        if ( requestValidationSource == RequestValidationSource.Form &&
             collectionKey.Equals(
               WSFederationConstants.Parameters.Result,
               StringComparison.Ordinal ) )
        {
            SignInResponseMessage message =
              WSFederationMessage.CreateFromFormPost(context.Request)
               as SignInResponseMessage;

            if (message != null)
            {
                return true;
            }
        }

        return base.IsValidRequestString(
          context,
          value,
          requestValidationSource,
          collectionKey,
          out validationFailureIndex );
    }
}

Register this validator via web.config:

<httpRuntime requestValidationType="WSFedRequestValidator" />


IdentityModel
Saturday, July 24, 2010 8:14:36 AM UTC  #   
 Thursday, July 22, 2010

StarterSTS v1.2

I just uploaded version 1.2 of StarterSTS. This is simply a conversion of v1.1 to a web application project. Some people have asked for it so here we go.

This version is still compiled against .NET 3.5 SP1 – but this will the last release. All upcoming releases will be .NET 4.0.

Codeplex Site



Thursday, July 22, 2010 9:23:30 AM UTC  #   
 Wednesday, July 21, 2010

IIS & RESTful Services #FAIL

really? when will super duper IIS finally support non-Windows accounts for HTTP authentication?

http://blogs.msdn.com/b/astoriateam/archive/2010/07/21/odata-and-authentication-part-6-custom-basic-authentication.aspx

see here for a complete module including IIS management integration:

http://custombasicauth.codeplex.com


IIS | WCF
Wednesday, July 21, 2010 8:39:18 PM UTC  #   
 Tuesday, July 20, 2010

Re-MVP’d 2010

As always: thank you Microsoft!


Misc
Tuesday, July 20, 2010 5:33:43 AM UTC  #   
 Tuesday, June 22, 2010

Modifying the SL/WIF Integration Bits to support Issued Token Credentials

The SL/WIF integration code that ships with the Identity Training Kit only supports Windows and UserName credentials to request tokens from an STS. This is fine for simple single STS scenarios (like a single IdP). But the more common pattern for claims/token based systems is to split the STS roles into an IdP and a Resource STS (or whatever you wanna call it).

In this case, the 2nd leg requires to present the issued token from the 1st leg – this is not directly supported by the bits. But they can be easily modified to accomplish this.

The Credential
Fist we need a class that represents an issued token credential. Here we store the RSTR that got returned from the client to IdP request:

public class IssuedTokenCredentials : IRequestCredentials
{
    public string IssuedToken { get; set; }
    public RequestSecurityTokenResponse RSTR { get; set; }

    public IssuedTokenCredentials(RequestSecurityTokenResponse rstr)
    {
        RSTR = rstr;
        IssuedToken = rstr.RequestedSecurityToken.RawToken;
    }
}

The Binding
Next we need a binding to be used with issued token credential requests. This assumes you have an STS endpoint for mixed mode security with SecureConversation turned off.

public class WSTrustBindingIssuedTokenMixed : WSTrustBinding
{
    public WSTrustBindingIssuedTokenMixed()
    {
        this.Elements.Add( new HttpsTransportBindingElement() );
    }
}

WSTrustClient
The last step is to make some modifications to WSTrustClient to make it issued token aware. In the constructor you have to check for the credential type, and if it is an issued token, store it away.

private RequestSecurityTokenResponse _rstr;
public WSTrustClient( Binding binding, EndpointAddress remoteAddress, 
IRequestCredentials credentials )
    : base( binding, remoteAddress )
{
    if ( null == credentials )
    {
        throw new ArgumentNullException( "credentials" );
    }

    if (credentials is UsernameCredentials)
    {
        UsernameCredentials usernname = credentials as UsernameCredentials;
        base.ChannelFactory.Credentials.UserName.UserName = usernname.Username;
        base.ChannelFactory.Credentials.UserName.Password = usernname.Password;
    }
    else if (credentials is IssuedTokenCredentials)
    {
        var issuedToken = credentials as IssuedTokenCredentials;
        _rstr = issuedToken.RSTR;
    }
    else if (credentials is WindowsCredentials)
    { }
    else
    {
        throw new ArgumentOutOfRangeException("credentials", "type was not expected");
    }
}

Next – when WSTrustClient constructs the RST message to the STS, the issued token header must be embedded when needed:

private Message BuildRequestAsMessage( RequestSecurityToken request )
{
    var message = Message.CreateMessage(
base.Endpoint.Binding.MessageVersion ?? MessageVersion.Default,
      IssueAction,
      (BodyWriter) new WSTrustRequestBodyWriter( request ) );

    if (_rstr != null)
    {
        message.Headers.Add(new IssuedTokenHeader(_rstr));
    }

    return message;
}

HTH


IdentityModel
Tuesday, June 22, 2010 6:45:17 AM UTC  #   
 Thursday, June 10, 2010

StarterSTS 1.1

Earlier today I uploaded StarterSTS 1.1 and StarterRP 1.1 to codeplex.

I added identity delegation for internal as well as OpenID accounts and also updated StarterRP to show these features.

I also recorded an updated screencast on delegation since some of the config settings have changed since the CTP.


IdentityModel
Thursday, June 10, 2010 8:07:49 AM UTC  #