I have a custom MembershipProvider as shown below. It validate user name and password against Active Directory. I would like to make this as an “authentication service”. This should work even if the client uses forms authentication or windows authentication.
There is a WCF “HR Service” which is providing employee information. The “HR UI” website is using “HR Service” WCF service. Now we need to ensure that any client using the “HR Service” should be authenticated using “authentication service” before accessing the operation of “HR Service”. If the client application is authenticated once, next time onwards it should not be validated again (till the application is closed). When a new instance of the client application is opened it need to be authenticated from beginning.
How do we achive it? Do we have any code samples for the end to end flow demonstration?
Note: I should be able to test it using self hosted services.
Note: The client can be of any platform (e.g. Java).
namespace LijosCustomValidation
{
public sealed class LijoMembershipProvider : MembershipProvider
{
public override bool ValidateUser(string username, string password)
{
bool isValid = true;
//my logic to validate the user name and password
return isValid;
}
//other implementations of Abstract Methods from MembershipProvider
}
Your auth service should return a token if the auth is successful. This token in turn should then be presented to the HR service.
You have a couple of options as to what the HR service does at this point. It can either know the secret to validate the token, or it needs to call the auth service to validate the token.
The token should be some value that can be validated if you know the secret, so it could something, say the users id, that is symmetrically encrypted. Ideally it should have a time component in it to prevent replay attacks.
I'd suggest some something like
<hash value>|<token issue time>|<user id>
The hash value should be hash (sha1, md5, etc) of everything after the first pipe. You can then base64 encode the result and pass it around. Validating the token could then check the issue date was within a certain time-frame.
You also have the option of storing the token in the client in a cookie and passing as a cookie to the services, or making it a parameter on your services. There may be other options, depending on your client architecture & how you want to structure your services.
Related
I have an ASP.NET web application, let's call it Web App A, that is self-hosted using OWIN and NancyFX.
Web App A uses Basic Authentication, which is set up in CustomBootstrapper.cs like this:
pipelines.EnableBasicAuthentication(new BasicAuthenticationConfiguration(
container.Resolve<IUserValidator>(),
"MySpecificRealm"));
After querying the user for the username and password, Web App A calls an authentication REST API to validate the credentials and return a security token if they are valid.
I am being asked to make a subset of that app, let's call this subset Web App B, when a valid security token is specified in the URL instead of prompting for the credentials.
The following picture might help explain this:
Per the usual, there are various modules in Web App A that call:
this.RequiresAuthentication();
How can I bypass the authentication when a valid security token is passed as a parameter in the URL?
You need to either add a parameter to a config file or use a conditional compilation symbol. Either of these will set a flag that you can then check to bypass the wiring up of the Basic Authentication in the pipelines and possibly the this.RequiresAuthentication().
For those Nancy Modules that require authentication, add a required URL parameter to the incoming request for the caller to supply the security token.
You are going to need the REST API to have a call that validates the security token, and you will need to call it and receive back the userName so you can create your IUserIndentity.
We have a need to protect our WebApi services with 2 separate authentication schemes, but we need both to be required.
Here's the scenario:
We have an internal service registry where service consumers will register for an API Key and shared secret. These are then used in a standard pattern for generating a HMAC that should be sent with every web service call. These API Keys essentially represent software system.
However, at an application level, we also want to authenticate our users individually. We're using an OAuthAuthorizationServerProvider to connect to LDAP to authenticate the user, pull some roles from our app internally, and then generate/return the Bearer token.
I initially tried creating a custom AuthenticationHandler Owin middleware to implement the HMAC scheme, but this wasn't working how I wanted. In that scenario, if either the HMAC or OAuth authenticated, the user was granted access.
What I've done in the interim is changed the HMAC logic as a more generic OwinMiddleware. Here's a general idea of what I'm doing:
public class HMACMiddleware : OwinMiddleware
{
private HMACOptions _HMACOptions;
public HMACMiddleware(OwinMiddleware next, IAppBuilder app, HMACOptions options) : base(next)
{
_HMACOptions = options;
}
public override Task Invoke(IOwinContext context)
{
// Pull headers use for HMAC generation, process them and handle any errors
// Authenticate with the external service registry
string authFailureReason;
var authenticated = _HMACOptions.AuthStrategy.DoAuthentication(requestData, out authFailureReason);
if(authenticated)
{
return Next.Invoke(context);
}
else
{
context.response.StatusCode = 401;
contextresponse.ReasonPhrase = "An error occurred authenticating via HMAC";
return context.response.WriteAsync(authFailureReason);
}
}
}
If HMAC auth fails, I short circuit the Owin pipeline and return immediately.
There are a couple things I don't like about this implementation in its current form:
This applies to every Owin request. What I really want it to apply to is every WebAPI route instead. That way we can supply WebApi help pages that don't need to be authenticated against
Is this really the correct way to handle this? It feels like it should be an AuthenticationHandler, but I could not figure out how to make it required, even if another authentication scheme authenticated
A side question: We have a version of this for WebApi as a DelegatingHandler. That version can access the target method (IE: if the route comes in as /api/users/1, we can access the GET method of the UsersController) by using the controllerSelector and actionSelector from webApi's GlobalConfiguration. We can then check that method for custom attributes that may affect the call we make to the HMAC Authenticator. Is there anyway to do something similar in Owin?
I have WCF Service where user can add a simple message. Before service put message to database, I need to authorize user, like here:
[OperationContract]
[WebGet(UriTemplate = "/GetMessages/{SessionToken}/{UserPassword}/{UserGLKNumber}")]
Messages GetMessages(string SessionToken, string UserPassword, string UserGLKNumber);
It's obvious that this solution is not good (sending in url user password and number). So, what is other approach?
What is important - I have a client written in Java/PHP/Obj-C (simple, small application) - anyway not in C#.
Write Login method and use ASP.NET auth cookie (forms based authentication), see this. Or use Basic authentication and let client to authenticate by http standard way.
You have to distinguish between Authentication (who is it) and Authorization (what can he do than). For the first you have a variety of options where Windows (the logon credentials of the user) or Basic (username + password) are most straightforward. This is just a manner of configuration on the service side.
On the other hand, authorization can be done on identity (which user is it) or by role (which roles apply to this user). The latter is possible "in code" with if/else constructs but also with attributes on the method [PrincipalPermission(SecurityAction.Demand, Role="Administrator")]. This specifies that you "demand" that the user accessing the method has the "role" administrator (something you specify yourself).
To supply roles to the identity you need some sort of role provider, obviously it is not something the user can provider. Therefore you can use the ASP.NET RoleProvider or a Secure Token Service that stands in between.
You can read more about it here: http://msdn.microsoft.com/en-us/library/ff405740.aspx
For a WCF service host implementation, I need to roll my own authentication & authorization procedure, but I can't find any information about how WCF supports this. The system should be pretty straight forward using Username, Password for authentication and Role to check for operation permissions.
In WPF documentations and tutorials, all I found is authentication using WinLogon, IIS login or security certificate and permissions using ASP.Net roles and security realms. What I would like to have is (pseudo example):
myChannelFactory.Username = "myuser";
myChannelFactory.Password = "mypass";
myChannelFactory.CreateChannel();
and for operation contracts
[OperationContract(Permission = MySecurityRoles.Administrator)]
public bool Reboot();
There are many possibilities how you could achieve this.
You could use sessions and authenticate in the first call by passing username and password to the server.
http://www.codeproject.com/Articles/188749/WCF-Sessions-Brief-Introduction
Or you could (as you do in the example code) use the existing features and create a custom Username and Password validator on the server.
This example is quite nice:
http://msdn.microsoft.com/en-us/library/aa702565.aspx
You can then check the role in the actual implementation.
i am working on project in which we are creating a web service that is called from desktop application.my problem is that how i provide security to the web method when they called from desktop application so that only authenticated member can access that method.
How I pass user name and password through SOAP header.
But at not all the time when we call a method i want to authenticate the user name and password .i want to authenticate a user only for the first time when he called a web method and for next call a token will generate that will we used for future references.
Please give me solution for all that problems immediatly.
or another way to impliment security to web service.
Please give solution with coding.
You need to set the authentication type in IIS on the webserver. http://technet.microsoft.com/en-us/library/cc733010(WS.10).aspx
The type will depend on your application (in-house app, external etc.) and how important security is to you.
You could store the credentials in an encrypted section in your client app.config file. Then authenticate each time you call the webservice.
Note that Basic Authentication sends the username/password combo in the clear (base64 encoding) so it is recommended to use SSL with this.
You can create credentials to pass to the webservice like so (where ConfigurationUtility is a custom helper class and WebServiceCredentials retrives the credentials from a custom config section in the config file).
CredentialCache credentialCache = new CredentialCache();
CredentialElement credentials = ConfigurationUtility.WebServiceCredentials;
NetworkCredential netCredential = new NetworkCredential(
credentials.UserName,
credentials.Password,
credentials.Domain);
You can programmatically encrypt config sections using
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ConfigurationSection section = config.GetSection(sectionName);
if (!section.SectionInformation.IsProtected)
{
// Protecting the specified section with the specified provider.
section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
}
section.SectionInformation.ForceSave = true;
config.Save(ConfigurationSaveMode.Modified);
Note: you don't need to decrypt the section, this is done for you.
You can accept (any and all) SSL certs programmatically
ServicePointManager.ServerCertificateValidationCallback += this.ValidateRemoteCertificate;
private bool ValidateRemoteCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors)
{
return true;
}
Even if you pass the username and password through the soap headers anybody sniffing the packets will be able to lift this out easily. Even if you encrypt the data then a hacker can easily reuse the encrypted headers.
I would consider doing the following:-
Put a SSL certificate on the webserver (this is a VERY cheap option now)
Create a login service that accepts a username and password and then returns a token as a guid
When user successfully authenticates pass back the token and loginId, log this token guid and login id into the database on the server. Every time the user logs back in then recreate a new token guid
Every time the user calls another webservice pass the token and login and check against the database to make sure user is still logged in
You can every be clever with dates to see when a user last authenticated and expire them if need be.
Because you are using SSL the connection between the server and the client is secure. All data that gets transmitted including GET and POST data is encrypted