Monday, December 12, 2016

Swagger : Using Swagger for Implicit Grant on ADFS 4.0

This is based on this post.

I like Swagger. It maps your REST API and documents them and then allows you to test them from the documentation. Very neat.

You can write the code first and then Swagger reflects the API - much like the default API page in an MVC project or you can use the Swagger UI link to write the contract first and then generate.

Very much along the lines of code first vs. contract first.

(Aside: Once upon a time, I used SOAP and wsdl's and the WSCF (Web Services Contract First) project from thinktecture that does much the same thing. That article is dated from 2006! The more things change ...)

ADFS 4.0 (Server 2016) opens up the OpenID Connect / OAuth stack with full support for all four grant types (refer previous blog entries for a number of examples of this).

So it was a no brainer to try and put the two together.

I used this as a start point and that post gives a good overview of Swagger and how to integrate into a .NET MVC project with NuGet Swashbuckle.

The problem of course is that you need to authenticate the web API and the only OAuth type support in Swagger as I write is the implicit flow.

So following the article, as usual the gist is here.

You will notice that there is a scope called "sampleui". It's simple to add this to the Scopes section in the ADFS wizard.

So we run up the project in VS 2015 and then navigate to:

https://localhost:44326/swagger

(or whatever port your web API project uses).


Notice the highlighted exclamation mark in red.

Click that.


Check the boxes, click "Authorize".

It should take you off to the ADFS login page where you authenticate.


 Notice the exclamation mark is now blue (and if you click it you can Logout).

Now we put a value e.g. 5 in the "id" box and click "Try it out".

And it returns:

{
  "Message": "Authorization has been denied for this request."
}

I've tried everything I can think of  but I can't get this to work.

The JWT returned is:

{
  "aud": "microsoft:identityserver:7b23c943-6782-4d5b-b56c-7ecd59da17f2",
  "iss": "http://my-adfs/adfs/services/trust",
  "iat": 1480889151,
  "exp": 1480892751,
  "apptype": "Public",
  "appid": "7b2...7f2",
  "authmethod": "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport",
  "auth_time": "2016-12-04T22:05:50.803Z",
  "ver": "1.0",
  "scp": "sampleapi user_impersonation"
}

and when I access the API normally from a client in the VS project, I get the JWT:

{
  "aud": "https://localhost:44326/NativeTodoListService1",
  "iss": "http://my-adfs/adfs/services/trust",
  "iat": 1480889366,
  "exp": 1480892966,
  "apptype": "Confidential",
  "appid": "0cc...549",
  "authmethod": "http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password",
  "auth_time": "2016-12-04T22:09:26.486Z",
  "ver": "1.0"
}

I suspect the problem is that the "aud" is wrong. But I can't figure out how to get rid of the "microsoft:identityserver" one?

So close :-(

Any bright ideas?

Enjoy!

No comments: