CloudMetal / Orchard.Api

Orchard Content Management REST API Module
BSD 2-Clause "Simplified" License
7 stars 9 forks source link

@GQAdonis - How Are You Approaching Security #1

Open jeffolmstead opened 11 years ago

jeffolmstead commented 11 years ago

I am excited about the work you are doing on this module as I have set up a number of API access points to Orchard and it would be nice to see something both native and generic to make it work through an interface without needing to code every time.

My one early question is how you are approaching security. On all my API access I am using the WebAPI.Hmac model with the goal of having a private key for each user. This means the username be passed in with the request then go to the user part to get their private key. It allows the information to be encrypted using a private key that only the user knows. The other nice thing is that I can apply the security via an attribute so it is not obtrusive. I would gladly contribute it to the project (both client side and server side).

I suppose oAuth could also be considered (don't know exactly how that works out but I am sure someone else does).

Possibly the security could be a plugin (via interface)? This way other developers could implement the interface to append their own security scenarios they need.

I would just like to see a scenario where the users password is never streamed over the wire as not everyone I work with uses https.

Finally, is there a better place to dialogue other than the issue section?

GQAdonis commented 11 years ago

Hey, there! Thanks so much for responding, Jeff! I think we can discuss the issues here and go back to CodePlex with questions that might need more interaction from the entire group (although this may prove to need change).

Here are my thoughts on security:

That is THE most important part of this design effort, and I was planning to support the configuration of security/authorization provider interfaces, building 2 into the base module code (one for OAuth and one for Basic authentication with or without SSL). This can be done using an implementation of IAuthorizationFilter that would have an enumeration of the configured IDependency-derived provider interfaces.

I will be checking in again today some code that has an ApiSettingPart/ApiSettingPartRecord defined for globally turning on and off API access and, perhaps, turning on and off various provider types for authentication and authorization.

Here is a code sample that I have used before to support Basic authentication:

public class BasicAuthenticationAttribute : AuthorizationFilterAttribute
    {
        public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext) {
            var workContext = actionContext.ControllerContext.GetWorkContext();
            var membershipService = workContext.Resolve<IMembershipService>();
            var authenticationService = workContext.Resolve<IAuthenticationService>();
            var userEventHandlers = workContext.Resolve<IEnumerable<IUserEventHandler>>();

            var authorization = actionContext.Request.Headers.Authorization;
            if (authorization != null && authorization.Scheme.ToLower().Equals("basic")) {
                var credentials = Encoding.ASCII.GetString(Convert.FromBase64String(authorization.Parameter));
                if (!string.IsNullOrEmpty(credentials)) {
                    var credentialParts = credentials.Split(new[] {':'}, 2);
                    if (credentialParts.Length == 2) {
                        var userName = credentialParts[0];
                        var password = credentialParts[1];

                        // now check for authorization...
                        var user = ValidateLogOn(membershipService, userName, password);
                        if (user != null) {
                            authenticationService.SignIn(user, true);

                            foreach (var userHandler in userEventHandlers) {
                                userHandler.LoggedIn(user);
                            }
                        }
                        else {
                            actionContext.Response = actionContext.ControllerContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
                        }
                    }
                }
            }
        }

        private IUser ValidateLogOn(IMembershipService membershipService, string userNameOrEmail, string password)
        {
            bool validate = !String.IsNullOrEmpty(userNameOrEmail);

            if (String.IsNullOrEmpty(password))
            {
                validate = false;
            }

            if (!validate)
                return null;

            var user = membershipService.ValidateUser(userNameOrEmail, password);

            return user;
        }
    }

The "Basic Authentication" provider will look something like that, but there is more to this. At some point, I would like to support the field-level configuration of what the resulting JSON will look like based on role and method of authentication (e.g., an "administrator" authenticated directly might have access to more JSON properties than a regular user authenticated via OAuth token from Facebook). This feature might be deferred to a later release, but I would hope not to box ourselves in where this is hard to add.

We will also have an IPermissionsProvider come into play. Some people should be able to make GET requests for content type definitions, content part definitions, etc. but perhaps not be able to create them via POST methods. The site administrator should be able to use the Orchard permissions infrastructure to control this in addition to role and method of authentication as previously mentioned.

An IHttpRouteProvider implementation will use the ApiPart settings (or lack of presence) to configure routes against a plain vanilla ContentApiController, which operates from a JSON API perspective, JUST like the ContentController does for assembling shapes and template processing to return HTML. It will be the same idea.

There will be a ContentTypeApiController, ContentPartApiController, and FieldApiController for "reflecting" over Orchard's set of type, part, and field definitions.

When a ContentPart has an associated strongly typed "record", I planned to use standard CLR property reflection along with custom attributes to determine how those custom record properties should be treated when it comes to building the final JArray and/or JObjects using NewtonSoft to dynamically create IQueryable results for API callers.

This way, we can support OData for all these objects as well. The construction of JSON, once again, is dependent on permissions, roles, and rules associated with authorization methods that can be extended via authorization providers.

Does that sound like a plan?

jeffolmstead commented 11 years ago

That is sounding awesome. I love the example code you provided as it allows me to see how I could drop in my WebAPI.Hmac authorization provider. I am new to the Git side of source control, but I will learn. I will be taking a pull of this project (probably on a fork for requesting integrating changes).

I am glad to hear you talk about supporting OData. While I love JSON, there are some times you just need OData to easily integrate into an existing package.

I am assuming there will also be the ability to retrieve "Lists" of data rather than making the client iterate over the API one at a time?

GQAdonis commented 11 years ago

Yes, sir! Lists will be returned via IQueryable return sets. This will most likely require using some extensions that are rarely used inside the ASP.NET Web Api OData package to specify attributes of how the query engine should operate (since we are not using POCO objects). This should work well with AJAX/Javascript as well (e.g., KendoUI data sources, JayData, etc.).

I will have a partially functioning set of code that contains all the "structure" behind this plan up sometime today. That way, everyone can play with it some and see some real results as other work is being done.

weichen55 commented 10 years ago

Hi, I am very much interested in this module, just curious what's the status of the project now? it seems all the code were checked in 3 month ago. Thanks.

GQAdonis commented 10 years ago

Hello, Wei! Thanks for you interest! This is indeed an active module for which development is in progress. We have a dependency on another module in progress that was just completed, called Orchard.Lists, which is a fork from the main Orchard project here. That module implements containment relationships between content types, and will be a part of Orchard 1.8.

That module is now feature complete, so we will start updating this module again. You can expect a comprehensive update to this module code this weekend. After that you can expect updates once or twice a week between now and the release of Orchard 1.8, which is due in November.

This module should be feature complete before then, however. Let me know if you have other questions!

weichen55 commented 10 years ago

Thank you for your update. I do have one more question, do you happen to know any viable solution to make Orchard work with Phonegap? I think this API project could be one essential link for such solution, but still, there are a lot unknowns.

Wei

GQAdonis commented 10 years ago

It is quite ironic that you ask that question, Wei. That, indeed, is one of the goals of the effort to create Orchard.Api--to support mobile applications--both native and hybrid using PhoneGap/Cordova. The idea begins with the idea of modular PhoneGap applications once we have an API available for Orchard itself. This code example of this modular structure gives you a good idea about this.

Very easily, Orchard's built in "shapes" model can be extended to be used inside HTML5-based mobile hybrid apps to provide a user experience that is spectacular and performant.

You can accomplish this TODAY by simply creating standard modules that expose API's via ASP.NET Web API hooks in Orchard. Orchard.Api seeks to make this automatically available for every content type without writing custom modules and providing a basis for merging custom API's with content API's.

weichen55 commented 10 years ago

awesome! i will take a look and hopefully contribute some work in future, really appreciated.

weichen55 commented 10 years ago

Hi, I looked at the idea of the modular phonegap application and have couple of questions, in the sample, it uses some html template files to display pages, for example, employee list. Do you think those template files should be the content "Shape" Orchard needs to return? I can imagine Orchard return contenttype definitions, but not quite sure how the content shape should be represented. It almost looks to me that we need a mobile designer tool to generate those shape data for the content type and store it as property for the content type. But then the shape representation is also dependent on the mobile client, for example, whether it's JQuery mobile or other technologies.

This if can be done, i think it will cut development cost greatly compared to the native app approaches. Performance may be not as good though.

Have you thought about using Xamarin + MvvmCross + Orchard? How do you compare it with this modular phoneGap approach?

jmgomez commented 10 years ago

Hi, the idea of the module sounds pretty good, congrats. Do you have any sample with the module working? Is the development active?

jeffolmstead commented 10 years ago

Howdie all, I am looking to move ahead in this module and combine it with some Knockout scripting to see if it can be used in a generic manner. Has anyone attempted / thought about creating a Create / Update method in the ContentApiController? I would like to create an API based form creation tool that harnesses Knockout but is generic enough to not have to write a separate controller for every content type (i.e. form) that I create. It might not be possible as there is a lot of business logic in a form / series of forms but I welcome thoughts and ideas.

sfmskywalker commented 10 years ago

Grab the latest Orchard source code from the 1.x branch, it is updated to .NET 4.5.

From: mlasell [mailto:notifications@github.com] Sent: donderdag 6 februari 2014 05:12 To: CloudMetal/Orchard.Api Subject: Re: [Orchard.Api] @GQAdonis - How Are You Approaching Security (#1)

I installed Orchard API in Orchard Modules. When trying to build Orchard, It failed on: Warning 1 Could not resolve this reference. Could not locate the assembly "System.Web.Http.OData". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors. Orchard.Api

I used Nuget to try to install ASP.NET Web API Odata and got this error:

Successfully installed 'Microsoft.AspNet.WebApi.OData 5.1.0'. Successfully uninstalled 'Microsoft.AspNet.WebApi.Client 5.1.0'. Install failed. Rolling back... Could not install package 'Microsoft.AspNet.WebApi.Client 5.1.0'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.0', but the package does not contain any assembly references that are compatible with that framework. For more information, contact the package author.

Does Orchard need to be updated to NETFramework,Version=v4.5? Can it be?

— Reply to this email directly or view it on GitHubhttps://github.com/CloudMetal/Orchard.Api/issues/1#issuecomment-34290733.

NukemHill commented 10 years ago

What is the status on this project? And where is Orchard 1.8? I've seen several references to it, and even saw someone indicate that they had upgraded to it. But I see nothing official, other than a recently-created bug list on the Orchard Codeplex site that apparently needs to be closed before 1.8 becomes RC.

If 1.8 is out and Orchard.Api is done, I'd love to take a crack at it. I have an iOS app that I am planning to attach to the website that I built last Winter. I'd really rather not re-invent the wheel wrt mobile authentication/authorization and web api calls to GET/POST JSON data.