Search code examples
azureswaggerazure-service-fabricswagger-ui

Enabling Azure AD Auth for Swagger UI hosted in Service Fabric


We enabled Swagger for Web API application which is hosted on Azure Service Fabric. We want to enable security on Swagger UI. So I followed below url which enables security – https://blogs.msdn.microsoft.com/pratushb/2016/04/28/enable-swagger-to-authenticate-against-azure-ad/ https://github.com/domaindrivendev/Swashbuckle/issues/671 (response from Oleksandr-Tokmakov)

I could see the “Available authorizations” popup and I could see AAD authentication done successfully on another tab on click of Authorize button. But once authentication completed, I see the token not returns back to swagger ui and the authentication tab not closes.

Below is the code I used. (I created two AAD, one for Web Services hosted on Service Fabric and another for Swagger UI)

 config.EnableSwagger(
   c =>
    {
        c.SingleApiVersion("v1", "Title of Service");
        c.OAuth2("oauth2")
            .Description("OAuth2 Implicit Grant")
            .Flow("implicit")
            .AuthorizationUrl("https://login.microsoftonline.com/tenentId-guid/oauth2/authorize")
            .Scopes(scopes =>
            {
                scopes.Add("user_impersonation", "Access Services Local Swagger Secure");
            });
        c.OperationFilter<AssignOAuth2SecurityRequirements>();
    }
).EnableSwaggerUi(c =>
{
    c.EnableOAuth2Support(
            clientId: "Swagger AAD application Client Id",
            clientSecret: "Swagger AAD application Key",
            realm: "https://localhost:444/swagger/ui/o2c-html",
            appName: "https://serviceslocal/swagger/", // Free text, no reference to AAD
            scopeSeperator: "",
            additionalQueryStringParams: new Dictionary<string, string>() { { "resource", "Web API AAD application Client Id" } }
        );
}
);


public class AssignOAuth2SecurityRequirements : IOperationFilter
    {
        public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
        {
            // Correspond each "Authorize" role to an oauth2 scope
            var scopes = apiDescription.ActionDescriptor.GetFilterPipeline()
                .Select(filterInfo => filterInfo.Instance)
                .OfType<AuthorizeAttribute>()
                .SelectMany(attr => attr.Roles.Split(','))
                .Distinct();
            if (scopes.Any())
            {
                if (operation.security == null)
                    operation.security = new List<IDictionary<string, IEnumerable<string>>>();
                var oAuthRequirements = new Dictionary<string, IEnumerable<string>>
            {
                { "oauth2", scopes }
            };
                operation.security.Add(oAuthRequirements);
            }
        }
    }

Solution

  • I'm using Auth0, but here's what I got for OAuth2 that works for me.

    options.AddSecurityDefinition("oauth2", new OAuth2Scheme
    {
        Type = "oauth2",
        Flow = "implicit",
        AuthorizationUrl = Path.Combine(auth0Settings["Authority"].Value, "authorize")
    });
    
    app.UseSwaggerUI(c =>
    {
        c.RoutePrefix = "docs";
        c.InjectOnCompleteJavaScript("/swagger-ui.js");
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "Easy Streak API");
        c.ConfigureOAuth2(auth0Settings["ClientId"].Value, auth0Settings["ClientSecret"].Value, auth0Settings["Authority"].Value, "EasyStreak API");
    });