Monday, November 28, 2016

Postman : Using Postman for Implicit Grant on ADFS 4.0

This is ADFS 4.0 (Server 2016) and you need the official release.

I tried to get this working on the TPx series but no joy.

I kept getting the error:

"MSIS9358: Received invalid OAuth authorization request. The authorization server does not support the response type 'token' for confidential clients."

However, there is an extra entry in the official release which seems to to the job.


When you select this entry, you first get to configure a "Native Application" that generates a ClientID and you need to provide a "Redirect URI" and then an "Access Policy".

You end up with something like:


and you can configure the web application with claims etc.

The "Native Application" seems a bit weird but refer Customizing Id_Token Claims with OpenId Connect in AD FS 2016.

"Behind the scenes, this template creates a native client and new app type called Web application, which is just a Web API with an Identifier (RPID) that matches the native client's client ID. This means the Web application is simultaneously client and resource, so you can assign issuance transform rules as you would with a Web API."

As always, the gist is here.

You need to run this in a browser, The implicit flow returns an access token straight away. You miss out the intermediate step of getting a code and then using that for an access token. It's normally used for SPA where JavaScript is involved. Hence no security key is required as that would be easy to access.

If you look at the access token with e.g. jwt.io, you see:


Notice the "apptype" is "Public" and this is what is required for this flow. Hence the error about "confidential clients".

Enjoy!

Wednesday, November 23, 2016

ADFS : Metadata on ADFS 4.0

This is on Server 2016.

I've had a number of questions around compatibility e.g. can ADFS 3.0 federate with ADFS 4.0?

The servers are very different e.g. 2016 has containers, full OpenID Connect / OAuth support etc.  but the SAML level on both is still 2.0 so there should be no issues.

As an exercise, I checked the ADFS metadata on both.

Other than the expected differences e.g. federation service name, certificates, ID's etc. there is no difference which bears out the fact that they are compatible.

Enjoy!

Friday, November 11, 2016

Postman : Using Postman for Resource Owner Password Grant on ADFS

This is on Server 2016 TP5 - ADFS 4.0

Couldn't find any examples of this so rolled my own.

As always, the gist is here,

Note that you need the user in the "domain\user" format.

Be careful of this flow  - you are potentially exposing the user name and password.

This is supposed to be for "trusted" clients.

Enjoy!

Postman : OpenID Connect / OAuth errors

This is on ADFS 4.0 on Server 2016 TP5.

Yes, I know the official release is out but I've had other priorities :-)

So some of this may not apply to the official release.

This is based on the Postman collection described here.

While I was trying to get this to work, I encountered a number of errors and quickly established that there is basically zero documentation on any of them.

So I documented as I went along.

There is a authorisation request. This is an https request with a number of parameters and I removed them manually one by one.

Remove client id

MSIS9220: Received invalid OAuth authorization request. The 'client_id' parameter is missing or found empty. The client could not be validated.

Remove "response_type=code"

MSIS7065: There are no registered protocol handlers on path /adfs/oauth2/authorize to process the incoming request.

Remove "redirect_uri=https%3A%2F%2Fmy-pc%2FTodoListWebApp%2F"

MSIS9221: Received invalid OAuth authorization request. The 'redirect_uri' parameter is missing or found empty. Public clients must send the redirect_uri parameter with valid redirect URI in the OAuth authorization request.

This is followed by a REST token request.

This is driven by Postman and one of the nice features of Postman is there is a tick box next to each parameter and if you untick the box, that parameter is not sent.

Remove client_id

MSIS9629: Received invalid Client credentials.'client_secret' was present but 'client_id' parameter is missing or found empty.

Remove code

MSIS9610: The 'code' parameter is not specified. The access token request must contain the 'code' parameter which specifies the previously issued authorization code."

Remove "grant type"

MSIS7065: There are no registered protocol handlers on path /adfs/oauth2/token to process the incoming request.

Remove "client_secret"

MSIS9267: No Client credentials found in the request. Client 'a07...e75' is configured as a confidential client.

Remove "redirect_uri"

MSIS9221: Received invalid OAuth authorization request. The 'redirect_uri' parameter is missing or found empty. Public clients must send the redirect_uri parameter with valid redirect URI in the OAuth authorization request.

MSIS9608: The 'redirect_uri' parameter is not specified. The access token request must contain 'redirect_uri' parameter for public clients

Note there are two slightly different errors here. I noticed this in some other scenarios as well.

The first error is from the ADFS event log i.e. the server side (which is where most of the errors were copied from).

The second is what Postman actually reports i.e. the client side.

I have no idea why they are different?

Enjoy!



Wednesday, November 09, 2016

AAD : Advanced user lifecycle management

Done so much ADFS stuff lately, it's cool to look at Azure AD for a change!

Good overview

So to provision users into Azure AD as per above:

"Azure AD provides automated, advanced user life-cycle management by using dynamic group membership rules and application management capabilities. Here’s more detail:
  • For organisations with on-premises HR, Microsoft Identity Manager establishes user identities in Windows Server Active Directory.
  • For organisations with software as a service (SaaS)–delivered HR, Azure AD currently integrates with Workday.
  • Azure AD Connect syncs users and groups between Windows Server Active Directory and Azure AD.
  • Azure AD provides group-based automated licensing for Office 365 and other Microsoft on line services."
Or you could use the Graph API.

Or manually via the portal.

Or via B2B.

What is really needed as well is a browser-based provisioning service into Azure AD that does not require the use of the Azure portal, admin rights. etc.

Extra brownie points for adding delegated admin. as well :-)

Enjoy!

 

Postman : Authorisation Code Grant on Server 2016 - ADFS 4.0

I previously blogged on ADFS - Web App and Web API on Server 2016 TP4 ADFS 4.0.

This also shows the ADFS configuration

This is using Authorisation Code Grant in a .NET C# program to call the default template API i.e.

/api/values

Then I was asked how to do this with Postman which turned out to be less trivial than I thought.

As always, the Postman gist is here.

There is an authorisation request, a token request and the API request.

The VS project (as above) runs on my PC and has the web site and web service.

Running the authorisation request from a browser redirects to ADFS to authenticate and then returns a code in the query string..

As in "/?code=NjX0...".

We paste the code into the body of the second request (the code parameter) and then send it. This returns an access token, a refresh token and an ID token.

The Postman script automatically posts the access token into the third request (the API call) and this returns:

[
  "value1",
  "value2"
]

as we would expect.

The access token and the id token are encoded and can be decoded with something like jwt.io.

The refresh token is just a long GUID.

This results in:

Access token:

{
  "aud": "https://my-pc/TodoListService/",
  "iss": "http://my-adfs/adfs/services/trust",
  "iat": 1478562128,
  "exp": 1478565728,
  "apptype": "Confidential",
  "appid": "a07...e75",
  "authmethod": "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport",
  "auth_time": "2016-11-07T22:50:31.925Z",
  "ver": "1.0",
  "scp": "openid user_impersonation"
}

ID token:

{
  "aud": "a07...e75",
  "iss": "https://my-adfs/adfs",
  "iat": 1478562128,
  "exp": 1478565728,
  "auth_time": 1478559031,
  "sub": "v2O...nA=",
  "upn": "user1@dev.local",
  "unique_name": "DEV\\user1"

The ADFS wizard allows you to add claims to the web API part.

So I added the usual LDAP rules for email, given name and surname.

After this change, this resulted in a new access token.

{
  "aud": "https://my-pc/TodoListService/",
  "iss": "http://my-adfs/adfs/services/trust",
  "iat": 1478562556,
  "exp": 1478566156,
  "email": "user1@company.com",
  "given_name": "User",
  "family_name": "One",

  "apptype": "Confidential",
  "appid": "a07...e75",
  "authmethod": "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport",
  "auth_time": "2016-11-07T23:49:15.935Z",
  "ver": "1.0",
  "scp": "openid user_impersonation"
}

Enjoy!

Tuesday, November 01, 2016

Visual Studio : VS 2015 Enterprise takes ages to start up

And it gets slower and slower.

Then I found Slow Visual Studio Performance … Solved!.

Essentially "Delete everything in C:\Users\\AppData\Local\Microsoft\WebSiteCache".

As you load up your projects, the first time they will run slower as it rebuilds the cache but it seems to be a good idea to clear this cache out once in a while.

Use at your own risk but wow - what a difference in start-up!

Enjoy!

Tuesday, September 13, 2016

AD : Attempt to compromise security (HRESULT: 0x800704F1)

The full error is:

System.DirectoryServices.AccountManagement.PrincipalOperationException: The system detected a possible attempt to compromise security. Please ensure that you can contact the server that authenticated you. (Exception from HRESULT: 0x800704F1) ---> System.Runtime.InteropServices.COMException: The system detected a possible attempt to compromise security. Please ensure that you can contact the server that authenticated you. (Exception from HRESULT: 0x800704F1)

This is described here:

MS16-101: Description of the security update for Windows authentication methods

Essentially, the updates disable the ability of the Negotiate process to fall back to NTLM when Kerberos authentication fails for password change operation.

I found these useful:

Enabling Secure LDAP on Windows Server 2008/2012 Domain Controllers
Enabling Secure LDAP on Windows Server 2008/2012 Domain Controllers: Configuration

There is a good write-up here:

Solution for Problem in Change Password after Windows Security Update 

TL;DR
  • Enable LDAPS
  • Set "Trusted Hosts"
  • Revert the update
Only the former was an option for me.

And so began a journey into the depths of the Internet - or more specifically the huge amount of garbage, rubbish and misinformation out there :-(

One of the problems was the connection string.

I naively assumed that I simply needed to change:

LDAP://fqdn       to
LDAPS://fqdn

But from what I can see, there is no actual protocol called LDAPS? It's official name is "Secure LDAP" and the connection string you need is:

LDAP://fqdn:636

The "correct" way to enable it is to install an Enterprise Root CA on a Domain Controller.

That wasn't an option (and a massive overkill) so I started wondering about installing a self-signed certificate on the DC.

Disclaimer: Using self-signed certificates or installing certificates as follows may not be the best solution security wise. Use this at your own risk!

The certificate that you need has to follow certain rules e.g.
  • It has to be for "Server Authentication" (OID: 1.3.6.1.5.5.7.3.1)
  • The Subject name must match the Fully Qualified Domain Name (FQDN) of the host machine, such as Subject:CN=server.domain.com
  • (This is also true for the first name in the Subject Alternative Name (SAN))
  • The host machine account needs to have access to the private key
In other words, much the same as an IIS SSL certificate.

Once you have the .pfx file, and using "mmc" with:

Service Account / Local Computer

Select "Active Directory Domain Services".


and import.

You need this certificate in "NTDS\Personal" and  "NTDS\Trusted Root Certification Authorities".

To check this, you need to run "ldp" from the command line.


This should result in:

"Host supports SSL, SSL cipher strength = 256 bits"

If you need to run "ldp" from a non-DC machine, you need Remote Server Administration Tools (RSAT) for Windows Client and Windows Server.

Once "ldp" runs OK, you now have secure LDAP.

Now for the C# .NET side:

Replace the ldapConnection below:

DirectoryEntry ldapConnection = null;

try
{     
      ldapConnection = new DirectoryEntry(LDAP fqdn, user, password);               
}
with:
ldapConnection = new DirectoryEntry(LDAP fqdn, user, password, 
    Password,AuthenticationTypes.SecureSocketsLayer); 
Coming at this from another angle, this code also worked:

Authenticating a user over LDAP in .Net: LdapConnection vs. PrincipalContext

Footnote: I also found that I could leave out the extra parameter:

"Password,AuthenticationTypes.SecureSocketsLayer"

if the user was "domain\user" rather than "user". Go figure!

Enjoy!

Monday, September 12, 2016

OAuth2 : Verifying the ADFS JWT signature

I wrote up this post recently: OAuth2 : Verifying the Azure AD JWT signature.

So how do you do this with ADFS? You need ADFS 4.0 - Server 2016.

This has the following ADFS OAuth information ( ~ metadata) endpoints:



If we go to the "keys" endpoint, we see:

{
  "keys": [
    {
      "kty": "RSA",
      "use": "sig",
      "alg": "RS256",
      "kid": "hHk-...A6k",
      "x5t": "hHk-...A6k",
      "n": "tGy...w9Q",
      "e": "AQAB",
      "x5c": [
        "MIIC7..Log=="
      ]
    }
  ]
}

The information under "x5c" is the certificate that you need.

As  per the linked post, you need to wrap this with "---BEGIN--- ---END---" and copy / paste and you'll see that the signing key is now verified.

Enjoy!



Monday, September 05, 2016

B2C : The Process ID cannot be found for .NET Core exe

The .NET Core B2C sample is here.

I was helping to get it working on another Windows 10 box with VS 2015 when we got the error:

"The Process ID cannot be found for .NET Core exe".

Works fine on my Windows 8.1 box.

If we run .NET Core from the command line and then ran the project, it loaded but then localhost refused the connection.

So Mr. Google to the rescue and the vast majority of the suggestions were along the lines of:

"For me the problem was solved by closing down Visual Studio, deleting project.lock.json
and starting Visual Studio again"

That didn't help and neither did a whole lot of others.

Then I came across a reference along the lines of localhost certificates that aren't trusted for SSL.

And some bells started ringing because I hate IIS Express and don't use it but the Windows 10 machine did not have IIS installed so was running IIS Express by default.

(I always battle with IIS Express and SSL).

And the B2C sample uses https://localhost.

You need to trust the IIS Express self-signed certificate as per this post.

That fixed the problem.

How a trusted certificate issue caused an error message regarding a process ID is another issue entirely :-)

Enjoy!


Friday, September 02, 2016

Postman : Using Postman for Confidential Grant on ADFS

Continuing the series for ADFS 4.0 on Server 2016.

The confidential flow relies on a client_id and a secret_key to authenticate the user.

The gist for the Postman collection is here.

You need to update your ADFS FQDN and the client_id and secret_key.

ADFS returns:

{
  "access_token": "eyJ...ErQ",
  "token_type": "bearer",
  "expires_in": 3600,
  "scope": "openid"
}

You can plug the access token into a JWT viewer.

Enjoy!