0

I am having problem integrating JWT with my Web API.. I tried to follow this tutorial and example

It seems pretty straight forward, but I am having difficulties integrating it with my project. You should know that I have a bunch of .aspx (Web Form) files that makes my website. This website is consuming my Web API using javascript (Ajax). I have installed jose-jwt package so I can use it in my code.

Server Side

WebApiConfig.cs:

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "defaultApiRoutes",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional },
                constraints: new { id = @"\d+" }   // Only matches if "id" is one or more digits.
            );

            config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

        }
    }

Example of one of my actions inside 'Request' Controller:

[HttpPost]
        [ActionName("createRequest")]
        public IHttpActionResult createRequest(Request request)
        {
            if (userIsAuthorized) // I am guessing that for each action there will be this kinda condition to check the token of the user
            if (ModelState.IsValid) {
                using (SqlConnection connection = WebApiApplication.reqeustConnection("ConStrMRR")) {
                    using (SqlCommand command = new SqlCommand("createRequest", connection)) {
                        try {
                            command.CommandType = CommandType.StoredProcedure;
                            command.Parameters.Add(new SqlParameter("@status_id", request.StatusID));
                            command.Parameters.Add(new SqlParameter("@patient_firstname", request.PatientFirstName));
                            command.Parameters.Add(new SqlParameter("@patient_lastname", request.PatientLastName));
                            command.Parameters.Add(new SqlParameter("@patient_url", request.PatientURL));
                            command.Parameters.Add(new SqlParameter("@facility", request.Facility));
                            connection.Open();
                            int request_id = (int)command.ExecuteScalar();
                            return Ok(request_id);
                        } catch (Exception e) {
                            throw e;
                        } finally {
                            connection.Close();
                        }
                    }
                }
            }
            return Content(HttpStatusCode.BadRequest, "Request has not been created.");
        }

Client Side

Create-request.js

$.ajax({
            url: "http://" + window.myLocalVar + "/api/requests/createRequest",
            type: "POST",
            dataType: 'json',
            contentType: 'application/json',
            data: request,
            success: function (request_id, state) {
                    console.log(request_id);
            },
            error: function (err) {
                if (err) {
                    notyMessage(err.responseJSON, 'error');
                }
            }
        });      

I am guessing that the previous request will be updated to have the following after the 'success' function:

beforeSend: function(xhr)
              {
                xhr.setRequestHeader("Authorization", "Bearer " + localStorage.getItem('token'));
              },

My login page is like the following:

<body id="cover">

<div class="container">
    <div class="row">
        <div class="col-md-4 col-md-offset-4">
            <div class="login-panel panel panel-primary">
                <div class="panel-heading">
                    <h3 class="panel-title">Please Sign In</h3>
                </div>
                <div class="panel-body">
                    <div align="center" style="margin-bottom: 50px;"><img class="img-responsive" src="../img/logo.jpg"/></div>
                    <form role="form" runat="server">
                        <fieldset>
                            <div class="form-group">
                                <asp:TextBox ID="usernameTextBox" CssClass="form-control" runat="server" placeholder="Username"></asp:TextBox>
                            </div>
                            <div class="form-group">
                                <asp:TextBox ID="passwordTextBox" CssClass="form-control" runat="server" placeholder="Password" TextMode="Password"></asp:TextBox>
                            </div>
                            <div class="checkbox">
                                <label>
                                    <asp:CheckBox ID="rememberMeCheckBox" runat="server"/>Remember Me
                                </label>
                            </div>
                            <!-- Change this to a button or input when using this as a form -->
                            <asp:Button CssClass="btn btn-primary btn-block" Text="Login" ID="Login" runat="server"/>
                        </fieldset>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>

I am having difficulties to integrate JWT authentication with my code. Could you please help with that.

Thanks!

10
  • Before diving into a lengthy response, I'd like to know the kind of scenario you are trying to solve. The big question would be "Why are you trying to use JWT authentication?". Related questions: is your web api consumed only by your own application, or are you expecting calls from third party clients? Are you using session cookies for the webform parts of your web site? JWT authentication is usually used for Single Page Applications, but if you have session cookies already in place in your regular web app, you can use the same mechanism for API calls, without worrying about JWTs. Commented Nov 5, 2016 at 21:00
  • @Nico, There will be no third parity in this. The scenario is I have built a simple API and consume it using web pages. I am using plain Jquery/Ajax to consume the API. I have an active directory on an Azure machine. What I want to know is how to authenticate users from DC and if the user is validated, then this user will have a token that s/he can use while making requests to the API.. So the first thing is to have a token in order to make a request to the API otherwise the request will get rejected. I am not using a cookie or a session. Commented Nov 9, 2016 at 16:11
  • As I mentioned before I am consuming my API through the View (Ajax) and I want to pass the token with each request and let the back end validate it. I am honestly not sure if the API should validate the token or Azure has something that is already implemented for that purpose. Commented Nov 9, 2016 at 16:12
  • Next step for me is to check whether a user can perform a request based on his/her role also retrieved form DC. So if a use is authenticated, then return a token and a role and save them (let's say in local storage or somewhere accessible throughout my website.) Commented Nov 9, 2016 at 16:12
  • So, the web API would be implemented with ASP.Net Web API, in a server/application that is completely separated from the Web Forms application that will be the client, right? Commented Nov 11, 2016 at 18:58

1 Answer 1

1

So, you will have:

  1. One Web API server (the "API")
  2. One Web forms application (the "Client")

Web API Server

The API will be protected by JWT. Every client of the API should provide a JWT in the HTTP header (a Bearer token). This JWT will be given by the Identity Provider at the time of authentication.

The Web API needs some kind of middleware to get the JWT token from the request, validate it (verify audience, issuer, expiration and signature) and set a ClaimsPrincipal that will be valid for the request. That way you can use .Net standard authorization attributes and procedures, such as:

[Authorize] // requires the user to be authenticated
public IActionResult SomeProtectedAction()
{
}

If your Web API is for ASP.Net Core, you can use the Microsoft.AspNetCore.Authentication.JwtBearer to do that, configured like this:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    var options = new JwtBearerOptions
    {
        Audience = "[Your API ID]",
        Authority = $"[URL for your identity provider]/",
        // certificate public keys will be read automatically from
        // the identity provider if possible
        // If using symmetric keys, you will have to provide them
    };
    app.UseJwtBearerAuthentication(options);

}

Regular ASP.Net applications with OWIN can use the Microsoft.Owin.Security.ActiveDirectory package, with configuration code like this:

public void Configuration(IAppBuilder app)
{
    var issuer = $"[url to identity provider]/";
    var audience = "[your API id];

    app.UseActiveDirectoryFederationServicesBearerAuthentication(
        new ActiveDirectoryFederationServicesBearerAuthenticationOptions
        {
            TokenValidationParameters = new TokenValidationParameters
            {
                ValidAudience = audience,
                ValidIssuer = issuer
                // you will also have to configure the keys/certificates
            }
        });

Client

Your client application will be a webforms app. After the user signs in (usually by redirecting the user to the identity provider's login page), you will get an access token back. You can store the token in the client (local storage), and use it when making calls to the API as you showed:

beforeSend: function(xhr) {
    xhr.setRequestHeader("Authorization", "Bearer " + localStorage.getItem('token'));
},
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.