How UserNamePasswordValidator reads username password from SOAP header? - wcf

I am using custom UserNamePasswordValidator for User Authentication. Following is the code and it works well.
I want to understand how does does this method gets username and password from UserNameToken from SOAP header.
public class DistributorValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
{
throw new FaultException("Username and password required", new FaultCode("9001"))
................

you should turn on WCF logging (or use Fiddler) to see how the soap message looks like. There you will see the token. WCF has a pretty complex model to extract the credentials from the message. There is a (de)serializer for the security header, and each token (username, x.509, etc) has its own deserializer.

Related

ServiceStack Authentication Return Custom Response

I'm implementing a custom CredentialsAuthProvider in ServiceStack and it works great. My only problem is that I would like to return more information back in my AuthResponse. I'm using the following override to authenticate in my custom provider:
public override bool TryAuthenticate(ServiceStack.ServiceInterface.IServiceBase authService, string userName, string password)
{
// Authenticates user and adds values to session
}
The response I get after successful authentication is the out of the box response that the Auth plugin provides. Is there a way to add more values or to customize the response upon successful login? I don't see any overrides that would allow it.

WCF - Get password from MessageHeader

I have a WCF service with security mode set to message. I use Username for client credentials type with a custom UserNamePasswordValidator.
NetTcpBinding binding = new NetTcpBinding(SecurityMode.Message, false);
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
Can I retrieve the password on server side, after the user is authenticated?
Is the password saved in MessageHeader of the request? Can I get it from MessageHeader (after user is authenticated)?
Angela
As far as I understand your question you have a WCF service which requires a user name and password for authentication. You have configured a custom UserNamePasswordValidator for this purpose instead of relying on the default mechanism employed by WCF (= Windows).
Take a look here for more information on how to setup a custom username and pasword validator in WCF:
http://msdn.microsoft.com/en-us/library/aa702565.aspx
I assume you have created a class that dervies from the UserNamePasswordValidator type. Your custom type is responsible for checking the username and password against a store (database, xml file...etc.) which contains a list of your users. The validator must determine if it is dealing with a valid user. If so, it can authenticate the user.
For example:
public class CustomUserNameValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (null == userName || null == password)
{
throw new ArgumentNullException();
}
// Validator username and password here
// bool isValid = ...;
if (!isValid)
{
throw new SecurityTokenException("Access denied.");
}
}
}
As you can see if you correctly implemented the custom UserNamePasswordValidator you already have a place where you can access the username and password which the client submitted.
If you want to access the username after the user has been authenticated, for instance in the body of one of service's methods you can use the following:
var userName =
OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name;
Take a look at the ServiceSecurityContext type for more information.
If you also want to make the password available, then I suggest you take a look at the following article:
http://www.neovolve.com/post/2008/04/07/wcf-security-getting-the-password-of-the-user.aspx
I guess you could also extract the username and password from the current OperationContext as one of the comments of the previously mentioned article suggests.
public void MyServiceMethod()
{
var context = OperationContext.Current;
var token = context.IncomingMessageProperties.Security
.IncomingSupportingTokens[0].SecurityToken as
System.IdentityModel.Tokens.UserNameSecurityToken;
//...
}

Port WCF SOAP service to REST service: How to implement user/password/token authentication

I've got a WCF service provided with a SOAP endpoint with the following service contract:
[OperationContract]
string Login(string sAuthUserName, string sAuthUserPassword);
[OperationContract]
Consumer GetData(string sAuthKey);
[OperationContract]
bool Logout(string sAuthKey);
[OperationContract]
DataSet GetSingleByRefID(string sAuthKey, int iCommand, int iRefID);
Calling Login() checks the provided sAuthUserName and sAuthUserPassword an generates a hash (sAuthKey) which will be further used for authentication.
How to port this to REST?
Using the following addresses?
/session/{sAuthUserName}/{sAuthUserPassword} [POST]
would be Login()
/consumer/{sAuthKey} [GET]
would be GetData()
/session/{sAuthKey}/ [DELETE]
would be Logout()
/data/single/{sAuthKey}/{iCommand}/{iRefID} [GET]
would be GetSingleByRefID()
Which is the best way to authenticate with username and password?
This should be only required once? And after that the REST-Consumer should be able to authenticate with it's AuthKey..
We have a similar situation and use header for auth related values (username, password, auth-key in your case). The auth related methods are called without any parameters. Communication happens over secure transport.
You can access header values like below
HttpRequestMessageProperty httpProperties;
string sAuthKey = default(string);
if (OperationContext.Current.IncomingMessageProperties.TryGetValue(HttpRequestMessageProperty.Name, out httpProperties))
{
sAuthKey = httpProperties.Headers["sAuthKey"];
}

Work with OData secured service

I want to generate entity classes and Service class of OData secured service.
In OData Java extension page it is written that I need to use org.restlet.ext.odata.Generator class that should get uri and output directory parameters.
But if my OData service is secured the generator instance is not able to generate service classes without username and password of the service.
I did not find any way to pass username and password to generator class.
I get 401 HTTP response code.
Please help.
In the org.restlet.ext.odata.Generator class, in the method main,
The following code would clear the credential details set in the setCredentials() method.
Service service = new Service(dataServiceUri);
if(service.getMetadata() == null)
{
errorMessage = "Cannot retrieve the metadata.";
}
Kindly provide a solution for this issue as I am currently unable to generate the classes for my rest service as the service is secured with an user password.
I tried the following code to generate the code for my secured service uri:
import org.restlet.ext.odata.Generator;
import org.restlet.ext.odata.Service;
import org.restlet.data.ChallengeResponse;
import org.restlet.data.ChallengeScheme;
public class ODataRestletGenerator extends Service {
public ODataRestletGenerator(String serviceUri) {
super(serviceUri);
}
public static final String APPLICATION_URI = "http://ldcigkd.xxx.yyy.corp:50033/xxx/opu/sdata/IWCNT/CUSTOMER/";
public static void main(String[] args) {
// Add the client authentication to the call
ChallengeScheme scheme = ChallengeScheme.HTTP_BASIC;
ChallengeResponse credentials = new ChallengeResponse(scheme, "user", "pwd");
new ODataRestletGenerator(APPLICATION_URI).setauth(credentials);
String[] arguments = { APPLICATION_URI, "/customer/src" };
Generator.main(arguments);
}
private void setauth(ChallengeResponse credentials) {
super.setCredentials(credentials);
}
}
In the org.restlet.ext.odata.Service subclass that is generated by OData extension, you can call setCredentials() and pass an instance of ChallengeResponse including scheme (BASIC?), login (identifier) and password (secret).

Getting details of the call to a WCF service in custom UserNamePasswordValidator

I have a WCF service setup with my own UserNamePasswordValidator. When authentication fails in the Validate(string userName, string password) method I want to write the details to a log as well as throwing a FaultException.
I want to store details of the particular service method that was being called and the parameters that were passed in as well as the username.
How do I access these details from inside the Validate method?
Example code below:
public class ColesUserNameValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (CheckCredentials(userName, password))
{
return;
}
else
{
// do something here to get details of the call to the service and send them to a log file
throw new FaultException("Unknown Username or Incorrect Password");
}
}
It is not possible. Validation runs in different thread and it doesn't have access to WCF contexts. Also no WCF context contains information about service method which was called. Incomming message only contains information about SOAP Action which was requested.
If you want to make some logging implement IErrorHandler. Throw SecurityTokenException from custom validator and handle this expection in ProvideFault of IErrorHandler - create FaultException. In HandleFault of IErrorHandler you can implement logging. For logging you can check if OperationContext.Current is not null (yes it can be if exception is thrown before message processing) and access information about current operation call.