Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
25 changes: 25 additions & 0 deletions docs/report-viewer/BasicAuthAppMVC/BasicAuthApp.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30128.36
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasicAuthApp", "BasicAuthApp\BasicAuthApp.csproj", "{B865679F-EE47-498F-A50C-09E6C0ADAE12}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B865679F-EE47-498F-A50C-09E6C0ADAE12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B865679F-EE47-498F-A50C-09E6C0ADAE12}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B865679F-EE47-498F-A50C-09E6C0ADAE12}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B865679F-EE47-498F-A50C-09E6C0ADAE12}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A0CD6C69-C1E4-4D2D-BFE3-C72D05B82654}
EndGlobalSection
EndGlobal
434 changes: 434 additions & 0 deletions docs/report-viewer/BasicAuthAppMVC/BasicAuthApp/App_Data/DemoRDL.rdl

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System.Web;
using System.Web.Optimization;

namespace BasicAuthApp
{
public class BundleConfig
{
// For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*"));

// Use the development version of Modernizr to develop with and learn from. Then, when you're
// ready for production, use the build tool at https://modernizr.com to pick only the tests you need.
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));

bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/Scripts/bootstrap.js"));

bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Web;
using System.Web.Mvc;

namespace BasicAuthApp
{
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace BasicAuthApp
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

// routes.MapRoute(
// name: "DefaultApi",
// url: "{controller}/{action}/{id}",
// defaults: new { id = UrlParameter.Optional }
//);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using BasicAuthApp.AuthHelper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;

namespace BasicAuthApp
{
public class WebApiConfig
{
public static void Register(HttpConfiguration configuration)
{
// Web API routes
configuration.MapHttpAttributeRoutes();
configuration.Filters.Add(new BasicAuthActionAttribute());
configuration.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;

namespace BasicAuthApp.AuthHelper
{
public class AddChallengeOnUnauthorizedResult : IHttpActionResult
{
public AddChallengeOnUnauthorizedResult(AuthenticationHeaderValue challenge, IHttpActionResult innerResult)
{
Challenge = challenge;
InnerResult = innerResult;
}

public AuthenticationHeaderValue Challenge { get; private set; }

public IHttpActionResult InnerResult { get; private set; }

public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response = await InnerResult.ExecuteAsync(cancellationToken);

if (response.StatusCode == HttpStatusCode.Unauthorized)
{
// Only add one challenge per authentication scheme.
if (!response.Headers.WwwAuthenticate.Any((h) => h.Scheme == Challenge.Scheme))
{
response.Headers.WwwAuthenticate.Add(Challenge);
}
}

return response;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.Http.Filters;

namespace BasicAuthApp.AuthHelper
{
public class BasicAuthActionAttribute : Attribute, IAuthenticationFilter
{
public string Realm { get; set; }

public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
HttpRequestMessage request = context.Request;
AuthenticationHeaderValue authorization = request.Headers.Authorization;

if (authorization == null)
{
if (context.Request.RequestUri.ToString().Contains("ReportApi/PostReportAction") &&
HttpContext.Current.Request.Form.Count > 0 && HttpContext.Current.Request.Form.GetValues("reportAction")[0] == "Export")
{
return;
}
else if (context.Request.RequestUri.ToString().Contains("ReportApi/GetResource"))
{
return;
}
else
{
// No authentication was attempted (for this authentication method).
throw new HttpResponseException(HttpStatusCode.Unauthorized);
}
}

if (authorization.Scheme != "Basic")
{
// No authentication was attempted (for this authentication method).
// Do not set either Principal (which would indicate success) or ErrorResult (indicating an error).
return;
}

if (String.IsNullOrEmpty(authorization.Parameter))
{
// Authentication was attempted but failed. Set ErrorResult to indicate an error.
throw new HttpResponseException(HttpStatusCode.Unauthorized);
}

Tuple<string, string> userNameAndPasword = ExtractUserNameAndPassword(authorization.Parameter);

if (userNameAndPasword == null)
{
// Authentication was attempted but failed. Set ErrorResult to indicate an error.
throw new HttpResponseException(HttpStatusCode.Unauthorized);
}

string userName = userNameAndPasword.Item1;
string password = userNameAndPasword.Item2;

IPrincipal principal = await AuthenticateAsync(userName, password, cancellationToken);

if (principal == null)
{
// Authentication was attempted but failed. Set ErrorResult to indicate an error.
throw new HttpResponseException(HttpStatusCode.Unauthorized);
}
else
{
// Authentication was attempted and succeeded. Set Principal to the authenticated user.
context.Principal = principal;
}
}

protected Task<IPrincipal> AuthenticateAsync(string userName, string password, CancellationToken cancellationToken)
{
if (userName == null && password == null)
{
throw new NotImplementedException();
}
else
{

Claim nameClaim = new Claim(ClaimTypes.Name, userName);
var claims = new List<Claim> { nameClaim };

ClaimsIdentity identity = new ClaimsIdentity(claims, "Basic");

var principal = new ClaimsPrincipal(identity);
return Task.FromResult((IPrincipal)principal);
}
}

private static Tuple<string, string> ExtractUserNameAndPassword(string authorizationParameter)
{
byte[] credentialBytes;

try
{
credentialBytes = Convert.FromBase64String(authorizationParameter);
}
catch (FormatException)
{
return null;
}

// The currently approved HTTP 1.1 specification says characters here are ISO-8859-1.
// However, the current draft updated specification for HTTP 1.1 indicates this encoding is infrequently
// used in practice and defines behavior only for ASCII.
Encoding encoding = Encoding.ASCII;
// Make a writable copy of the encoding to enable setting a decoder fallback.
encoding = (Encoding)encoding.Clone();
// Fail on invalid bytes rather than silently replacing and continuing.
encoding.DecoderFallback = DecoderFallback.ExceptionFallback;
string decodedCredentials;

try
{
decodedCredentials = encoding.GetString(credentialBytes);
}
catch (DecoderFallbackException)
{
return null;
}

if (String.IsNullOrEmpty(decodedCredentials))
{
return null;
}

int colonIndex = decodedCredentials.IndexOf(':');

if (colonIndex == -1)
{
return null;
}

string userName = decodedCredentials.Substring(0, colonIndex);
string password = decodedCredentials.Substring(colonIndex + 1);
return new Tuple<string, string>(userName, password);
}

public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
{
Challenge(context);
return Task.FromResult(0);
}

private void Challenge(HttpAuthenticationChallengeContext context)
{
string parameter;

if (String.IsNullOrEmpty(Realm))
{
parameter = null;
}
else
{
// A correct implementation should verify that Realm does not contain a quote character unless properly
// escaped (precededed by a backslash that is not itself escaped).
parameter = "realm=\"" + Realm + "\"";
}

if (context == null)
{
throw new ArgumentNullException("context");
}

context.Result = new AddChallengeOnUnauthorizedResult(new AuthenticationHeaderValue("Basic", parameter), context.Result);
}

public virtual bool AllowMultiple
{
get { return false; }
}
}

}
Loading