Hi there (long time reader, first time poster)
Here is problem folks, I have lots of services using the standard AspNetSqlMembership authorization.
<webhttpbinding>
<binding name="webHttpTransportBinding">
<security mode="Transport">
</security>
</binding>
</webhttpbinding>
<behavior name="TaskServiceBehavior">
<serviceauthorization principalpermissionmode="UseAspNetRoles" roleprovidername="AspNetSqlRoleProvider" />
<servicemetadata httpgetenabled="true" httpsgetenabled="true" />
<servicedebug includeexceptiondetailinfaults="true" />
<servicecredentials>
<servicecertificate findvalue="XXXXXCERT" storelocation="LocalMachine" storename="My" x509findtype="FindBySubjectName" />
<usernameauthentication usernamepasswordvalidationmode="MembershipProvider" membershipprovidername="CustomMembershipProvider" />
</servicecredentials>
</behavior>
<endpointbehaviors>
<behavior name="AspNetAjaxBehavior">
<enablewebscript />
</behavior>
</endpointbehaviors>
<service behaviorconfiguration="TaskServiceBehavior" name=" Business.Managers.Managers.TaskManager">
<endpoint>
address=""
binding="wsHttpBinding"
bindingConfiguration="wsCertificateBinding"
contract=" Business.Contracts.Service.ITaskService" />
<endpoint>
address="api/ssl"
binding="webHttpBinding"
bindingConfiguration="webHttpTransportBinding"
behaviorConfiguration="AspNetAjaxBehavior"
contract="Business.Contracts.Service.ITaskService" />
<endpoint>
address="api"
binding="webHttpBinding"
behaviorConfiguration="AspNetAjaxBehavior"
contract="Business.Contracts.Service.ITaskService" />
</endpoint></endpoint></endpoint></service>
When I’m using webHttBinding, without HTTPS, and there is no “OperationContext.Current.ServiceSecurityContext” so I can just inject the user name and password in the ajax request and presto… I can set the user by setting Thread.Principal = ...
private void AuthenticateWebHttpRequest(string authorizationHeader)
{
try
{
string applicationHeader = HttpContext.Current.Request.Headers["Authorization"];
if (authorizationHeader != null && authorizationHeader.StartsWith(_headerAutorizationContainer))
{
string encodedUserPass = authorizationHeader.Substring(_headerAutorizationContainer.Length + 1).Trim();
Encoding encoding = Encoding.GetEncoding(_encoding);
string userPass = encoding.GetString(Convert.FromBase64String(encodedUserPass));
string[] credentials = userPass.Split(':');
string username = credentials[0];
string password = credentials[1];
string application = encoding.GetString(Convert.FromBase64String(applicationHeader));
if (Membership.ValidateUser(username, password))
{
HttpApplication app = HttpContext.Current.ApplicationInstance;
if (app != null)
{
string[] roles = Roles.GetRolesForUser(username);
var genericIdentity = new System.Security.Principal.GenericIdentity(username);
var genericPrincipal = new System.Security.Principal.GenericPrincipal(genericIdentity, roles);
HttpContext.Current.User = genericPrincipal;
Thread.CurrentPrincipal = genericPrincipal;
_application = application;
_operationUser = username;
}
}
}
}
catch(Exception ex)
{
Logger.LogException(this.Application, this.OperationUsername, ex);
throw new FaultException(ex.Message);
}
}
This is the client code
var username = 'xxxxxxxxxxxxx@xxxxxxxxxx.com';
var password = 'xxxxxxxxx';
var application = 'Mobile';
var sendData = { accountId: 1, userId: 2, recordCount: 100, taskListResponse: taskListResponse };
var jsonData = JSON.stringify(sendData);
$.ajax({
type: "POST",
url: "/TaskService.svc/api/ssl/GetTaskList",
data: jsonData,
dataType: "json",
contentType: "application/json; charset=utf-8",
beforeSend: function (xhr) {
xhr.withCredentials = true;
var creds = username + ':' + password;
var basicScheme = btoa(creds);
xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
xhr.setRequestHeader('Application', btoa(application));
xhr.setRequestHeader('username', username);
xhr.setRequestHeader('password', password);
},
}).success(function (data) {
var isValid = data.d.IsValid;
alert('valid');
}).error(function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
console.log(jqXHR.responseText);
console.log(textStatus);
console.log(errorThrown);
alert('error');
});
With the user injected it’s then valid to do this
[PrincipalPermission(SecurityAction.Demand, Role = SecurityRole.SystemAdministrator)]
public string GetTaskList(int accountId, int userId, int recordCount, string taskListResponse)
{
}
My problem occurs when HTTPS is used instead of HTTP. In those cases, the Principal is in “OperationContext.Current.ServiceSecurityContext” and doing HttpContext.Current.User = genericPrincipal; Thread.CurrentPrincipal = genericPrincipal; simply has no side effects. I can’t get permission to access the method.
I’ve tried a couple of things with no success. I can’t seem to be able to simulate sending the credentials over the ajax request. Username and Password don’t work and using “<transport clientcredentialtype="Basic"/>” seem to stop the service altogether.
Is there anyone out there that has done something similar?
Thanks in advanced for your time