OData - Data Service Simple Authentication - odata

I would like to add simple authentication to Data Services, for now only to restrict access for particular applications by simple token.
I don't need Domain Authentication or Forms authentication.
I read a lot about authentication here:
http://franssenden.wordpress.com/2010/06/14/custom-security-odata-service-wcf-data-services/
http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2008/06/03/10482.aspx
http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2008/01/15/10119.aspx
http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2008/01/10/10100.aspx
Unfortunately it all demands a loooot of work.
Most of all creating custom IHttpModule.
There should be more simple solution.
I know that when I create object context on the client (WPF) I can add Credentials.
Uri uri = new Uri("http://localhost/myapp/odata.svc");
MyEntities ent= new MyEntities (uri);
ent.Credentials = new NetworkCredential("token", "zx5as9vxc5sa9h0vb6523cv56");
But where can I read them (without implementation of custom IHttpModule)?
I thought that I can use something in class that is implementation of Data Service for example:
protected override void OnStartProcessingRequest(ProcessRequestArgs args)
{
string cred = args.OperationContext.AbsoluteRequestUri.UserInfo;
}
I'm not familiar with UserInfo but description for it stands "Gets the user name, password, ...)
So I have two main questions:
Where can I read Credentials included by typing ent.Credentials = new NetworkCredential("token", "zx5as9vxc5sa9h0vb6523cv56");
Where can I (if I can) set UserInfo on the client app and use it in OnStartProcessingRequest method.
Regards,
Daniel SkowroĊ„ski

There's a series of post about authentication and WCF Data Services (which is the .NET implementation of the OData protocol): http://blogs.msdn.com/b/astoriateam/archive/tags/authentication/
You should be able to find lot more information there (including code samples).

Related

Application_PostAuthenticateRequest equivalent in OWIN OAuth

To enable my service layer to access the current User Id anytime it needs, I use Thread.CurrentPrincipal.
The service layer is used by two front-end layers, one MVC App and one MVC Web Api used for a Mobile App.
In the web app, I use Forms Authentication and the Principal is set into Application_PostAuthenticateRequest. It works fine.
In the web Api, I use Owin. But I cannot find a way to set that Principal after each request is authenticated with the access token.
I can do it when the user logs in with its credentials by overriding GrantResourceOwnerCredentials into my OAuthAuthorizationServerProvider or when he logs with its refresh token by overriding GrantRefreshToken in the same class.
But where could I assign it for requests automatically authenticated with the access token ?
NB. I know that in my Api Controllers I can access the current User, and it is correctly set, but I don't want to pass it with each call to my service layer.
Thanks.
I found how to set it.
The bearer validation is not done by the OAuthAuthorizationServerProvider. I had to implement a custom OAuthBearerAuthenticationProvider, and override the ValidateIdentity method:
public class MyBearerAuthenticationProvider : OAuthBearerAuthenticationProvider
{
public override Task ValidateIdentity(OAuthValidateIdentityContext context)
{
Thread.CurrentPrincipal = new Principal(context.Ticket.Identity);
return base.ValidateIdentity(context);
}
}
And plug that provider into my app by using:
OAuthBearerAuthenticationOptions bearerAuthenticationOptions = new OAuthBearerAuthenticationOptions()
{
Provider = new MyBearerAuthenticationProvider()
};
app.UseOAuthBearerAuthentication(bearerAuthenticationOptions);
Unfortunately Thread.CurrentPrincipal is null in my Business Layer. I assume the token validation is done in another thread than the request execution. So I'll have to change my method.

How to implement a MetadataProvider that reads from database

I'm adding SSO support to a spring-based application using the spring-security-saml extension. The idea will be that an IDP can register to use SSO with my application by filling out a form in the UI, specifying their entityId, SSO authentication URL (for SP-initialized login), and public X.509 certificate. This seems to be a common workflow for SaaS applications with SSO support.
I haven't yet been able to find a clean way of implementing this with the spring saml extension, and am wondering if there is one. FilesystemMetadataProvider and HTTPMetadataProvider provide support for loading IDP metadata from an XML file or an HTTP GET, respectively, but I need to instead generate the IDP metadata from the above attributes that are stored in the database.
My current thinking is to use ResourceBackedMetadataProvider and use an implementation of Resource that fetches the metadata attributes from the database for each registered IDP. It would look something like:
class DatabaseBackedResource implements Resource {
MetadataDao metadataDao; // autowired
public InputStream getInputStream() throws ResourceException {
Collection<MetadataPojo> idpMetadata = metadataDao.getMetadata();
return convertMetadataPojosToInputStream(idpMetadata);
}
private InputStream convertMetadataPojosToInputStream(Collection<MetadataPojo> metadata) {
// somehow convert attributes to XMLObject
// then write XMLObject to input stream
// ...
}
// implementations of other methods
// ...
}
where MetadataPojo is simply a wrapper object of the above 3 attributes provided by an IDP. What I'm not sure about is how to generate a valid IDP metadata java object, given some attributes, using the spring saml extension. I see that AbstractMetadataProvider#unmarshallMetadata(InputStream) converts the metadata input stream into an XMLObject, but it is not clear to me how I will convert my collection of MetadataPojos into an XMLObject.
In short, is there a tool in the spring saml extension library to build an IDP metadata xml object given a list of string attributes? Or, taking a step back, is there a better way to implement a MetadataProvider that fetches the metadata information from a database instead of a file or url?
Update:
I implemented the above MetadataProvider implementation and Resource subclass and it's been working like a charm. To generate the IDP metadata documents I used various subclasses of AbstractSAMLObjectBuilder (i.e. EntityDescriptorBuilder, IDPSSODescriptorBuilder, KeyDescriptorBuilder, etc.) and that worked pretty cleanly. It would be nice if the Spring SAML library had an IDPMetadataGenerator class like the MetadataGenerator that exists for SP metadata.
If there was a cleaner way about this, I'd love to hear it.

How do I manage my authentication with WorldDomination and Nancy?

I'm trying to get social authentication working in an asp.net-hosted Nancy web app using the WorldDomination SimpleAuthentication plugin for Nancy. TL;DRs skip to the question bolded at the bottom of the question.
Both are pretty nice, but there is a big documentation gap between the authentication process (well covered) and identifying the authenticated user during requests other than the initial authenticate request (nothing).
Nancy provides for basic and forms authentication via additional packages, and the hooks they provide are pretty straight forward. WorldDomination does not provide much information past the actual authentication process. There seems to be a distinct lack of Happy Path for the normal "who is the user making this request" process that has to happen every time a user hits the server.
I've been spending a fair amount of time to figure this part out, but my research hasn't led me to any obvious solutions. The WD demo apps are bereft of request code other than authentication requests, and the codebase doesn't appear to contain anything dealing with the normal request cycle.
My best guess is that I need to integrate with forms auth, implementing Nancy's forms auth hooks and using what I get back from WD to populate my own types.
This doesn't exactly seem like the happiest of happy paths. In fact, it seems to be more of a "do lots of work you lazy bastard" path.
What, exactly, is the recommended happy path for integrating WorldDomination's social OAuth authentication providers and Nancy? I'm concentrating on the standard "who is this person that requests of me" page lifecycle part here.
Bonus points (from my hordes of sockpuppet accounts I will create for the purpose) for how this happy path handles users logging out as well!
With Simple Authentication, we simply handle the authentication with a provider in a simple way. Every provider has slightly different implementations, different naming, different promises, so we can to consolidate all that into Simple Authentication and make it easier for a developer to implement into their website.
Thats why the Nancy.SimpleAuthentication package exists. Because we know how Nancy works we have simplified the integration into Nancy by creating the modules for you to handle redirection, authentication callback, etc.
The problem is, we simply do not know how you authenticate a user against your website.
We can handle the whole forms auth scenario ourselves, and I actually plan to in the future. (have to implement claims first which I'm 60% way through), but it will still at bare minimum require you to implement the IAuthenticationCallbackProvider
public class Test : IAuthenticationCallbackProvider
{
public dynamic Process(
NancyModule nancyModule,
AuthenticateCallbackData model)
{
//Query for the database user based on the Provider / Id
//Authenticate the user
//Call LoginWithoutRedirect, and redirect how you want...
// or LoginWithRedirect
return nancyModule.Negotiate.WithView("AuthenticateCallback")
.WithModel(model);
}
}
This class is required in order for you to authenticate the user against your database.
The thing we thought about tho is 95% of the time the user putting in the authentication, most likely already has some form of authentication already. Usually Forms Auth.
So assuming you've pulled in SimpleAuthentication, and wired up your IAuthenticationCallbackProvider class. All you really need to do is implement the Forms Auth stuff, which is pretty much 1 class, and a method call.
In the provider you need to call the LoginWithoutRedirect method so that Nancy can create an auth cookie.
Then you need to setup the IUserMapper class to tell Nancy how to get the user from the Database. If you're using RavenDB this would look something like:
public class DatabaseUser : IUserMapper
{
public IDocumentStore DocumentStore { get; set; }
public DatabaseUser(IDocumentStore documentStore)
{
DocumentStore = documentStore;
}
public IUserIdentity GetUserFromIdentifier(
Guid identifier,
NancyContext context)
{
using (var session = DocumentStore.OpenSession())
{
var member = session.Query<Member>()
.SingleOrDefault(x => x.Identifier == identifier);
if (member == null)
return null;
return new UserIdentity
{
UserName = member.DisplayName,
Claims = new []
{
"NewUser",
"CanComment"
}
};
}
}
}
Configured in the bootstrapper like:
protected override void ConfigureRequestContainer(
TinyIoCContainer container,
NancyContext context)
{
base.ConfigureRequestContainer(container, context);
container.Register<IUserMapper, DatabaseUser>();
}
protected override void RequestStartup(
TinyIoCContainer container,
IPipelines pipelines,
NancyContext context)
{
base.RequestStartup(container, pipelines, context);
var formsAuthConfiguration = new FormsAuthenticationConfiguration
{
RedirectUrl = "~/login",
UserMapper = container.Resolve<IUserMapper>(),
};
FormsAuthentication.Enable(pipelines, formsAuthConfiguration);
}
And that's really it...
I personally don't think it's a lot of code that you have to write. Both Nancy and Simple Authentication have done most of the leg work for you :)
I hope we can make SimpleAuthentication even easier in the future by removing the need for the Forms Auth, but for now I think we have a pretty good solution.
Helpful links:
http://www.philliphaydon.com/2012/12/18/forms-authentication-with-nancyfx/
http://www.philliphaydon.com/2013/01/31/oauth-with-nancyfx-and-world-domination-authentication/
The 2nd link for World Domination, although there's a bit of renaming, it's mostly the same. I do plan to do an updated blog post and revamp the wiki when we have polished off Claims.
I hope that helps you.
Edit:
I've made note to create a more end-to-end solution demo project.

Obtaining the current Principal outside of the Web tier

I have the following ntier app: MVC > Services > Repository > Domain. I am using Forms authentication. Is it safe to use Thread.CurrentPrincipal outside of my MVC layer to get the currently logged in user of my application or should I be using HttpContext.Current.User?
The reason I ask is there seems to be some issues around Thread.CurrentPrincipal, but I am cautious to add a reference to System.Web outside of my MVC layer in case I need to provide a non web font end in the future.
Update
I have been following the advice recieved so far to pass the username into the Service as part of the params to the method being called and this has lead to a refinement of my original question. I need to be able to check if the user is in a particular role in a number of my Service and Domain methods. There seems to be a couple of solutions to this, just wondering which is the best way to proceed:
Pass the whole HttpContext.Current.User as a param instead of just the username.
Call Thread.CurrentPrincipal outside of my web tier and use that. But how do I ensure it is equal to HttpContext.Current.User?
Stick to passing in the username as suggested so far and then use Roles.IsUserInRole. The problem with this approach is that it requires a ref to System.Web which I feel is not correct outside of my MVC layer.
How would you suggest I proceed?
I wouldn't do either, HttpContext.Current.User is specific to your web layer.
Why not inject the username into your service layer?
Map the relevant User details to a new Class to represent the LoggedInUser and pass that as an argument to your Business layer method
public class LoggedInUser
{
public string UserName { set;get;}
//other relevant proerties
}
Now set the values of this and pass to your BL method
var usr=new LoggedInUser();
usr.UserName="test value "; //Read from the FormsAuthentication stuff and Set
var result=YourBusinessLayerClass.SomeOperation(usr);
You should abstract your user information so that it doesn't depend on Thread.CurrentPrincipal or HttpContext.Current.User.
You could add a constructor or method parameter that accepts a user name, for example.
Here's an overly simplified example of a constructor parameter:
class YourBusinessClass
{
string _userName;
public YourBusinessClass(string userName)
{
_userName = userName;
}
public void SomeBusinessMethodThatNeedsUserName()
{
if (_userName == "sally")
{
// do something for sally
}
}
}
I prefer option number 2( use Thread.CurrentPrincipal outside of web tier ). since this will not polute your service tier & data tier methods. with bonuses: you can store your roles + additional info in the custom principal;
To make sure Thread.CurrentPrincipal in your service and data tier is the same as your web tier; you can set your HttpContext.Current.User (Context.User) in Global.asax(Application_AuthenticateRequest). Other alternative location where you can set this are added at the bottom.
sample code:
//sample synchronizing HttpContext.Current.User with Thread.CurrentPrincipal
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
//make sure principal is not set for anonymous user/unauthenticated request
if (authCookie != null && Request.IsAuthenticated)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
//your additional info stored in cookies: multiple roles, privileges, etc
string userData = authTicket.UserData;
CustomPrincipal userPrincipal = PrincipalHelper.CreatePrincipal(authTicket.Name, authTicket.UserData, Request.IsAuthenticated);
Context.User = userPrincipal;
}
}
of course first you must implement your login form to create authorization cookies containing your custom principal.
Application_AuthenticateRequest will be executed for any request to server(css files, javascript files, images files etc). To limit this functionality only to controller action, you can try setting the custom principal in ActionFilter(I haven't tried this). What I have tried is setting this functionality inside an Interceptor for Controllers(I use Castle Windsor for my Dependency Injection and Aspect Oriented Programming).
I believe you are running into this problem because you need to limit your domains responsibility further. It should not be the responsibility of your service or your document to handle authorization. That responsibility should be handled by your MVC layer, as the current user is logged in to your web app, not your domain.
If, instead of trying to look up the current user from your service, or document, you perform the check in your MVC app, you get something like this:
if(Roles.IsUserInRole("DocumentEditorRole")){
//UpdateDocument does NOT authorize the user. It does only 1 thing, update the document.
myDocumentService.UpdateDocument(currentUsername, documentToEdit);
} else {
lblPermissionDenied.InnerText = #"You do not have permission
to edit this document.";
}
which is clean, easy to read, and allows you to keep your services and domain classes free from authorization concerns. You can still map Roles.IsUserInRole("DocumentEditorRole")to your viewmodel, so the only this you are losing, is the CurrentUserCanEdit method on your Document class. But if you think of your domain model as representing real world objects, that method doesn't belong on Document anyway. You might think of it as a method on a domain User object (user.CanEditDocument(doc)), but all in all, I think you will be happier if you keep your authorization out of your domain layer.

asp.net mvc authentication against shibboleth and authorization

Where do I get information about the currently connected user? That is, how does shibboleth pass the information?
Can I set some restrictions on actions using [Authorize] attribute based on data acquired from shibboleth?
Shibboleth publishes user attributes associated with
sessions into HTTP request headers, based on header names defined
in Attribute Acceptance Policy (1.3.x) or Attribute Mapping (2.x)
files. These headers are transformed into CGI variables based
on mapping rules defined by the CGI specification.
You should be aware of this security advisory:
http://shibboleth.net/community/advisories/secadv_20090615.txt
I have never user shibboleth, but you can get information about the user from Controller.User property. It will return a generic principal of current thread. Using this principal you can check whether the user is authenticated and get a login name of the user. This is due to the reason that after logon an authentication cookie is set and this cookie contains limited amount of information. And on each request after logon only this cookie is checked (if it exists and valid - user is authenticated).
So if you need in some specific information you can manually load a user (it's better to use cache here) and check whatever you want.
Also you can create and attach your own principal with necessary information to the thread on start of a request (e.g. on start of a request load the user from db/cache using user name from base principal, create and set your own principal to thread). After this you can check all properties of the user you need.
Where would you attach your own principal? You say on the start of the request but what if you don't want every request authorizing?
You'll want to create a method in Global.asax.cs that has the following signature
protected void Application_PostAuthenticateRequest()
{
//Your code here.
}
This will be called automatically before almost anything else is done (MVC will call this method if it exists, you don't have to "turn it on" anywhere), and this is where you need to set the Principal. For instance, let's assume you have a header called RolesHeader that has a comma separated value of roles and another header called UserId that has (duh) the user ID.
Your code, without any error handling, might look something like:
protected void Application_PostAuthenticateRequest()
{
var rolesheader = Context.Request.Headers["RolesHeader"];
var userId = Context.Request.Headers["UserId"];
var roles = rolesheader.Split(',');
var principal = new GenericPrincipal(new GenericIdentity(userId), roles);
Context.User = principal;
}
It's the Principal/Identity that the [Authorize] attribute uses, so setting it here at the beginning of the request lifecycle means the [Authorize] attribute will work correctly.
The rest of this is optional, but I recommend it:
I like to create my own custom classes that implement IPrincipal and IIdentity instead of using the GenericPrincipal and GenericIdentity, so I can stuff more user information in it. My custom Principal and Identity objects then have much more rich information, such as branch numbers or email addresses or whatever.
Then, I create a Controller called BaseController that has the following
protected new CustomPrincipal User
{
get
{
return (base.User as CustomPrincipal) ?? CustomPrincipal.GetUnauthorizedPrincipal();
}
}
This allows me to access all my rich, custom Principal data instead of just what's defined in IPrincipal. All of my real controllers then inherit from BaseController instead of directly from Controller.
Obviously, when using a custom Principal like this, in the Application_PostAuthenticateRequest() method, you'd set the Context.User to be your CustomPrincipal instead of a GenericPrincipal.

Resources