Skip to main content

Swagger Authentication in Dot Net Core

Swagger is really a cool tool to document and test out REST API's. This blog tells about steps to enable Swagger on a Dot Net Core Application along with Authentication as well. In this demo, I am using Azure Active Directory OAuth 2 Authentication to protect my Web API from unauthenticated access. We will be enabling OAuth 2 Authentication on our Swagger UI as well so that we can authenticate using Swagger and then invoke our APIs successfully.

OAuth 2 Authentication works by using Bearer Token to validate the caller and provide access to resource. This requires us to register an Application in the Active Directory tenant, which will be used for authentication of the API, and we will use the same app to authenticate Swagger as well.

Lets get started -

Assuming you have a Dot Net Core Web API that's authenticated via Azure Active Directory OAuth 2 Authentication.

Azure Active Directory Application Registration -

We need to set up our Active Directory Application so that this can be used in our Swagger UI -


Add Redirect URI's as below - 


Generate a new Client Secret -


Make sure you have User Read permission on Microsoft Graph as below - 




Now your Controller Code might look like this, notice the out of box Authorize attribute that's used to tell Dot Net that this is the part which must be invoked via valid authenticated requests only.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace WebApplication4.Controllers
{
    [Authorize]
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        // GET api/values
        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            return new string[] { "value1", "value2" };
        }

Install Swagger  - 


You need to install Swashbuckle.AspNetCore from Nuget Package Manager. I have installed version 4.0.1 at the time of creating this Blog as that's the Latest Stable version available.

Your appsettings.json file must already be populated with tenant and client details.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "yourtenant.onmicrosoft.com",
    "TenantId": "{your-tenant-id}",
    "ClientId": "{your-client-id}"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*"
}

Modify your Startup.cs file and provide necessary values for the Active Directory Application -


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.AzureAD.UI;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Swashbuckle.AspNetCore.Swagger;
using Microsoft.IdentityModel.Tokens;
using Swashbuckle.AspNetCore.SwaggerGen;
using Microsoft.AspNetCore.Mvc.ApiExplorer;

namespace WebApplication4
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
                .AddAzureADBearer(options => Configuration.Bind("AzureAd", options));
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            services
           .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
           .AddJwtBearer(options =>
           {
               options.Authority = "https://login.microsoftonline.com/{tenant-id}";
               options.TokenValidationParameters = new TokenValidationParameters
               {
                   ValidAudiences = new List<string> { "{client-id-of-azure-ad-app}" }
               };
           });
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
                c.AddSecurityDefinition("OAuth2", new OAuth2Scheme()
                {
                    Flow = "implicit",
                    Type = "oauth2",
                    TokenUrl = "https://login.microsoftonline.com/{tenant-id}/oauth2/token",
                    Description = "OAuth2 Implicit Grant",
                    AuthorizationUrl = "https://login.microsoftonline.com/{tenant-id}/oauth2/authorize",
                    Scopes = new Dictionary<string, string>()
            {
                { "user_impersonation", "Access api" }
            }
                });
                c.OperationFilter<AuthenticationOperationFilter>();
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseSwagger();

            // Enable middleware to serve swagger-ui (HTML, JS, CSS etc.), specifying the Swagger JSON endpoint.
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
                c.RoutePrefix = string.Empty;
   c.OAuthClientId("{client-id-of-azure-ad-app}");
                c.DisplayRequestDuration();
                c.OAuthClientSecret("{client-secret-of-azure-ad-app}");
                c.OAuthAppName("swagger app");
                c.OAuthRealm("http://localhost:44389/swagger/ui/o2c-html");
                c.OAuthScopeSeparator(" ");
                c.OAuthUseBasicAuthenticationWithAccessCodeGrant();
                c.OAuthAdditionalQueryStringParams(new Dictionary<string, string>
        {
            { "resource", "{client-id-of-azure-ad-app"}
        });
            });
            app.UseAuthentication();
            app.UseMvc();
        }
    }

    public class AuthenticationOperationFilter : IOperationFilter
    {
        public void Apply(Operation operation, OperationFilterContext context)
        {
            operation.Security = new List<IDictionary<string, IEnumerable<string>>>
        {
            new Dictionary<string, IEnumerable<string>>
            {
                //Note "OAuth2" casing here must match the definition you use in Swagger UI config
                ["OAuth2"] = new List<string>{ "user_impersonation" }
            }
        };
        }
    }
}

That's it, we are ready to test out Swagger now.

Demo - 

Launch your Application by pressing F5, then navigate to localhost/swagger and you will see Swagger homepage.


Since our API's are protected, try invoking any 1 of them and you should get a 401 response indicating you have not authenticated the API that you have just invoked.



Now click on Authorize button on top right, and then you will see your client-id already populated in the box in popup. Below that there is a checkbox for user_impersonation. Select that checkbox and then click on Authorize button.


You will be prompted to log in with your credentials. 


Upon successful login, you will be redirected back to Swagger page, and now in the Popup, you should be able to see a message saying AUTHORIZED. You have successfully authorized now, and you are ready to invoke the API's. Clock the popup.


Now invoke the API and you should see a valid response this time indicating you have successful y authenticated the API and received valid response. 

Notice the Curl section below, it has a request header for Authorization which has the access token that was passed in the HTTP request. This is the token that gets injected every time automatically when you try to invoke any API's after successful authorization


So we have learned how to enable OAuth 2 authentication for Azure Active Directory in Swagger.

Happy learning !! 🙂🙂

Comments

  1. Thanks for sharing this kind of content. It is very helpful and very informative and I really learned a lot from it. Further More Information About Dot Net Training Institute in Delhi So Contact Here-+91-9311002620 Or Visit Website- https://htsindia.com/Courses/microsoft-courses/dotnettraininginstituteinsouthdelhi

    ReplyDelete
  2. It's very helpful i hope you will continue your blogging, anyway if anyone looking for java training institute in delhi contact us +91-9311002620 or visit-
    https://www.htsindia.com/java-training-courses

    ReplyDelete
  3. Thanks for sharing this valuable post its very helpful if anyone looking for best advanced excel training institute in delhi contact us +91-9311002620 Or Visit Website- Contact Here-+91-9311002620 Or Visit Website- https://htsindia.com/Courses/business-analytics/adv-excel-training-course

    ReplyDelete

Post a Comment

Popular posts from this blog

Handling Concurrency in Azure Functions (HTTP Triggered)

Concurrency & Isolation Concurrency is one of the most common requirements when we don't want the resource to be accessed by multiple requests at the same time. Lets say we have a Database that holds products stock information, then it is very important that any read/write operation that happens on the Database must hold the property of Isolation . The isolation property ensures that the concurrent execution of transactions results in a system state that would be obtained if transactions were executed sequentially, i.e., one after the other. Providing isolation is the main goal of concurrency control. Depending on the concurrency control method (i.e., if it uses strict – as opposed to relaxed – serializability), the effects of an incomplete transaction might not even be visible to another transaction. Options Available in Azure Functions Recently while working on Azure Functions, I discovered a really simple way of handling Concurrency via code. There are ways to con

Azure Functions - Retrieve data from Dynamics 365 CRM/CE Online using CRM OData Web API

Introduction: This blog describes how you can retrieve data from Dynamics 365 CRM/CE Online in an Azure Function, using CRM OData Web API. The CRM Web API has a couple of advantages over the traditional SOAP based approach to interact with CRM. These are rest based services, its easy to use and transport over http protocol , and there is no need to use additional web resources (XrmServiceToolkit ) of SDK (SDK.REST). Here is a detailed documentation on CRM OData Wbeb API. I will be using an Azure Function Application in Visual Studio 2017 to retrieve records from Dynamics 365 CRM/CE, by making use of OData API Endpoint provided by CRM. Prerequisites: Dynamics 365 CRM Online Trial https://trials.dynamics.com/ https://signup.microsoft.com/Signup?OfferId=bd569279-37f5-4f5c-99d0-425873bb9a4b&dl=DYN365_ENTERPRISE_PLAN1&Culture=en-us&Country=us&ali=1 Azure Subscription related to CRM Online instance https://portal.azure.com/ Visual Studio 2017 with Cl

Retrieve 5000+ Records in Dynamics 365 CE using CRM OData, Fetch XML and C#

If you want to retrieve 5000+ records in Dynamics 365 CE, you need to make use of Paging concept of CRM. By default 5000 records are retrieved in a single OData call in CRM. To get more, you need to make subsequent calls to OData Endpoint by passing a paging cookie in the request. I will be using a simple C# Console Application to retrieve 5000+ records from Dynamics 365 CE, by making use of OData API Endpoint provided by CRM and passing Fetch XML in OData Call . Concept: CRM OData Endpoints allows us to use Fetch XML to retrieve data from Microsoft Dynamics 365 CE.  If your resultset has more than 5000 records, you will be returned with first 5000 records ONLY in one OData call. To know if the resultset has more than 5000 records, we make use of the response from OData call. The response is added with a cookie value contained in a key - "@Microsoft.Dynamics.CRM.fetchxmlpagingcookie" If you wish to fetch the next set of resultset data, you will have to pass this c