Tuesday, March 22, 2016

ADFS - Web App and Web API on Server 2016 TP4 ADFS 4.0

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

A looooong journey to get this to work because there is (as I write) absolutely no documentation on how to do this. Much midnight oil.

I based this on the Active directory dotnet webapp webapi openidconnect sample.

There is also some useful stuff on OpenId Connect Web Sign On with ADFS in Windows Server 2016 TP3 and Securing a Web API with ADFS on WS2012 R2 Got Even Easier.

This sample has a web app and a web API. The web app connects with OpenID Connect and then calls a ToDoList web API using OAuth with the auth. token from the OpenId Connect call.

Both the web app and the web API are protected by ADFS 4.0.

Now the Open ID Connect part is relatively simple. I've got it working before (see earlier blog entries).

The web API is another kettle of fish :-)

Eventually, I figured it out from Vittorio's new book Modern Authentication with Azure Active Directory for Web Applications. (Seriously, just buy it!).

I have put the important code gists here.

Disclaimer: Don't use this in a Production system e.g. I just simulated a token store. Use at your own risk! Use this as a guide.

The logout is commented out because apparently that doesn't work yet. The Profile tab won't work because that gets user details via the Graph API to Azure AD.

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

In the solution, the web app is at localhost:44322 and the web API is at localhost:44321.

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. (Just for a start, ADFS 3.0 has no OpenID Connect support).

On to the ADFS configuration:

You need to create a new Application Group.


Then select "Server Application or Website".


Give it a name and click next.


Save the client identifier somewhere.

The URI is https://localhost:44322/.

Click Add then Next.


You want a shared secret so click the box and copy to clipboard and save somewhere. You cannot get back to this value. This is exactly how the secret key process in Azure AD works. You can however generate a new one.

Click Next.


You will see a summary.

Click Next.

And the group is successfully created.

Now here's the trick and the bit that held me up. We want to add a web API. So we click the "Add" button on the group screen and not the new group as we did above.


Select Web API


and then Next.


Enter the identifier, then Add and Next.

The identifier is https://localhost:44321/.


For now, we just go with "Permit everyone".

Click Next.


You'll see the web app is automatically included in the permissions but you can add more.

Essentially the web app has default permissions to all the web API in the application group.

Select "user_impersonation" and click Next.

You get a summary.


Click Next.

And the web API entry is created.

You should now see both.


Now we need to add some claims.

Click Edit.

You'll see a number of tabs.


Click "Issuance Transform Rules".

Now we are in familiar territory :-).

We add some claims rules.


viz. a LDAP rule for email and a transform rule to transform email to NameID with a format of email.

These are required because the sample uses these two claims.

Save these and you are done.

Remember to add the clientID and the secret that you saved to the ClientId and AppKey entries in the web app web.config.

Run up the sample, you should be redirected to ADFS for authentication.

Then click the "ToDo List" and you should be able to add items to the list.

Hopefully, you should not have to battle as much as I did.

Enjoy!

1 comment:

Javafun said...

Hi nzpcmad

Thanks for sharing this comprehensive details. I recently came across the same requirement, I followed your article and got the web app working with openid on ADFS, but not the webapi.

Basically as far as I put the [Authorize] attribute on webapi controller, I got 401 error.

Could you provide the api project sample code?

Thanks a lot