The code you have posted looks okay to me. So it's likely something trivial with your setup.
I have created a simple, self hosted app which also uses a CustomUserSession
and a CustomCredentialsAuthProvider
, hopefully using this as a guide will highlight what is going wrong. Let me know how you get on.
using ServiceStack.CacheAccess;
using ServiceStack.CacheAccess.Providers;
using ServiceStack.ServiceInterface;
using ServiceStack.ServiceInterface.Auth;
using ServiceStack.ServiceHost;
using ServiceStack.WebHost.Endpoints;
namespace Testv3
{
class MainClass
{
public static void Main()
{
// Very basic console host
var appHost = new AppHost();
appHost.Init();
appHost.Start("http://*:8082/");
Console.ReadKey();
}
}
public class AppHost : AppHostHttpListenerBase
{
public AppHost() : base("Test Service", typeof(TestApp).Assembly) {}
public override void Configure(Funq.Container container)
{
// Cache and session IoC
container.Register<ICacheClient>(new MemoryCacheClient());
container.Register<ISessionFactory>(c => new SessionFactory(c.Resolve<ICacheClient>()));
// Register the Auth Feature with the CustomCredentialsAuthProvider.
Plugins.Add(new AuthFeature(
() => new CustomUserSession(),
new IAuthProvider[]
{
new CustomCredentialsAuthProvider(),
new BasicAuthProvider(),
})
);
}
}
public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
// Replace with a database lookup
return (userName == "clark.kent" && password == "kryptonite");
}
public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
{
var customSession = session as CustomUserSession;
if(customSession != null)
{
// Replace these static values with a database lookup
customSession.FirstName = "Clark";
customSession.LastName = "Kent";
customSession.SuperHeroIdentity = "Superman";
}
authService.SaveSession(customSession, SessionExpiry);
}
}
public class CustomUserSession : AuthUserSession
{
// Our added session property
public string SuperHeroIdentity { get; set; }
}
public static class TestApp
{
[Route("/SuperHeroTime", "GET")]
public class SuperHeroTimeRequest {}
public class TestController : Service
{
public CustomUserSession CustomUserSession
{
get
{
// Returns the typed session
return SessionAs<CustomUserSession>();
}
}
[Authenticate]
public object Get(SuperHeroTimeRequest request)
{
// Return the result object
return new { CustomUserSession.FirstName, CustomUserSession.LastName, Time = DateTime.Now.ToString(), CustomUserSession.SuperHeroIdentity };
}
}
}
}
If you put this index.html
in your bin
folder and navigate to http://localhost:8082/index.html
you can call the service, to test it.
<!doctype html>
<html>
<head>
<title>Test</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
function login()
{
$.ajax({
type: "POST",
url: "/auth/credentials",
contentType: "application/json",
data: JSON.stringify({
UserName: "clark.kent",
Password: "kryptonite",
RememberMe: true
})
}).done(function(result){
getSuperHeroTime();
});
}
function getSuperHeroTime()
{
$.ajax({
type: "GET",
url: "/SuperHeroTime",
contentType: "application/json",
}).done(function(result){
$("#result").html(result.FirstName + " " +
result.LastName + " is " +
result.SuperHeroIdentity + " (" +
result.Time + ")");
});
}
</script>
</head>
<body>
<h1>Super Hero Time</h1>
<button onclick="login()">Go</button>
<div id="result"></div>
</body>
</html>
Update:
Having looked at your usage code provided in your edit. You are calling the Auth method in
SomeClass1
and then thatJsonServiceClient
isn't reused. So your session won't follow. You have to reuse the client, because the client stores the cookies that track your session.In
SomeClass2
you are effectively calling the service without authenticating, so the session isnull
. You need to reuse the sameJsonServiceClient
for your requests.You could run your authentication method and then pass the session cookies to any subsequent
JsonServiceClient
, to save re-authenticating with each client. It's easy to do:var authClient = new JsonServiceClient(url); authclient.Post<AuthResponse>("/auth", new Auth { UserName = "clark.kent", Password = "kryptonite", RememberMe = true }); // Get the session cookies var cookies = authClient.CookieContainer.GetCookies(new Uri(url)); // In your other `JsonServiceClient`s set the cookies before making requests var anotherClient = new JsonServiceClient(url); anotherClient.CookiesCollection.add(cookies); anotherClient.Post( ...
You are also trying to resolve another service within your service using:
base.TryResolve<EService>();
You need to use this instead, or you will see the
Only ASP.NET Requests accessible via Singletons are supported
exception:base.ResolveService<EService>();