diff --git a/OwinWebApiTest/App_Start/FileServerConfig.cs b/OwinWebApiTest/App_Start/FileServerConfig.cs new file mode 100644 index 0000000..0cff240 --- /dev/null +++ b/OwinWebApiTest/App_Start/FileServerConfig.cs @@ -0,0 +1,34 @@ +using Microsoft.Owin; +using Microsoft.Owin.FileSystems; +using Microsoft.Owin.StaticFiles; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Web; + +namespace OwinWebApiTest +{ + /** + * Configuration of the static file serving options + */ + public static class FileServerConfig + { + public static FileServerOptions Create(PathString pathString, string dir) + { + string appRoot = AppDomain.CurrentDomain.BaseDirectory; + var fileSystem = new PhysicalFileSystem(Path.Combine(appRoot, dir)); + + var options = new FileServerOptions + { + RequestPath = pathString, + EnableDefaultFiles = true, + FileSystem = fileSystem + }; + options.StaticFileOptions.FileSystem = fileSystem; + options.StaticFileOptions.ServeUnknownFileTypes = true; + + return options; + } + } +} \ No newline at end of file diff --git a/OwinWebApiTest/App_Start/WebApiConfig.cs b/OwinWebApiTest/App_Start/WebApiConfig.cs index 3fc7061..c82d3b2 100644 --- a/OwinWebApiTest/App_Start/WebApiConfig.cs +++ b/OwinWebApiTest/App_Start/WebApiConfig.cs @@ -5,13 +5,13 @@ using System.Web.Http; namespace OwinWebApiTest { + /** + * Configuration of the web service options. + */ public static class WebApiConfig { public static HttpConfiguration Register(HttpConfiguration config) { - // Web API configuration and services - - // Web API routes config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( @@ -20,6 +20,15 @@ namespace OwinWebApiTest defaults: new { id = RouteParameter.Optional } ); + config.Routes.MapHttpRoute( + name: "DetailApi", + routeTemplate: "api/{controller}/{resource}/{id}" + ); + + // require authorization for all the entrypoints + // can be overriden by [AllowAnonymous] attribute (at the controller/service level) + config.Filters.Add(new AuthorizeAttribute()); + return config; } } diff --git a/OwinWebApiTest/Doc/index.html b/OwinWebApiTest/Doc/index.html index a782963..0959e07 100644 --- a/OwinWebApiTest/Doc/index.html +++ b/OwinWebApiTest/Doc/index.html @@ -1,8 +1,8 @@  - - + Documentation +

Documentation

diff --git a/OwinWebApiTest/OwinWebApiTest.csproj b/OwinWebApiTest/OwinWebApiTest.csproj index 9c9dca4..75e898d 100644 --- a/OwinWebApiTest/OwinWebApiTest.csproj +++ b/OwinWebApiTest/OwinWebApiTest.csproj @@ -155,6 +155,7 @@ + diff --git a/OwinWebApiTest/Providers/CasAuthorizationServerProvider.cs b/OwinWebApiTest/Providers/CasAuthorizationServerProvider.cs index caa04c6..3a0454e 100644 --- a/OwinWebApiTest/Providers/CasAuthorizationServerProvider.cs +++ b/OwinWebApiTest/Providers/CasAuthorizationServerProvider.cs @@ -1,6 +1,6 @@ -using Microsoft.Owin.Security.OAuth; +using Microsoft.Owin.Infrastructure; +using Microsoft.Owin.Security.OAuth; using Microsoft.Owin.Security; -using Microsoft.Owin.Infrastructure; using Newtonsoft.Json.Linq; using Newtonsoft.Json; using System.Collections.Generic; @@ -13,7 +13,12 @@ using OwinWebApiTest.Models; namespace OwinWebApiTest.Providers { - + /** + * CAS Single Sign On Authorization Provider. + * + * Authenticates user against CAS server login and grants authorization; + * provides authenticated user with access_token and AccessControl dataset. + */ public class CasAuthorizationServerProvider : OAuthAuthorizationServerProvider { private static string casValidationUrl; @@ -26,13 +31,30 @@ namespace OwinWebApiTest.Providers serviceUser = ConfigurationManager.AppSettings["ServiceUser"]; } + /** + * Client authentication + * + * Superseded by CAS authentication but is required, so just validate + */ public override async Task ValidateClientAuthentication( OAuthValidateClientAuthenticationContext context) { - // required but as we're not using client auth just validate & move on... await Task.FromResult(context.Validated()); } + /** + * Performs CAS ticket validation & grants authorization + * + * Expected params (POST method): + * "ticket" (provided to the client by the CAS server on a successful login) + * "service" (application url - against which the login attempt was performed) + * "grant_type=password" + * + * See TokenEndpointPath in Startup.cs for the autorization entry point URL + * + * If successful, grants authorization and returns client a response with + * a valid "access_token", "username" and (app-specific) "AccessControl" dataset + */ public override async Task GrantResourceOwnerCredentials( OAuthGrantResourceOwnerCredentialsContext context) { @@ -40,7 +62,7 @@ namespace OwinWebApiTest.Providers if (string.IsNullOrEmpty(args["ticket"]) || string.IsNullOrEmpty(args["service"])) { context.Rejected(); - context.SetError("invalid_grant", "No CAS ticket or service URL sent."); + context.SetError("invalid_grant", "No CAS ticket or service URL sent"); return; } @@ -57,6 +79,7 @@ namespace OwinWebApiTest.Providers return; } + // once the CAS auth is done, gather additional data about the user (app-specific) //var acda = new AccessControlDA(); //var ac = acda.GetAccessControl(res.success.user); var ac = new { userId = res.success.user, canRead = true, canSave = true }; @@ -69,9 +92,10 @@ namespace OwinWebApiTest.Providers ClaimsIdentity identity = new ClaimsIdentity(context.Options.AuthenticationType); identity.AddClaim(new Claim(ClaimTypes.Name, res.success.user)); - identity.AddClaim(new Claim(ClaimTypes.Role, "Admin")); + identity.AddClaim(new Claim(ClaimTypes.Role, "User")); - // Identity info will be encoded into an Access ticket as a result of this call: + // To add app-specific data to the access token response use AuthenticationProperties + // as below, for plain access token response identity will be encoded into it this way: //context.Validated(identity); var props = new AuthenticationProperties(new Dictionary { @@ -83,7 +107,9 @@ namespace OwinWebApiTest.Providers context.Validated(ticket); } - // needed to get the custom props as a part of the token-granted response + /** + * Necessary to add the AuthenticationProperties to the AuthenticationTicket + */ public override Task TokenEndpoint(OAuthTokenEndpointContext context) { foreach (KeyValuePair property in context.Properties.Dictionary) @@ -94,6 +120,9 @@ namespace OwinWebApiTest.Providers return Task.FromResult(null); } + /** + * Validates CAS ticket received from the frontend against the CAS server + */ private async Task ValidateCasTicket(string ticket, string service) { var requestUri = WebUtilities.AddQueryString(casValidationUrl, new Dictionary() { @@ -108,6 +137,9 @@ namespace OwinWebApiTest.Providers } } + /** + * Sends the CAS ticket validation request and gets relevant data from a response + */ public async Task GetCasServiceValidationAsync( HttpClient client, string requestUri) { diff --git a/OwinWebApiTest/Startup.cs b/OwinWebApiTest/Startup.cs index 3b83649..47d85c2 100644 --- a/OwinWebApiTest/Startup.cs +++ b/OwinWebApiTest/Startup.cs @@ -1,13 +1,10 @@ using System; using System.Configuration; -using System.IO; using System.Threading.Tasks; using Owin; using Microsoft.Owin; using Microsoft.Owin.Cors; using Microsoft.Owin.Security.OAuth; -using Microsoft.Owin.FileSystems; -using Microsoft.Owin.StaticFiles; using System.Web.Http; using System.Net; @@ -17,6 +14,9 @@ using OwinWebApiTest.Providers; namespace OwinWebApiTest { + /** + * Application entry point. + */ public class Startup { public void Configuration(IAppBuilder app) @@ -46,30 +46,15 @@ namespace OwinWebApiTest ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; + // configure web root string webDir = ConfigurationManager.AppSettings["WebDirectory"]; if (string.IsNullOrEmpty(webDir)) webDir = "Web"; - app.UseFileServer(GetFileServerOptions(PathString.Empty, webDir)); + app.UseFileServer(FileServerConfig.Create(PathString.Empty, webDir)); + // configure web root for /doc url string docDir = ConfigurationManager.AppSettings["DocDirectory"]; if (string.IsNullOrEmpty(docDir)) docDir = "Doc"; - app.UseFileServer(GetFileServerOptions(new PathString("/doc"), docDir)); - } - - private FileServerOptions GetFileServerOptions(PathString pathString, string dir) - { - string appRoot = AppDomain.CurrentDomain.BaseDirectory; - var fileSystem = new PhysicalFileSystem(Path.Combine(appRoot, dir)); - - var options = new FileServerOptions - { - RequestPath = pathString, - EnableDefaultFiles = true, - FileSystem = fileSystem - }; - options.StaticFileOptions.FileSystem = fileSystem; - options.StaticFileOptions.ServeUnknownFileTypes = false; - - return options; + app.UseFileServer(FileServerConfig.Create(new PathString("/doc"), docDir)); } } } diff --git a/OwinWebApiTest/Web.Release.config b/OwinWebApiTest/Web.Release.config index c358444..03a0f12 100644 --- a/OwinWebApiTest/Web.Release.config +++ b/OwinWebApiTest/Web.Release.config @@ -3,6 +3,10 @@ + + + - - + +