Del via


Enable Swagger to authenticate against Azure AD

Swashbuckle has brought swagger goodness to .Net web API applications.  It is pretty cool to have the auto-generated swagger ui, swagger-json and other features light up with just a few clicks.

However as of now – the ‘Try It’ button on applications which are using any kind of authentication doesn’t work as expected, and usually requires some extra efforts / tweaks to enable any kind of authentication. image001

 

Let’s look at the steps we need to perform to enable swagger generated UI make authenticated calls to a Web API using Azure AD as the authentication mechanism.

Assuming that web API application is already integrated with an Azure Active Directory (AAD) application, and swashbuckler is already integrated. Users are able to open swagger UI and are getting a 401 on “Try it Out” button.

 

Following steps are targeted to help users enable swagger UI

 

First we need to create a new application in Azure AD console to enable swagger UI client integrate with web application. Following steps requires the use to have permissions to create a new application on Azure AD console

 

  1. From AD management portal, create a dedicated application on Azure AD which will be used by swagger UI client to authenticate against the web application.image003
  2. Select 'swagger' application in application list and go to configure section. Scroll down to 'permissions to other applications' and press 'Add application' buttonimage005
  3. In appeared popup change filter setting 'SHOW' to 'All Apps' and press confirm on the right side. Search for your application from the search, select your desired web application and press confirm.
  4.  image007
  5. Web Api application will now be visible to application list. On right side of added web Api find 'delegated permissions' dropdown and select 'Access {web api name}'image009
  6. Add reply URL - ' https://{your_swagger_url}/swagger/ui/o2c-html ' to reply URL list. This should be the URL of the application environment where we want to enable swagger. Alternatively, this can be a static dedicated common URL, which can be used as a kind of application realm.image011
  7. Click on the Manage manifest button in the command bar, and select Download manifest. Open the JSON application manifest file and set the “oauth2AllowImplicitFlow” value to “true”. By default, it is “false”.
  8. image013
  9. In the downloaded manifest json, search for "oauth2AllowImplicitFlow". It will be false, set it to true.
  10. image015
  11. Save the updated JSON file and upload it by clicking the Manage manifest button in the command bar, selecting Upload manifest, browsing to your updated manifest file and then selecting it. Once uploaded, this new application is now configured to use OAuth 2.0 Implicit Grant to authenticate users.
  12.  Go to the 'keys' section and select required duration (currently available 1 or 2 years’ options) for new key. Create and save new Key.image017
  13.  In the bottom, click on 'VIEW ENDPOINTS' button and copy OAuth 2.0 Authorization Endpoint
  14. image019
  15.  On the web api application on azure portal and scroll to the 'permissions to other application' in. Ensure that 'Windows Azure Active Directory' has 'read directory data' permission checked in Application Permission dropdown and 'Read directory data' and 'Sign in and read user profile' permissions in 'Delegated Permissions' dropdownimage021

 

Now that we’ve configured the AAD application for swagger, lets tweak the web application itself to enable using the azure ad client.

As mentioned above, assuming swashbuckler integration is alrea dy existing on the target web application. Go to source repository and make following changes

  1. Edit SwaggerConfig.cs file and search for OAuth configuration. It should be starting with 'c.OAuth2("oauth2") ... ' line
    1. Find 'AuthorizationUrl' method parameter and copy-paste value from OAuth 2.0 Authorization Endpoint from azure. This is the value we collected in previous step.
    2. Add new scope: .Scopes(scopes =>

{

                          scopes.Add("user_impersonation", "Access {app_name}");

});

This section should look like:

c.OAuth2("oauth2")

.Description("OAuth2 Implicit Grant")

.Flow("implicit")

.AuthorizationUrl(string.Format("https://login.microsoftonline.com/{0}/oauth2/authorize", swaggerAdTenant))

.Scopes(scopes =>

{

scopes.Add("user_impersonation", "Access " + swaggerAppName);

});

  • Scroll down and enable an operation filter for OAuth2SecuritymentsFilter.

c.OperationFilter<AssignOAuth2SecurityRequirements>();

  • Add code to the AssignOAuth2SecurityRequirements class as followed :

public class AssignOAuth2SecurityRequirements: IOperationFilter

{

public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)

{

// Determine if the operation has the Authorize attribute

var authorizeAttributes = apiDescription

.ActionDescriptor.GetCustomAttributes<AuthorizeAttribute>();

if (!authorizeAttributes.Any())

return;

// Initialize the operation.security property

if (operation.security == null)

operation.security = new List<IDictionary<string, IEnumerable<string>>>();

// Add the appropriate security definition to the operation

var oAuthRequirements = new Dictionary<string, IEnumerable<string>>

{

{ "oauth2", Enumerable.Empty<string>() }

};

operation.security.Add(oAuthRequirements);

}

}

 

  • Scroll down to c.EnableOAuth2Support method. Method overload which we will use is now available as a part of Swashbuckle 5.0.3 version

image023

We need to invoke and set method parameters:

    1. clientId: -  CLIENT ID value from swagger application configuration on azure portal as “Client ID” method parameter
    2. clientSecret: - Generated key from Azure portal in the “Client Secret” method parameter
    3. realm:-  One of the valid “Reply URL” we configured on the portal.
    4. appName:– Can be value of application name we created for swagger. ‘Swagger’
    5. scopeSeparator :– Can be the default value of ' ' (whitespace)
    6. additionalQueryStringParams :- This is a string dictionary wherein we pass “resource” as key and the “Token Validation Param Audience” as the value. This value is typically a configuration value on the AAD configuration on Web application. It is typically configured in the config file as “audience” and is used in server side code to validate the specific resource on the application. On server side, earlier it used to correspond to WindowsAzureActiveDirectoryBearerAuthenticationOptions.Audience Now, that property is deprecated and this corresponds to TokenValidationParameters.AllowedAudience

var stringDict = new Dictionary<string, string>();

stringDict.Add("resource", swaggerAdAudience);

Finally, ensure that the API methods in API controllers are decorated with [Authorize] tag.

 

Once we are done with above steps, we will be good to go! Let’s deploy the solution and open swagger-ui in browser

We’ll now see an authorization button on the API methods

image029

Once we click on to enable the authentication, a popup will ask for the scopes to do the Azure AD authentication against. Not this scope will be same as we declared in the swagger config

image031

Click on the scope and click authorize. Users will be redirected to corresponding Azure AD authentication flow, where-in user will need to sign-in to the azure active directory with the corresponding credentials.

Once signed-in, system will check if the current signed in users have access to the Azure AD application for the web api. If user is granted access, they will be redirected to the swagger ui for the web application in an authenticated context.

image033

Now users can click the ‘Try It Out!’ link and will get the applicable behavior

 

Disclaimer: Majority of the above flow is derived from the discussion on GitHub @ https://github.com/domaindrivendev/Swashbuckle/issues/671 , particularly thanks to “Oleksandr-Tokmakov”’s comments.

I had added more content and additional steps based on my specific implementation. Hope this helps someone.

Comments

  • Anonymous
    August 05, 2016
    Should also check for [Authorize] attribute on Controller, not just on the Action. var authorizeAttributes = apiDescription.GetControllerAndActionAttributes();
  • Anonymous
    September 26, 2016
    The comment has been removed
  • Anonymous
    November 12, 2016
    How to enable this for Daemon flow? When I implement this, it asks for Email & Password. A Daemon flow (authentication between 2 apps) does not include users since it's just permissions between 2 apps not users. So Users are not involved in the flow.
  • Anonymous
    December 16, 2016
    Too complex
  • Anonymous
    January 28, 2017
    Hi All,I have followed exact same steps as mentioned, but upon clicking on the authorize button. i am redirected to a link that says " Sorry, but we're having trouble signing you in. We received a bad request. ". Can you please point me to what might be the issue here ? I have double checked all the mentioned steps and followed them correctly.