Wednesday, May 27, 2015

ADFS : OpenID Connect

This is for ADFS vNext or ADFS 4.0 running on Windows Server 2016 (Technical Preview at the moment).

One of the new features is that support for OpenID Connect has been enabled.

I tried a number of clients (including Postman) and couldn't get any of them to work so I had to write my own.

Except that Dominick has already done most of the work - refer Writing an OpenID Connect Web Client from Scratch.

Fantastic - except that Github link doesn't work.

The revised one in the comments does but it is to the whole sample and it's not obvious which one to use. In fact, it's this:

Clients/MvcFormPostClient

Download all the samples because that's what the VS .sln file references.

It compiled no problem with VS 2013 on my PC.

Now if you've used Dominick's samples before, you'll know that they reference Dominick's environment so you have to ferret out all the references and change them,

But before we do that we have to find out what they are.

I run up the Technical Preview 2 in an Azure VM using my MSDN subscription. I then made it a forest of one by promoting the server to a DC so now I have AD, checked I have a certificate, created a service account and installed ADFS as a service exactly like Server 2012 R2.

(Note - after creating the Azure VM, you have to add endpoints for ports 80 and 443!).

In ADFS, click the Client tab and then "Add new OAuth Client". You need to set the settings as below because that's what the sample uses. "Name" can be anything.


Also of interest is the "Scope Descriptions":


These are the only scopes that are recognised by default.

You'll see the sample uses scopes "openid" and "email".

Back to VS,

In the Constants,cs file (part of the larger project), you need to edit for your endpoints:

public static class Constants
    {
        //public const string BaseAddress = "https://localhost:44333/core";
        public const string BaseAddress = "https://ADFS.local/adfs";
        
        //public const string AuthorizeEndpoint = BaseAddress + "/connect/authorize";
        public const string AuthorizeEndpoint = BaseAddress + "/oauth2/authorize";
        public const string LogoutEndpoint = BaseAddress + "/connect/endsession";
        //public const string TokenEndpoint = BaseAddress + "/connect/token";
        public const string TokenEndpoint = BaseAddress + "/oauth2/token";
        public const string UserInfoEndpoint = BaseAddress + "/connect/userinfo";
        public const string IdentityTokenValidationEndpoint = BaseAddress + "/connect/identitytokenvalidation";
        public const string TokenRevocationEndpoint = BaseAddress + "/connect/revocation";

        public const string AspNetWebApiSampleApi = "http://localhost:2727/";
    }

Note that the ADFS OAuth2 endpoint is .../adfs/oauth2/authorize and similarly for token as above.

Houston - we have a problem with the ValidateIdentityTokenAsync method in the AccountController class.

The Github code does not match the code in the above link.

There was a later post - refer Using Discovery and Katana Middleware to write an OpenID Connect Web Client - and this matches the Github code.

In that code, you'll see:

var certString = "MIIC4jCCA..."

OK - see where does my certificate info. come from?

As per that post, it comes from:

https://ADFS.local/adfs/.well-known/openid-configuration

which returns JSON like:

{

    "issuer": "https://ADFS.local/adfs",
    "authorization_endpoint": "https://ADFS.local/adfs/oauth2/authorize/",
    "token_endpoint": "https://ADFS.local/adfs/oauth2/token/",
    "jwks_uri": "https://ADFS.local/adfs/discovery/keys",
    "token_endpoint_auth_methods_supported": 

[

    "client_secret_post",
    "client_secret_basic",
    "private_key_jwt",
    "windows_client_authentication"

],
"response_types_supported": 
[

    "code",
    "id_token",
    "code id_token",
    "token id_token"

],
"response_modes_supported": 
[

    "query",
    "fragment",
    "form_post"

],
"grant_types_supported": 
[

    "authorization_code",
    "refresh_token",
    "client_credentials",
    "urn:ietf:params:oauth:grant-type:jwt-bearer",
    "implicit",
    "password"

],

and more - this is truncated. But nowhere in the JSON is there any certificate information.

The key is this line as above.

"jwks_uri": "https://ADFS.local/adfs/discovery/keys"

Browse to that URL and you'll see a "x5c" section:

x5c": [ 
"MIIC4j... 
]

That Base64 string is what you paste into your code.for "var certString =".

And then you should be good to go.

Run the application, it will take you to the normal ADFS logon screen where you authenticate and then you will see:


If you use some sort of trace like "SAML Tracer" or Fiddler, you'll see a line like:


Now if you copy and paste this into a JSON viewer like:

http://jwt.io/

you'll see the same thing.

Enjoy!

Monday, May 25, 2015

Misc : Citrix Receiver on Firefox

I do a lot of work for customers and to do that I need remote access to their servers.

The VPN tool of choice these days seems to be Citrix Receiver.

If you are experiencing problems with FireFox i.e. you can login and get the portal but when you click on one of the icons e.g. desktop or remote desktop and you see the little wheel spin for a few moments and then stop and then nothing happens, try this:

Tools / Options / Applications


Ensure that "Connection Manager" is selected and not "Receiver".

Enjoy!

Friday, May 22, 2015

ADFS : Installing ApacheDS

Huh - what does ApacheDS have to do with ADFS?

I'm looking at Server Technical Preview 2 - aka Server 2016 - with ADFS 4.0.

This has the ability to use an LDAP as an alternative authentication source. So I decided to use ApacheDS.

I'm running on Windows. I ran up an Azure VM preconfigured with the image from the gallery using my MSDN subscription. I used Basic / A1 in SE Asia. I initially tried Australia as it's geographically closer but that was too damn slow - almost unusable.

Because I have ADFS and that needs AD, I also made that VM a DC in a forest of one. That also means that port 389 is now used.

Also, somewhat disappointed that you have to have AD. When I first read the announcement, I thought that ADFS could now authenticate against an LDAP without AD. That's what a lot of my customers have. I suppose you could always run up a "dummy" AD.

The thinking seems to be that you use AD for internal user authentication and the LDAP for external user authentication

Good article here: Getting started with ApacheDS – LDAP Server and Directory Studio.
  • Install Java. 
  • Remember the Java Home directory.
  • Install ApacheDS - will ask for the Home directory,
  • Install Directory Studio - will ask for the Home directory.
And then?

Found the answer in the above article:

"Set Bind DN or User to the value uid=admin,ou=system and Bind password to secret."

Note the port is 10389.

And then I was away.

More soon.

Enjoy!

Tuesday, May 19, 2015

ADFS : Getting the latest updates

The Windows Update with ADFS doesn't always seem to work so I use this Google search string to find the latest updates and hotfixes.

This particular example is for ADFS 3.0 (Server 2102 R2) but you can easily adapt for any version.

("server 2012 r2" OR "fs 3.0") (update OR hotfix) (adsf OR "ad fs" OR "active directory federation services")  site:support.microsoft.com

The "Site" command restricts the search to that site only.

It's one of those handy Google search tips like:

auckland -"north shore"

will search for Auckland but ignore any with the words "north shore".

Enjoy!

Thursday, May 14, 2015

Visual Studio : No STS tool

Inspired by this question on stackoverflow regarding the missing STS tool in VS 2013:

Add sts reference missing in visual studio 2013 update 4

From my answer:

"FedUtil and the "Identity and Access Tool" are no longer available.

The only way to do this is via "Change Authentication" when you create the project and then select "On Premise". Unfortunately, you can only do this when you create the project. You can't retrofit it afterwards. I believe this is changing in VS 2015.

Part of the reason for the tools disappearing is that these tools were WIF based whereas OWIN is the basis for all new VS development.

You can merge the WIF section from the web.config of an old WIF project"

So how do you do the last part.

Create a new project in VS 2013 - I choose MVC - and under "Change Authentication" select "No authentication".

Now find a VS2012 project of yours that uses WIF - with .NET 4.5

Use something like WinMerge and merge the two web.config.

Copy these over:

<configSections>
    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
    <section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
</configSections>


<system.web>
    <authentication mode="None" />
    <authorization>
      <deny users="?" />
    </authorization>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  </system.web>


<system.webServer>
    <modules>
      <add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
      <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
    </modules>
  </system.webServer>

as well as the "ida:" lines under appSettings

and the entire system.identitymodel and system.identitymodel.services sections.

Obviously you need to update the URL of your target application .( I assume your IDP and certificates are still the same and are still valid otherwise you need to update them as well).

Add References to:

  • System.IdentityModel
  • System.IdentityModel.Selectors
  • System.IdentityModel.services

Add a NuGet package from Package Manager:

Install-Package System.IdentityModel.Tokens.ValidatingIssuerNameRegistry -Version 4.5.0

and you are done.

Enjoy!

Wednesday, May 13, 2015

Musings : If you were stranded on a desert island, what three technical books would you have?

I asked this question in a previous post regarding career development.

And then got asked what my answer would have been?

So in no particular order:


And an honourable mention:

The Soul Of A New Machine

And a second honourable mention:

The Art Of Computer Programming

It's sad that these are older books. Where are the modern day equivalents?

Enjoy!

Monday, May 11, 2015

Musings : You need to expand your career

Been doing a bunch of interviews lately and what alarmed me was the number of people who do absolutely nothing wrt. professional development or expanding their career.

Time after time, I asked "Do you keep up with any blogs"? only to get a blank stare. Seriously - you're a Microsoft aligned dude and you don't read Scott Gu, Scott Hanselman. Jon Skeet, Mat Velloso et al?

So actually all you do is drag yourself into work from 9:00 to 5:00?

Do you attend any meetups - you didn't know of any? Just Google Meetups and prepare to be amazed. And it's not just the technical stuff or the pizza and beer - it's also the networking and meeting people - can't tell you how many people I've met because I go to user groups.

"If you were stranded on a desert island, what three technical books would you have"?

Seriously, you can't name one? Not one book?

Watch sessions on Pluralsight? No - don't really get the time.

Can't afford Pluralsight? Fair point - what about Microsoft Virtual Academy?

So you don't read blogs, don't go to user groups, don't read books, don't watch Pluralsight / MVA?

Move on dude into the backwater of your mediocrity - no opportunities here.

Make a resolution - from now on. I will read one blog entry a day, watch one online session a month and read a book every three months. You might even surprise yourself :-) Just do it!

And next time I might even offer you a job!

Enjoy!

Monday, May 04, 2015

SSO : Using Salesforce as an IDP

Had a number of questions around this lately and thought I would write this up.

The use case is that you have an existing Salesforce account and you want to use this to authenticate against an application.

Note that Salesforce federates using SAML.

Points to do this:
  • Hook up ADFS as the RP (SP in SAML speak) and Salesforce as the IDP using SAML
  • I don't believe you can do this with Azure AD. That's because AAD is always the IDP and everything else is the SP. That's how Salesforce out the SaaS back-end of AAD works i.e. access via the Access Panel / myapps.
  • Use Auth0 as in SAML : ASP.NET MVC application talking to SAML IDP . In this scenario, you are using the Auth0 Enterprise connection and configuring the SAML parameters similar to the ADFS example.
  • Use Auth0 but in this case use Salesforce as in the "Third Party App". Here Auth0 does some of the heavy lifting for you but the end result is the same.
Note: Auth0 does have a neat "Salesforce Configuration Instructions" tutorial available when you configure Salesforce as a "Third Party App" but it doesn't seem to be publicly available. The document doesn't tell you what to do on the client side. You need to add Salesforce to the Lock widget under "Connections / Social".

Enjoy!

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!