Thursday, April 23, 2015

stackoverflow : People reached

I help a lot of people over at SO and the MSDN forums. The new user pages show how many people your answers, comments etc. have reached.


1.8 million. Pretty neat!

Slowly closing on that magic 20,000 rep. mark when you have all rights. Nice to see that I've worked my way up over the years to get into the top 2%.

Enjoy!

Postman : Testing ASP.NET MVC Webapi

I've been looking at Postman.

It's a way of easily testing REST API.

So to play around with it, I thought I would test it against the standard ASP.NET MVC webapi project using VS 2013.

So run up a ASP.NET MVC webapi VS project in the usual way. Under ValuesController.cs, you'll see the standard API calls.

// GET api/values
        public IEnumerable Get()
        {
            return new string[] { "value1", "value2" };
        }

So http://xxx/api/values will return an array of the two values above.

So let's try:


Notice we need to select "GET" from the drop-down. You see the values returned as expected. You can select the format i.e. this is JSON. The "Status" is "200 OK". If you hold the cursor over this, you get a description of what the status means. Neat!

OK, let's try a PUT.

I changed the code to look like:

// PUT api/values/5
        public String Put(int id, [FromBody]string value)
        {
            return ("ID was " + id + " value was " + value);
        }

Remember to select "PUT" in the drop-down. If you select "Preview", you'll see what the HTTP message that is sent is.

Notice we get the ID but not the value. There's a ton of stuff on the Internet on this particular subject.

So let's select the "Raw" button, select "Text" from the drop-down, type in some text and press "Send".

You get the "No MediaTypeFormatter is available" message.

You can fix this via C# – Supporting text/plain in an MVC 4 Web API application.

Go and add that - I'll wait.

All done? - let's proceed.


All A-OK!

Note: There is an Interceptor feature which you can add to Postman. Running my website locally, I could only get this to work with the Interceptor turned off. Otherwise, it just hangs.

Enjoy!

Wednesday, April 15, 2015

SAML : ASP.NET MVC application talking to SAML IDP

By popular demand (yeah - all two of you!) I've expanded my previous post for a .MVC application.

SAML : .NET application talking to SAML IDP

Login to the Auth0 dashboard, create a new application.

Choose "Regular Web App." / ASP.NET.

You get a tutorial called "Using Auth0 with ASP.NET".

Make a project in VS - follow the tutorial.

I don't like IIS Express so I run in IIS but that's up to you.

If you logged in to the Auth0 dashboard, you see that the tutorial is pre-configured with the web.config settings. Neat!

Add the JS code for the widget somewhere - I just added it to the Contact page.

My callback URL is e.g.:

https://xxxWebApplication/LoginCallback.ashx

Remember to place this in the JS code (replace the dummy string there) and in the application entry in your dashboard under "Allowed Callback URLs".

Under Connections, remember to tick the ADFS-SAML entry as described in the previous blog entry referenced above.

OK - navigate to the website - Contact page - Login button. I only have the ADFS-SAML connection configured.



Make sure you have the SAML tracer tool enabled.

OK - click the login button - off to ADFS.

Authenticate.

(Note: If you get "Object reference not set to an instance of an object". it's probably because of proxy problems).

Now look at the SAML trace - you'll see a few orange SAML buttons - proving that you are talking to ADFS via SAML!



If you look at the LoginCallback,ashx.cs, you'll see code at the bottom to turn the JWT to a cookie ala the normal WIF SAML token flow. 

You can display this using the standard .NET WIF features (built into .NET 4.5) e.g.

How To: Build Claims-Aware ASP.NET MVC Web Application Using WIF

Remember to set the redirect at the bottom of the callback page.
context.Response.Redirect("Home/Contact");
 or whatever.

Enjoy!
 

 

 

Monday, April 13, 2015

SAML : .NET application talking to SAML IDP

I've blogged about this before viz:

SAML : SAML connectivity / toolkit

and the links inside that post.

The general problem is that you have a .NET application and you have a use case that requires you to authenticate with a SAML IDP.

There are two general approaches:
  • Add a SAML client side stack
  • Use something like ADFS as a bridge i.e. app --> WS Fed --> ADFS --> SAML --> IDP.
 Note that when I talk about SAML I refer to SAML-P (the protocol) as opposed to SAML (the token).

But then I came across Auth0.

This has an interesting approach. Instead of having many applications taking to many Identity repositories  (perhaps many-to-many - the spider's web scenario) , they have Identity aaS and each component has one connection into the circle. You then hook all the connections up with internal plumbing.

Internally, everything uses OpenID Connect. They also have something similar to the FIM metaverse concept i.e. a standard profile where they keep the essential information and that links all the different user identities together. So one profile holds that user's information for their Facebook, Twitter, ASP.NET Identity etc logins.

So how does this help the problem?

Auth0 provide a login widget (that they call Lock) that can be easily referenced by Javascript, code etc. This widget uses OpenID connect. The .NET applications uses this to get into the circle and then you configure another connection out of the circle which uses SAML to talk to the IDP. You then hook the two connections together.

Conceptually:

App --> OpenID Connect --> Auth0 --> SAML --> SAML IDP.

Now ADFS supports SAML-P so lets hook this all up as an exercise.

Following assumes you have an Auth0 developer account - which is free.

Auth0 has a number of samples on Github.

You can search for a MVC sample but for this particular investigation, I was interested in what Microsoft call a native device i.e. non-browser based. Mobile is a good example but so is command line or Windows Forms or WPF. There is a Forms / WPF example here.

In the example, where it says:

var auth0 = new Auth0Client(
   "{YOUR_AUTH0_DOMAIN}",
   "{YOUR_CLIENT_ID}");

You get these by creating a new App / API in the dashboard, Select:

Native Mobile App and then WPF / WinForms as the SDK Skip the Backend Platform.

You then get a tutorial. One neat thing is that if you log into the dashboard beforehand, all the tutorials are customised for your Auth0 domain and settings.The tutorial contains the settings you need, otherwise they are in the application settings for your application in the dashboard.

If you were looking for ASP.NET MVC, note that the only difference to the Forms / WPF approach is how you hook up to the widget i.e. you would use Javascript instead of C#. All the plumbing / configuration as below is identical.

Let's hook up the SAML.


Connections / Enterprise / SAML-P Identity Provider / Create New



You can give the connection any name you want and the URL's are the standard:

https://xxx/adfs/ls/

We'll ignore signing the request for now.

Now for the certificate:

ADFS wizard / Service / Certificates / right-click on Token-Signing / View certificate / Details tab / Copy to file

Choose Base 64 Encoded X509 (.CER)

Save this somewhere and then click "Upload Certificate" as above and upload it to Auth0.

Auth0 use a domain matching way to handle the typical Home Realm Discovery. In the "Email Domains" box above, enter a domain. This does not have to be a valid domain - just something that you can match on e.g. mysaml.co.nz. Yeah - I'm not wild about this either!

Now for the ADFS side - click on your new connection and then click the pencil (Setup). This shows the Auth0 endpoints or you can use the metadata link.

I just configured ADFS manually because I've done this so many times.

ADFS wizard / Trust Relationships / Relying Party Trusts / Add Relying Party Trust.

Going through the wizard:

Start / Enter data about the relying party manually / Next / Type any name you want / Next / AD FS profile / Next / ignore encryption so Next / Check enable support for SAML protocol- enter URL as below / Next / enter identifier as below / Add / Next / ignore MFA so Next / Permit all users / Next / Next / Close






Again, note that the strings above will reflect your Auth0 tenant and connection name.

Didn't bother with a signature because we are not signing the AuthnRequest. Note that these reflect the name I chose i.e. ADFS-SAML. You will use your name as reflected in the Auth0 endpoints.

Now edit the claims rules so they look like:




Now if you go back to your SAML connection in the Auth0 dashboard, you can click on the Try icon (the arrowhead) and if all goes well, it will come up with "It Works!". 



OK - so fire up the WPF application.



Enter e.g. joeb@mysaml.co.nz. This matched the Auth0 configuration so the Lock widget brings up the "Log in to mysaml.co.nz"

(BTW, if you are wondering about the social icons in the widget, this is configured in your application under Connections).

Click this and you will be redirected to ADFS where you can login as usual. Because you configured this to use SAML you now have a .NET application using SAML to authenticate. Neat!

Don't believe me? If you went with a standard MVC application and use FireFox, download the SAML tracer and run it (under Tools). Clear all your cookies, login in again and you'll see some of the entries in the trace have an orange SAML button.

Update: I wrote this up:

SAML : ASP.NET MVC application talking to SAML IDP

(BTW: I don't work for Auth0).

Enjoy!

Tuesday, March 31, 2015

Visual Studio : Missing metadata

Out of the blue, starting getting:

Metadata file '...\abc\xyz.dll' could not be found

Look in the folder - there it is - WTF?

Mr. Google and figured out that something had changed in my build order.

To get the build order, right click the solution - "Project Build Order".

Then build all the dll first and then the projects that consume the .dll.

You can do this by playing around with the dependencies.

Enjoy!

Friday, March 13, 2015

ASP.NET : Could not load file or assembly

For example:

"Could not load file or assembly System.Web.Http.WebHost, Version=4.0.0.0".

Came to work one morning, built my system, WTF, error as above.

All worked perfectly when I left the day before.

There had been a Windows Update during the night and obviously some dll's had been updated - so much for backward compatibility.

Problem was - I couldn't figure out who was calling this dll and hence where the reference / binding was

Mr. Google and came across this Scott Hansleman post:

Back to Basics: Using Fusion Log Viewer to Debug Obscure Loader Errors

I'm using VS 2013 and Windows 8.1.

So go to:

C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\Shortcuts

This is the shortcut to the VS Command Line Tool - "Developer Command Prompt for VS2013".

In the command line - fuslogvw.exe - run as Administrator.

In Settings - "Log bind failures to disk" / "Enable custom log path". Type in path - make sure the path exists.

Restart IIS.

Navigate to your web site - get the error - back to the tool - click "Refresh" - BOOM.

You will also notice that the text on the ASP.NET error page is different - it doesn't talk about the regedit change.

To repeat - if you use the tool you don't have to screw around with registry settings.

When you are done, remember to disable the log via the tool as it slows everything down.

Enjoy!


Wednesday, March 11, 2015

WIF : WIF10201: No valid key mapping

The full error is:



WIF10201: No valid key mapping found for securityToken: 'System.IdentityModel.Tokens.X509SecurityToken' and issuer: 'http://xxx/adfs/services/trust'.


This is with ADFS 3.0 and the base VS 2013 with ASP.NET MVC.

Long discussion with Mr. Google - many entries, many explanations - "remove the trailing slash" , blah, blah, the most bizarre was "This is because WIF doesn't support SAML".

Yes - that statement's true but WTF does it have to do with the problem?

Google quality is getting exponentially worse and worse.

I knew this error rang a bell and after some quite reflection I remembered why. Vittorio had mentioned it:


His article didn't apply in my case because I get the error straight away - the home page doesn't display so there's no "Sign up for this application" link.

The article goes on to say that this "issue will be fixed soon".

So I took a punt and upgraded to VS 2013 Update 4.

Created a new project - problem solved.

Enjoy!

Friday, March 06, 2015

ADFS : Legacy IE, legacy OS and ADFS 3.0

This is the ADFS that runs on Server 2012 R2.

Been busy with a project that has some legacy components.

Firstly - XP.

No longer supported and full of security holes. In particular, it does not support SNI (Server Name Indication).

To get ADFS 3.0 to work, refer:

How to support non-SNI capable Clients with Web Application Proxy and AD FS 2012 R2

ADFS 3.0 login failing from IE8

IE8 is the last incantation of IE on XP.

If you use a later OS e.g. Windows 7 and you play in the identity space with federation and lots of redirects, you may find IE 8 reporting "Internet Explorer cannot display the webpage".

This is because IE 8 has a redirect limit of 10 which is fine for a normal web site but not fine for the SSO browser profile which is based on redirects i.e.

User --> Application --> IDP1 --> IDP2 --> IDP 3 etc and then the rollback all the way down.

If the application is SharePoint, that alone has 3 to 4 redirects.

There is a "fix" but it involves regedit which is per machine and not something suitable for the average user,

Far better to upgrade IE or use another browser.

Enjoy!

Thursday, February 19, 2015

ADFS : RPUrl and SharePoint

I blogged previously about how you get the RPUrl field in the wctx field to see the originator of the message.

Normally for a .NET application, you'll see:

wctx: RPUrl=https://domain/application...

However, for SharePoint, you configure two identifiers in ADFS i.e.

https://domain/application/_trust/
urn:sharepoint:application

ADFS uses the urn in the RPUrl, so you'll see:

wctx: RPUrl=urn:sharepoint:application...

Which is a pain is you have to support both.

Enjoy!

Tuesday, February 10, 2015

IIS : Application pool service account

IIS web sites run under application pools and if you look under "Advanced settings" you see an application pool runs under an Identity.

This Identity can be a number of accounts e.g. ApplicationPoolIdentity or NetworkService. But you can also set your own service account under "Custom account".

I needed to do this but kept getting:

"The specified password is invalid.Type a new password."

WTF?

Had a conversation with Mr. Google. Seriously - about the only probable cause not mentioned was the proverbial kitchen sink!

Then I realised that this was a domain account so I needed to type:

domain\account

Bang! Problem solved - sometimes we keep getting confused by all the trees.

Enjoy!

Thursday, February 05, 2015

ADFS : Claims are URI

Answered this question over on the forum.

But for general interest.

Claims are URI and URL are a subset of URI so you would expect that URI look something like:

http://domain/site

So you can't have a claim type of givenName.

To repeat:

Mapping Given-Name to givenName gives:

System.ArgumentException: ID4216: The ClaimType 'givenName' must be of format 'namespace'/'name'.

Mapping Given-Name to http://givenName gives:

MSIS7012: An error occurred while processing the request. Contact your administrator for details. ---> System.ArgumentException: ID4213: Cannot parse the ClaimType 'http://givenName' into a constituent name and namespace.

Mapping Given-Name to http://company.com/givenName works.

Which makes sense - you can't have a website with a URL of e.g. givenName.

Enjoy!

Wednesday, February 04, 2015

ADFS : What happened to my roles?

Setting up a RP trust with the standard LDAP rule which maps "Token Groups - Unqualified Names" to Roles.

But when I enumerated the claims after RP authentication, some were missing?

WTF? when I do an AD memberOf, it displays them all?

Much  head-scratching and investigation and then I remembered that for this ADFS claims rule only non-local domain security groups are returned.

You can confirm this in ADUC by clicking on the Properties / General tab and looking at the group scope and type.

But what if you are not Domain Admin?

Allow me to recommend AD Explorer.

Tip - just click OK on the first page (don't enter credentials) and it will "find" the default DC.

Then navigate to the security group.

Under the attributes, look for groupType.

It will be something like -2147483646.

As per AD Attributes, this is a Global group.

But my missing Security group displayed  -2147483644 which is Domain Local.

Enjoy!