I have a web service that is outward-facing, however I need to generate a verification system to ensure that a request came from a valid client.
Let's say the original web service is defined as follows:
[OperationContract]
public void Service.RequestMethod (string clientId, int reqNumber,
string reqText)
{
// do stuff with the parameters
}
I want to make sure that the request actually came from the client specified by the clientId parameter.
My current plan is to add another parameter to the method signature, giving a checksum of sorts.
[OperationContract]
public void Service.RequestMethod (string clientId, int reqNumber,
string reqText, string reqChecksum)
{
// verify reqChecksum, then
// do stuff with the parameters
}
I need a function that verifies that the checksum was calculated by the approved client. It should be calculated on the reqNumber and reqText parameters as well as a client-specific "password" known by both client and server.
In effect, it should be:
private bool VerifyChecksum(int reqNumber, string reqText,
string clientPassword, string reqChecksum)
{
// hash reqNumber, reqTxt, and clientPassword
// ensure it matches reqChecksum
}
Does anyone have any suggestions for this hashing function or the model as a whole?
It needs to be message-specific, client-specific, and hard to guess (high entropy).
You're probably looking for some kind of MAC. Something like MD5 for the hash. The whole idea of MD5 is that you apply it to "some" data and get a value. As long as the "some data" part is not known to everyone, it's almost impossible to reproduce the value.
Why not use one of the standard web services authentication methods? You'll have a choice of well-known and widely implemented solutions and won't muddy up your interface by trying to pass both parameters and authentication information.
You might still have an authorization problem if an authenticated client can pass more than one 'clientId', but again there are plenty of known solutions to this and it's entirely on your side. E.g., you could go as far as an ACL implementation that lists all acceptable (userId, clientId, methodname) combinations and forbids everything else.
Related
im currently developing a user interface to manage users and stuff. As data store I have to use a ldap. I'm using the novell.directory.ldap library for ldap related things.
I'm now wondering if this library already does encoding of parameters it is receiving, e.g. when performing a search, or if I have to encode potential user input, like usernames which will be later used in searchqueries, by myself.
I've already tried to do encoding with the AntiXSSLibrary (I'm using the nuget package sicne the ldap encoding was not included in the .net Framework itself like the other parts of the library) and its Encoder.LdapFilterEncode() and Encoder.LdapDistinguishedNameEncode() methods.
This is my code when trying to encode:
public static LdapSearchResults PerformSearch(LdapConnection connection, string filter, string basedn)
{
string encodedFilter = Encoder.LdapFilterEncode(filter);
string encodedBasedn = Encoder.LdapDistinguishedNameEncode(basedn);
LdapSearchConstraints searchConstraints = new LdapSearchConstraints { BatchSize = 0 };
return connection.Search(encodedBasedn, LdapConnection.SCOPE_SUB, encodedFilter, null, false, searchConstraints);
}
If I pass the parameters directly (= not encoded) everything will work as expected.
If I pass the encoded filter I will receive a LdapLocalException with message "Filter Error" at the Search() method of the LdapConnection instance.
If I pass the unencoded filter and pass the encoded basedn I will receive a LdapException with message "Invalid DN syntax" when trying to access the search results.
If I pass the unencoded filter and pass the ecoded basedn, in this case encoded with the Encoder.LdapFilterEncode() method, everything will work fine.
So the central question is: Do I have to worry about ldap injection or is the library already taking care about this threat? Unfortunately I couldn't find an answer for this in the documentation and by searching the web.
If I have to encode (what I'm expecting I have to do at the moment) what is the easiest and safest way to encode inputs for ldap in C#/.Net when the AntiXSSLibrary is not working for me?
How about this system. I need some comments and maybe critical security part for this.
System which I use is maybe little bit complicated but 100% custom and should be good. This is a system for custom authentication in sending request to Asp.NET
WebApi
System works with sending 2 request
Everything what you need is 2 pairs of data. 1st one is public and 2nd one is secret.
Second pair of data be must be known to both sides (sender and receiver)
public: ApiKey and RequstID where ApiKey is "normal" and requstID have to be unique always;
secret: UserName and Password (both side have to know these data)
Sender:
Send 1st request with 3 parameters: 1st= ApiKey, 2nd=RequstID, 3rd=Hash(ApiKey+RequestID+USerName+Pass)
Server:
Read RequstID
Read ApiKey and get data about users UserName and Pass for this ApiKey
From the own side: Hash(ApiKey+RequestID+USerName+Pass)
Check is Hash from Sender same us from Server
If is False:
BadRequest - or whatever...
if is True
Before all - Create on database on table for collect data about request.
This is table with columns (e.g.):
ID(autoincrement), RequstID, Token, TokenValidateDateTime
Before create new row, check is there already this RequestID and if there is return BadRequest.
If there is not - make new row.
RequstID is RequstID from request;
Token - Generate token (e.g. Guid.NewGuid().ToString());
TokenValidateDateTime= DateTime.Now.AddMinutes(2) - or some other value ...
In response for the first request send back this this Token (from item 2)
In the second request, Sender have to use AGAIN same RequstID and Token (from response before)
Server will check
Combination RequstID and Token
Token validation (depend on current date time);
Is everything is OK, user is validated
if is not - BadRequest, or whatever
Any suggestions or comments are welcome :)
It sounds similar to traditional website username / password authentication which returns a session cookie.
But you're also including a api key & request id and a hash. The hash won't add to much value unless there's a shared salt, as once someone works out your hashing technique it will be vulnerable to dictionary attacks.
Also generating a Guid token isn't "cryptographically secure", it is designed to be unique but it's often based upon the system clock meaning it is predictable.
Building bespoke security mechanisms are generally unadvised; doing bespoke encryption is defiantly a "no no" (which you aren't doing as far as I'm aware). Bespoke authentication is probably less risky, but seeing as there are many frameworks already existing that have been critiqued by security experts I'd suggest researching if any of those suit first.
I'd recommend looking at asp.net core's security options: https://learn.microsoft.com/en-us/aspnet/core/security/?view=aspnetcore-2.1
I can trying to set an authentication value just for testing purposes.
I am not using basic authentication but just a String
VC.Request.Headers.Authorization = new AuthenticationHeaderValue("Secret Password");
It gives me this error that is making me pulling my hair off:
The format of value 'Secret Password' is invalid.
Again I don't want to use basic authentication and I don't know whats wrong, help?
The class is "documented" as:
Represents authentication information in Authorization, ProxyAuthorization, WWW-Authneticate[sic], and Proxy-Authenticate header values.
By calling the constructor with one parameter, you're using "Secret Password" as scheme, which can only contain tokens (i.e. no spaces). See RFC 2617 for specification.
You might want to call the other constructor overload:
new AuthenticationHeaderValue("MySuperAuthScheme", "Secret Password");
I think basic authentication generally uses a username:password syntax, so the client-side code might be pre-validating it to stop you sending "bad" data mistakenly to the server, even though that's what you're intentionally trying to do. Try adding a : and see if that helps.
I am using DotNetOpenAuth 4.0.20926 and trying to implement an OAuth2 based Authentication server with Db Nonce provider.
For some purpose I want to access username in NonceStore's StoreNonce function while processing the GetToken request.
I am not getting a way to retrieve Username in that call.
How can I solve this problem?
Hey Andrew thanks for your reply and DotNetOpenAuth.
My GetToken Method is like this
public ActionResult Token()
{
string userName = "";
//Want to fetch username here
//Using username here
var result = this.authorizationServer.HandleTokenRequest(this.Request);
return result.AsActionResult();
}
And I want to fetch the username before calling HandleTokenRequest.
Is there any Message Parser or Helper method to fetch the username from the request data / Code value .
As you've observed, the interface does not pass the username into the StoreNonce method. So the only way you may possibly be able to get the username would be for you to discover what it is first, before you instantiate your INonceStore instance, and pass it to that nonce store first, so that later when StoreNonce is invoked, it already knows the username.
That said, I believe any design where storing and checking a nonce requires the username needs some rethinking. Not only is it a mixing of concerns that otherwise should remain separate, you may be limiting yourself going forward or even introducing security holes.
I'm using a custom username and password validation for my WCF security. Now i would like to store the username during the request so that i can access it later in the method that is called. How do i do that?
Some sample code to describe my problem:
public class CustomUserValidator : UserNamePasswordValidator
{
public override void Validate(string username, string password)
{
if (username == "aaa" && password == "bbb")
{
// store username where i can get it in method called later.
return;
}
throw new SecurityTokenException("Unknown Username or Password");
}
}
Now the method that is being called:
public void WebServiceMethod()
{
Database.User.Single(c => c.Username == /* username from above */);
}
BR
Andreas
You would typically do this by issuing a custom "principal", which is done via IAuthorizationPolicy; IIRC, the username is made available to the auth-policy via the evaluation-context parameter. A general walkthrough to custom principals in WCF is here, however you may need to experiment a bit in Evaluate to find the incoming username in the evaluation context. In particular, if any of the keys is a "claims" dictionary, look at that. And look at the .Claims on the evaluation context - you should find a "claim" in their issued by CustomUserValidator with the username in it.
I have, however, done exactly what you describe in a previous job - and IIRC it worked fine, using the above page as my starting point.
Once you have issued a principal, it will be available, as normal, via:
string cn = Thread.CurrentPrincipal.Identity.Name;
To store data of any kind through a single WCF request, Darin Dimitrov suggests hooking up a simple IExtension<> helper class to the current OperationContext here: Where to store data for current WCF call?