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). (aka Active Directory Federation Services or "AD FS").

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 and hotfixes

This is for Active Directory Federation Services / "AD FS".

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".

Also, came across this link:

Updates for Active Directory Federation Services (AD FS)

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!