3

I am building a web api in C#, and its my first time using C# to build a web api. There is nothing special happening; we make a call to a stored procedure, and return the results as JSON.

I need to limit access to authenticated users. I added [Authorize] to the controller, which works to the extent that it redirects to the logon page, even when the user is already authenticated. [Authorize] is not working as expected. There is an existing application, so I can not change any global settings. What should I do?

Code sample below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;

using XXXX.XXXX.Web.Areas.api.Models;

namespace XXXX.XXXX.Web.Areas.api.Controllers
{
    [Authorize]
    public class ReportController : Controller
    {
        //
       // GET: /api/Report/

        public ActionResult Index()
        {

             return View();
        }

        //
        // GET: /api/Report/RiskRatingSnapshot
        public JsonResult  RiskRollForward(string type)
        {

            var GET = Request.QueryString;

            if (type != "Details") type = "";

            var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["PaynetDatabase"].ConnectionString);
            var command = new SqlCommand("procPrptAPDPortMgrRollForwardDetails", connection)
            {
                CommandType = CommandType.StoredProcedure
            };

            command.Parameters.AddWithValue("@subid", 0);
            command.Parameters.AddWithValue("@portfolio", GET["portfolio"]);
            command.Parameters.AddWithValue("@currentDateKey", GET["currentDateKey"]);
            command.Parameters.AddWithValue("@priorDateKey", GET["priorDateKey"]);
            command.Parameters.AddWithValue("@exposureFrom", GET["exposureFrom"]);
            command.Parameters.AddWithValue("@exposureTo", GET["exposureTo"]);
            command.Parameters.AddWithValue("@APDSensitivity", GET["APDSensitivity"]);



             if (type == "Details")
            {

                command.Parameters.AddWithValue("@groupId", GET["groupId"]);
                connection.Open();
                SqlDataReader reader = command.ExecuteReader();

                var table = pack(reader);
                connection.Close();

                return Json(table, JsonRequestBehavior.AllowGet);
            /*************************************************************
            --Example:
            DECLARE @return_value int

            EXEC    @return_value = [dbo].[procPrptAPDPortMgrRollForwardDetails]
                    @subid = 0,
                    @portfolio = N'52,53',
                    @currentDateKey = 20111001,
                    @priorDateKey = 20110701,
                    @APDSensitivity = 0.25,
                    @exposureFrom = 0,
                    @exposureTo = 1000000000,
                    @groupId = 2


            GO
            **************************************************************/
            }
            return null;
        }

        private List<DetailsReport> pack(SqlDataReader reader)
        {
            List<DetailsReport> table = new List<DetailsReport>();
            while (reader.Read())
            {
                DetailsReport row = new DetailsReport();

                row.customer_number = reader["customer_number"].ToString();
                row.customer_name = reader["customer_name"].ToString();
                row.portfolio = Convert.ToInt32( reader["portfolio"].ToString() );
                row.portname = reader["portname"].ToString();
                row.state = reader["state"].ToString();
                row.exposure_cur = reader["exposure_cur"].ToString();
                row.exposure_chg = reader["exposure_chg"].ToString();
                row.number_of_lenders = Convert.ToInt32( reader["number_of_lenders"].ToString() );
                row.member_lender_business_unit = reader["member_lender_business_unit"].ToString();
                row.LastKnownDel = reader["LastKnownDel"].ToString();
                row.CurDelStatus = reader["CurDelStatus"].ToString();
                row.PayNet_absolutePD_4q = reader["PayNet_absolutePD_4q"].ToString();
                row.APD_4QChg = reader["4QAPD_Chg"].ToString();
                row.PD_chg_wtd_cur_exp = reader["PD_chg_wtd_cur_exp"].ToString();
                row.expWtdPD_cur = reader["ExpWtdPD_cur"].ToString();
                row.expWtdPD_chg = reader["expWtdPD_chg"].ToString();


                table.Add(row);

            }

            return table;
        }
    }

 }
Binary Alchemist
  • 1,600
  • 1
  • 13
  • 28
  • Your question to me isn't very clear... are you saying that that `[Authorize]` redirects the user to the log-on page, which is what it's supposed to do, but it happens to a user EVEN if they are already authenticated? – Mike Marks Jan 07 '14 at 17:35
  • @MikeMarks Yes, every time I access a url of the above controller I am redirected to the login page, **EVEN** when I'm logged in. – Binary Alchemist Jan 07 '14 at 17:46

2 Answers2

0

I did something similar by implementing my own class inheriting from ActionFilterAttribute and perform validation in there (in this case, checking the current user was in an AD group). By overriding the OnActionExecuting method, you have access to the HttpActionContext and I think this happens early enough in the process for what you're trying to achieve. You can then throw an HttpResponseException and include a custom message like so:

         var msg = string.Format("User {0} attempted to use {1} but is not a member of the AD group.", id, actionContext.Request.Method);
        _logger.Info(msg);
        throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Unauthorized)
        {
            Content = new StringContent(msg),
            ReasonPhrase = msg
        });

Hope this helps! There is a walkthrough on MSDN here

EDIT: I gave a better example in this thread here a while back.

Community
  • 1
  • 1
Allan Elder
  • 4,052
  • 17
  • 19
0

Extend [Authorize] to meet your need. An example is provided below:

Controller

In your controller make sure to include the new helper class, and use [Helper.Authorize] in place of [Authorize]

using XXXX.Online.Web.Areas.api.Helpers;

Extended [Authorize]

using System;
using System.Web;
using System.Web.Mvc;
using XXXX.Online.Session;
using XXXX.Online.Enums;

 namespace XXXX.Online.Web.Areas.api.Helpers
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
           try
           {
               PayNet.Online.Web.Security.CheckSession(System.Web.HttpContext.Current);
           }
           catch
           {
               // Get the redirection URL for the request from the system.web/authentication section in the the web.config.
               var authenticationSection = (System.Web.Configuration.AuthenticationSection)System.Configuration.ConfigurationManager.GetSection("system.web/authentication");
               System.Web.Configuration.FormsAuthenticationConfiguration formsAuthentication = authenticationSection.Forms;
               string currentLoginUrl = formsAuthentication.LoginUrl;

               HttpContext.Current.Response.Redirect(currentLoginUrl, true);
           }
      }
   }
}
Binary Alchemist
  • 1,600
  • 1
  • 13
  • 28