Swagger, OAuth2 and Azure Active Directory

778 views
Skip to first unread message

Michael de Groot

unread,
Nov 3, 2015, 11:00:31 AM11/3/15
to Swagger
I have a .NET Web API project that I've secured using OAuth2 and Azure Active Directory.  The problem that I have is that I cannot get sample data from the Swagger UI as it is not passing an authentication token in the request header.  I've looked online and have found numerous documents.  I've tried following them but I've run into a problem.  I've implemented AssignOAuth2SecurityRequirements as a class and now have the "on/off" buttons displayed.  And when you click on "on", it tries to authenticate via Azure Active Directory.  The problem I'm encountering is that I receive an "invalid_resource" error before I can log in.  

Below is a sample of my SwaggerConfig.cs file:

       public static void Register()
        {
            var thisAssembly = typeof(SwaggerConfig).Assembly;

            GlobalConfiguration.Configuration
                .EnableSwagger(c =>
                    {
                        c.SingleApiVersion("v1", "SPRRoomsWebAPI");

                        c.OAuth2("oauth2")
                            .Description("OAuth2 Implicit Grant")
                            .Flow("implicit")
                            .AuthorizationUrl("https://login.microsoftonline.com/spr.com/oauth2/authorize");

                       c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString());

                        c.DescribeAllEnumsAsStrings();

                        c.OperationFilter<AssignOAuth2SecurityRequirements>();

                        c.OperationFilter<IncludeParameterNamesInOperationIdFilter>();
                        
                            })
                        .EnableSwaggerUi(c =>
                            {
                        
                         c.EnableOAuth2Support("xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "spr.com", "Swagger UI");
                    });
        }
    }

    internal class IncludeParameterNamesInOperationIdFilter : IOperationFilter
    {
        public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
        {
            if (operation.parameters != null)
            {
                // Select the capitalized parameter names
                var parameters = operation.parameters.Select(
                    p => CultureInfo.InvariantCulture.TextInfo.ToTitleCase(p.name));

                // Set the operation id to match the format "OperationByParam1AndParam2"
                operation.operationId = string.Format(
                    "{0}By{1}",
                    operation.operationId,
                    string.Join("And", parameters));
            }
        }
    }

    internal class AssignOAuth2SecurityRequirements : IOperationFilter
    {
        public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
        {
            var actFilters = apiDescription.ActionDescriptor.GetFilterPipeline();
            var allowsAnonymous = actFilters.Select(f => f.Instance).OfType<OverrideAuthorizationAttribute>().Any();
            if (allowsAnonymous)
                return; // must be an anonymous method

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

            var oAuthRequirements = new Dictionary<string, IEnumerable<string>>
        {
            {"oauth2", new List<string> {""}}
        };

            operation.security.Add(oAuthRequirements);
        }
    }


Shashank Banerjea

unread,
Aug 31, 2016, 12:58:59 PM8/31/16
to Swagger
Michael:

Were able to resolve the issue? Since this issue is pretty old, you may have already figured out the solution. However for those who will stumble into the future. 

ROOT Cause:
I believe, the reason for the 'invalid_resource' error is because the resource that Azure AD needs to give permission to is not specified in Authorization URL, when the OAuth2 is configured.

SOLUTION (that worked for me)
Send the resource as a parameter to c.EnableOAuth2Support method under EnableSwaggerUi . It should be passed as a value in the dictionary object in additionalQueryStringParams

It should look something like this:

  .EnableSwaggerUi(c =>
               {
                   c.EnableOAuth2Support(
                       swaggerUIClientID, // client id
                       swaggerUIClientSecret, // client secret
                       swaggerUITestRealm, // return url for the application, specified in azure ad for the client app
                       swaggerUIAppName, // "Swagger UI"
                        additionalQueryStringParams:
                            new Dictionary<string, string>()
                                {
                                    { "resource", swaggerUIAzureADResource } //url of the resource being accessed by the client app
                        });
                  
               });

Here are a blog entry on MSDN detailing the steps and the link to the GitHub issue for Swagbuckle where steps are specified.


Good Luck!
Reply all
Reply to author
Forward
0 new messages