Rory Braybrook
Jul 29 · 4 min read

I wrote a post recently about protecting an API with ADFS using the client credentials flow.

Note this is for Active Directory Federation Services (ADFS) 4.0 (Server 2016) and above.

This has a ToDoList API backend and a console application that acts as a client calling the API.

Then I was asked about using Swagger to test API’s protected by ADFS. Here Swagger acts as the client.

Maybe my Google foo was off but I couldn’t find a single article about this. There’s lots of questions and the usual amount of Internet rubbish but nothing that gave me any solid leads.

Hence this article …

I copied the above project and added Swashbuckle (Swagger for .NET).

This simply requires you to add the Nuget package:

Install-Package Swashbuckle -Version 5.6.0 (or whatever the latest is)

This adds a SwaggerConfig.cs.

The class “AssignOAuth2SecurityRequirements” needs to be added when you un-comment this line:


All the code can be found in the gist.

ADFS is configured in SwaggerConfig via:

.Description(“OAuth2 Implicit Grant”)
.Scopes(scopes =>
scopes.Add(“email”, “Email details”);

I’ve just used one scope but you can add more.

The application group parameters are configured via:

clientId: “74a2038e-f26f-40c2-ad4d-a0224a048ddd”,
clientSecret: null,
realm: “test-realm”,
appName: “Swagger UI”,
additionalQueryStringParams: new Dictionary<string, string>() { { “resource”, “https://localhost:44321/” } }

The “resource” parameter is needed to ensure that the OAuth “aud” in the JWT is correct.

In the “client credentials” example above, change the “ValidAudience”:

new ActiveDirectoryFederationServicesBearerAuthenticationOptions
TokenValidationParameters = new TokenValidationParameters()
SaveSigninToken = true,
//ValidAudience = “https://localhost/ToDoListService”
ValidAudience = “https://localhost:44321/”

MetadataEndpoint = “https://my-adfs/FederationMetadata/2007-06/FederationMetadata.xml"

Looking at the Swagger documentation, it supports implicit flow. That implies a SPA and in terms of ADFS application groups, that implies a web browser accessing a web application.

This creates a native application and a web application.

For the native application, note that you need two “Redirect URI”. The clientID is copied to the configuration as above.

For the web application, the first identifier is done for you (it’s the clientID).

You need to add the second.

I have one custom claims rule:

=> issue(claim = c);

i.e. issue everything.

“Email” is the only scope checked.

Run up the application:

Add “swagger” to the base URL in the browser:


You should see:

Click the “GET”.

Note the red exclamation mark.

This means authentication is required. Click it.

Click the “email” scope (remember we configured it in Swagger) and “Authorize”.

This takes us to the ADFS login screen:

Login and we see:

Note we now have a blue information icon.

So let’s POST a ToDo.

And now the GET.

And we can see that it worked!

The “Curl” command shows the JWT.

The JWT is:

Note the “scp” = “email” in the JWT.

All good!

The new control plane

“Identity is the new control plane”. Articles around Microsoft Identity, Auth0 and identityserver. Click the “Archive” link at the bottom for more posts.

Rory Braybrook

Written by

NZ Microsoft Identity dude. Microsoft MVP. Azure AD/B2C/ADFS. Plus Auth0/identityserver. N. Shore .NET UG Admin. Presentations:

The new control plane

“Identity is the new control plane”. Articles around Microsoft Identity, Auth0 and identityserver. Click the “Archive” link at the bottom for more posts.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade