Monday, May 16, 2016

Misc : "Why I Haven’t Fixed Your Issue Yet"

This really resonated with me.

Why I Haven’t Fixed Your Issue Yet

I don't do that much open source work - a bit - but nowhere near as much as I help out on Forums.

I help out on forums because I like to pay something back but it's not my full-time job and I don't get paid for it :-)

I get that you have a critical deadline, that your boss is on your back, that you are close to panic etc. but you are not the only one in the forums and like the writer above, I have to prioritise.

I give preference to those people who have actually tried to solve the problem e.g. they paste the ADFS claims rules that don't work.

People who write "HELP NEEDED" or "CRITICAL" and then leave a description like "Doesn't work" and I need three "answers" to tease out what version they are using against what repository and essentially expect me to do their job for them tend to be at the bottom.

And answers like "Don't have time to understand regex" pretty much guarantee that they will be back next week with another variation of the same problem.

Yes - it's hard but is it not part of your job to understand this stuff?

There are no excuses - there are hundreds of articles, books, Pluralsight etc.
'
Have a read of Jon Skeet's classic Writing the perfect question.

Help me to help you by describing and documenting the problem.

Oh and by the way, it's considered good etiquette to mark the question as answered, give reputation points or whatever if I help solve the problem.

Enjoy!

Friday, May 13, 2016

Azure B2C : Differences with Access Control Services (ACS)

B2C is the way forward for ACS.

Refer : The future of Azure ACS is Azure Active Directory.

I put this table together:



Note 1: Azure B2C : Differences with Azure Active Directory (AAD)

Any E&O, fell free to discuss via comments. 

Enjoy!

Thursday, May 12, 2016

Azure B2C : Differences with Azure Active Directory (AAD)

There are a number of gotcha's with B2C that you may not realise at first.

This is still in preview so things will undoubtedly change and there is also B2C Premium on the horizon but no details are publicly available.

More details around limitations here.

To be fair, B2C is aimed at a completely different use case viz. external users who can self-manage via self-service registration and who need SSPR functionality.

I put this table together:


Azure AD
Azure B2C


Can share tenant e.g. with O365
B2C separate tenant that can contain B2C users only


Can add SaaS applications via Market Place
N/A


Can federate with other IDP
N/A


AD sync. via AD Connect
N/A


Users can have O365 licences
N/A


Support for WS-Fed, SAML 2.0p, OpenID Connect, OAuth2
Some OpenID Connect, OAuth2 functionality
(See below)


Support for Single Page Application (SPA) front-end that is written primarily in JavaScript and often uses a SPA framework such as AngularJS, Ember.js, Durandal, etc.
N/A


Web API support for OAuth 2.0 JWT Bearer Credential Grant, otherwise known as the On-Behalf-Of flow
N/A


Support for OAuth 2.0 client credentials flow
N/A – must use OpenID Connect to authenticate first


Wide range of authentication platforms
Only .NET, iOS, Android, and NodeJS


Social support for Yahoo, Facebook, Google and MSA (Windows Live) via ACS
Social support for Facebook, Google, Amazon, LinkedIn and MSA (Windows Live)


Can add additional social providers via Identity aaS e.g. Auth0, Optimal IDM etc.
N/A


Can verify custom domains
N/A on classic portal

Any E&O, fell free to discuss via comments.

Enjoy!

Wednesday, May 04, 2016

ADFS : Expired password

Continuing from ADFS : Adding "Change Password" to the default login page.

This concerned "Change Password" but then I came across a reference to the effect that once this feature was enabled, it also handled "Expired Password".

Now I tried this on Active Directory Federation Services on Server 2016 Technical Preview 4 (ADFS 4.0) but the article states that it works on ADFS 3.0 (Server 2012 R2) as well.

After logging in with an expired password. I got:


Very neat!

However, for "Forgotten Password" i.e. user requires a "Reset Password", you are out of luck.

You could configure one of the configurable strings using PowerShell to say something like "Forgot your password?" and then link that to a custom web site that you would have to create that talks to AD via LDAP.

Obviously there are security constraints with this e.g. you need something like "Secret Q & A".

Enjoy!

Monday, May 02, 2016

ADFS : Server 2016 OAuth JWT is missing scope and NameID

This is for Active Directory Federation Services on Server 2016 Technical Preview 4 / 5.

As per ADFS : Daemon and Web API on Server 2016 TP4 ADFS 4.0, I made the comment:

"The Azure AD sample relies on scope and NameID claims being returned in the JWT token. This is OK in Azure AD where the claims are static and Azure ID knows the ID of the application which is returned as a GUID in the NameID claim. ADFS AFAIK does not have claims rules for this so I hard coded the NameID. Hopefully, this will be resolved as more documentation is forthcoming."

Then I came across AD FS On-behalf-of Authentication in Windows Server 2016.

As per that article, you have to manually generate the scope claims!

They use the following claims rules:
@RuleName = "All claims"
c:[]
=> issue(claim = c);

@RuleName = "Issue open id scope"
=> issue(Type = "http://schemas.microsoft.com/identity/claims/scope", 
Value = "openid");

@RuleName = "Issue user_impersonation scope"
=> issue(Type = "http://schemas.microsoft.com/identity/claims/scope", 
Value = "user_impersonation");
These match the scope check boxes configured in ADFS in the application group.

This means that every time you alter the scopes you need to alter the claims rules.

Hopefully, this will be fixed before the official release.

The other issue I had was with NameID.

As per that article:

"From AD FS we are issuing the Nmae claim but we are not issuing NameIdentifier claim. The sample uses NameIdentifier to uniquely key in the ToDo items. For simplicity, you can safely remove the NameIdentifier with Name claim in the code. Find and replace all occurences of NameIdentifier wiht Name."

(Spelling as per original article.)

My solution was simply to generate a static NameID. The whole point is to have a unique key into the token store.

Enjoy!

ADFS : OpenID Connect and OAuth2 support on Server 2016 TP5

This is for Active Directory Federation Services on Server 2016 Technical Preview 5.

This is the last TP before RTM.

I've done a series of posts on this capability in TP4 and I tried a few of the use cases in TP5 and they worked no problem.

All you need to do is to change the metadata URL and the clientID and the secret key.

So much easier when you have a working sample as reference :-).

There is a similar series of Microsoft posts here. I believe that more content is going to be added prior to RTM.

The format of these posts is somewhat different to the way that I do them but I will leave you to decide which way you prefer!

Enjoy!

Thursday, April 28, 2016

ADFS : Daemon and Web API on Server 2016 TP4 ADFS 4.0

This follows on from my previous series of posts around taking the Azure AD OpenID Connect / OAuth2 samples and getting them to run on ADFS on TP4.

This uses the active-directory-dotnet-daemon sample that has a Windows console application calling a Web API using its application identity.

This is for Active Directory Federation Services on Server 2016 Technical Preview 4.

Just ignore all the Azure AD comments. There is no Azure in this solution.

In the solution, I've set the Web API to be at localhost:44326.

Just to re-iterate - the ADFS has to be Server 2016 - TP4 and above. This will not work on Server 2012 R2 - ADFS 3.0.

As before, the changes are all in a gist here.

This uses the client credential flow with ADAL i.e.

result = authContext.AcquireToken(todoListResourceId, clientCredential); 

where clientCredential is a combination of the clientID and the secret key. There is no authentication pop up where a user name and password needs to be entered.

The Azure AD sample relies on scope and NameID claims being returned in the JWT token. This is OK in Azure AD where the claims are static and Azure ID knows the ID of the application which is returned as a GUID in the NameID claim. ADFS AFAIK does not have claims rules for this so I hard coded the NameID. Hopefully, this will be resolved as more documentation is forthcoming. (But see ADFS : Server 2016 OAuth JWT is missing scope and NameID).

On to the ADFS configuration:

New Application Group - "Server Application and Web API".

For the Server Application:


You also need to generate a secret key. Copy this key before you leave the page because you can't get back to it. (You can, however, generate a new one).

The Client ID and the secret key need to be copied into the daemon app.config here:

 <add key="ida:ClientId" value="bee24b9a-13ac-45fc-988c-8cce06160c07" />
 <add key="ida:AppKey" value="wp...nE" />

For the Web API:






The custom claim rule for NameID is:

 => issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", Value = "abcd");


Now run up the sample and the console application will show something like:

Posting to To Do list at 28/04/2016 9:03:27 p.m.
Successfully posted new To Do item:  Task at time: 28/04/2016 9:03:27 p.m.

Retrieving To Do list at 28/04/2016 9:03:33 p.m.
Task at time: 28/04/2016 9:02:10 p.m.
Task at time: 28/04/2016 9:03:27 p.m.
Task at time: 28/04/2016 9:02:36 p.m.
Total item count:  3

Posting to To Do list at 28/04/2016 9:03:46 p.m.


Enjoy!

Thursday, April 21, 2016

Claims : Azman in the new claims-based world

Refer : Windows Authorisation Manager

"AzMan is available for use in the following versions of Windows: Windows Server 2012, Windows 8, Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003, or Windows XP. It is deprecated as of Windows Server 2012 R2 and may be removed in subsequent versions."

"AzMan is a role-based access control (RBAC) framework that provides an administrative tool to manage authorisation policy and a run time that allows applications to perform access checks against that policy. The AzMan administration tool (AzMan.msc) is supplied as a Microsoft Management Console (MMC) snap-in.

Role-based authorisation policy specifies access in terms of user roles that reflect an application's authorisation requirements. Users are assigned to roles based on their job functions and these roles are granted permissions to perform related tasks.

Authorisation policy is managed separately from an application’s code. The application designer defines the set of low-level operations that are considered security sensitive and then defines a set of tasks that map onto those operations. The tasks, but not the operations, are designed to be understandable by administrators and business analysts."

Windows Server 2003 was way before the era of claims-based authentication and no doubt it had a place then.

Imagine a library. There could be two kinds of people; librarians and users. 


Users can browse the catalogue and check in / out books. Librarians can also do those functions plus they can order books. So the list of tasks could be:


Now the steps in ordering a book could be:


So the librarian would first check that there was enough budget, then check that the supplier has stock and then process the order.

There is a hierarchy of Role which has Tasks which has Operations. Each operation has a number.

Now you assign Tasks to Roles and then Operations to Tasks.


Lastly, you then assign users to Roles under "Role Assignments" above.

This is all wrapped up in an Application. As above, in the tree, "Library" is an instance of an application.

You then used .COM objects to get the assignments and you ended up with an array of ints; each element was a binary for the operation of that number e.g. if "Check budget" was numbered one, then the first instance in the array would tell you if the user had permission to perform that operation.

Never having used Azman, I may have some details wrong but they are close enough to illustrate the point.

This is all well and good but how to you migrate this to a modern claims-based world using e.g. ADFS.

ADFS authenticates against Active Directory (AD) and AD does not directly support the above structure.

AD does not have a concept of "application" and I'm ignoring that for the moment as my particular requirement was to migrate an Azman based program that only had one application.

AD does allow a hierarchy of roles (called Groups in AD) e.g. A can be memberOf B can be memberOf C.

The problem is that the groups do not display in a hierarchical manner e.g.


The way this is setup in AD is that:

"Librarian" is a memberOf "Order book" is a memberOf "Check budget".

The user is then a memberOf  "Librarian".

In terms of setting up the claims-based application, there are two ways to go:
  • WIF (the older way but still supported)
  • OWIN WS-Fed (the newer way)
For WIF, refer:

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

where the STS = ADFS.

For OWIN, there is a Azure AD sample:

Integrating a web app with Azure AD using WS-Federation

and then convert to ADFS by using:

Use the OWIN Security Components in ASP.NET to Implement Web Sign On with ADFS.

On the ADFS side, be sure to add an LDAP rule that maps "Token-Groups - Unqualified Names" to "Role".

Using this and by adding the code in the gist to display the claims, my user that has the Librarian Role displays as:


The code can now use the IsInRole construct.

Refer Working with claims-based identities in multi-tenant applications for other ways to look at the claims.

Hopefully, this provides enough of the plumbing to get you across the line during your Azman migration.

Enjoy!

Wednesday, April 20, 2016

Misc : Switching over to https

Now that Blogger supports https, I've enabled https support for this blog.

I can't see any obvious errors.

If you find something, please leave a comment.

Thanks.

Enjoy!

Friday, April 15, 2016

ADFS : Adding "Change Password" to the default login page

I used Server 2016 TP4 for this but you can use any version of ADFS from 2012 R2 upwards.

I gave an overview here but this is the actual code sample.

This is based on #AzureAD Mailbag: Self-Service Password Reset.

The PowerShell commands are:

New-ADFSWebTheme -Name ADFSChangePassword -SourceName default

Name                    : ADFSChangePassword
IsBuiltinTheme          : False
StyleSheet              : {[, System.Byte[]]}
RTLStyleSheet           : {42, 32, 123, 13...}
OnLoadScript            :
Logo                    : {}
Illustration            : {[, System.Byte[]]}
AdditionalFileResources : {[/adfs/portal/script/onload.js, System.Byte[]], [/adfs/portal/images/idp/localsts.png, System.Byte[]], [/adfs/portal/images/i
                          [/adfs/portal/images/idp/otherorganizations.png, System.Byte[]]}
 

Export-ADFSWebTheme -Name ADFSChangePassword -DirectoryPath C:\Work

Onload.js will now be in c:\work\script\onload.js

Modify onload.js at this point as below.

Set-AdfsWebTheme -TargetName ADFSChangePassword -AdditionalFileResource @{Uri=’/adfs/portal/script/onload.js';path=”c:\work\script\onload.js”}

Set-AdfsWebConfig -ActiveThemeName ADFSChangePassword


Modify onload.js by adding the following at the end: 

// Add "Change Password" link

var formsAuthArea = document.getElementById("formsAuthenticationArea");

if (formsAuthArea) {

    // Create the hyperlink

    var pwdResetLink = document.createElement('a');

    var linkText = document.createTextNode("Change your password");

    pwdResetLink.appendChild(linkText);

    pwdResetLink.title = "Change your password";

    pwdResetLink.href = "https://my-adfs/adfs/portal/updatepassword/";

    document.body.appendChild(pwdResetLink);

    // Append to the authArea

    var authArea = document.getElementById("authArea");
   
    authArea.appendChild(pwdResetLink);
}


Then run the last two PowerShell commands.

The login screen will now look like:


Clicking the link leads to:


Enjoy!

ADAL : Use of token cache in Azure multi-tenancy

Very good Patterns and Practices series of posts here on developing an Azure multi-tenant application.

Part of this is the issue around caching the tokens.

The article has this to say:

"It's relatively expensive to get an OAuth access token, because it requires an HTTP request to the token endpoint. Therefore, it's good to cache tokens whenever possible. The Azure AD Authentication Library (ADAL) automatically caches tokens obtained from Azure AD, including refresh tokens.

ADAL provides a default token cache implementation. However, this token cache is intended for native client apps, and is not suitable for web apps:
  • It is a static instance, and not thread safe.
  • It doesn't scale to large numbers of users, because tokens from all users go into the same dictionary.
  • It can't be shared across web servers in a farm.
Instead, you should implement a custom token cache that derives from the ADAL TokenCache class but is suitable for a server environment and provides the desirable level of isolation between tokens for different users."

Just something to keep in mind!

Enjoy!

Thursday, April 14, 2016

ADFS : Change the user password

As per ADFS 2012 R2 now supports Password Change (not reset) across all devices, users have had the ability to change their password since 2012 R2.

This is as simple as enabling the endpoint and then restarting the service.

Note that this does not encompass resetting the password.

Note also that you only get these values when the password is due to expire within the next 14 days. (The 14 day value is not currently configurable).

As per the above link:

"All you need to do is to add the following claims rule to the issuance claims when sending tokens to Azure AD/Office 365.

c1:[Type == “http://schemas.microsoft.com/ws/2012/01/passwordexpirationtime“]
=> issue(store = “_PasswordExpiryStore”, types = (“http://schemas.microsoft.com/ws/2012/01/passwordexpirationtime“, “http://schemas.microsoft.com/ws/2012/01/passwordexpirationdays“, “http://schemas.microsoft.com/ws/2012/01/passwordchangeurl“), query = “{0};”, param = c1.Value);

With the above rule we are sending 3 additional claims
  • Password Expiration Time: This is the time when the user’s password will expire
  • Password Expiration Days: This is the number of days remaining prior to the password expiry
  • Password Change URL: This is the URL of the password change URL from ADFS"
That's all well and good with WS-Fed & SAML but what happens with OpenID Connect / OAuth where you don't have the ability to add claims rules?

With Server 2016 TP4, OpenID Connect functionality is enabled but you still can't add claims rules to web applications. You can only add them to web API.

So what happens in TP4 when "Change Password" is enabled and we use OpenID Connect from a web application.

We get two new entries:


Previously, the order was upn / name / c_hash.

Now we have upn / name / pwd_url / pwd_exp / c_hash.

The pwd_url is the URL of the "Change Password" page.

The pwd_exp value is the number of seconds until the password expires (approx. 4 days).

If you want to add this link permanently to the ADFS login page, refer:

I love the SSPR functionality but my users authenticate with AD FS.

Note that this is for the Azure AD SSPR link but there is nothing stopping you changing the wording from "Can't access your account?" to "Change your password" and setting the URL to the ADFS  "Change Password" URL as above.

Code sample for this here.

Enjoy!