Hi Demis,
I'm having no luck what so ever, service stack always seems to allow access to services that are marked: [authenticate], and I cant seem log users out. Is there anything obviously wrong with what I have below, sorry for the hassle, but I think I'm missing something really obvious :)
Created my own custom: CredentialsAuthProvider:
/// <summary>
/// Handles authentication to the service.
/// </summary>
/// <remarks>
/// overview of the authentication system:
https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization /// </remarks>
public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{
private readonly IUnitOfWorkFactory _UnitOfWorkFactory;
private readonly IUserDao _UserDao;
private readonly IUtilities _Utils;
public CustomCredentialsAuthProvider(IUtilities utils, IUnitOfWorkFactory uowFactory, IUserDao userDao)
{
_UnitOfWorkFactory = uowFactory;
_UserDao = userDao;
_Utils = utils;
}
/// <summary>
/// Try to authenticate the current user.
/// </summary>
/// <param name="authService">The auth service.</param>
/// <param name="userName">The username.</param>
/// <param name="password">The users password.</param>
/// <returns>A <see cref="bool"/> indicating if the user authenticated or not.</returns>
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
using (_UnitOfWorkFactory.StartUOW())
{
//Return true if credentials are valid, otherwise false
var user = _UserDao.GetByUserName(userName);
// Check the user isn't null and the hashed password is valid.
return user != null && _Utils.VerifySha1Hash(user.Salt, password, user.Password);
}
}
/// <summary>
/// Occours after the user is authenticated.
/// </summary>
/// <param name="authService">The auth service.</param>
/// <param name="session">The auth session.</param>
/// <param name="tokens">Any OAuth tokens</param>
/// <param name="authInfo">The auth infomation.</param>
public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
{
using (_UnitOfWorkFactory.StartUOW())
{
// Get the currently logged in user.
var user = _UserDao.GetByUserName(session.UserAuthName);
// Fill the IAuthSession with data which you want to retrieve in the app eg:
session.FirstName = user.FirstName;
session.LastName = user.LastName;
session.Email = user.Email;
session.DisplayName = user.Username;
session.CreatedAt = user.CreatedAt;
session.LastModified = user.UpdatedAt;
session.Sequence = user.Id.ToString();
session.UserName = user.Username;
session.IsAuthenticated = true;
// Set the role the user has.
if (user.Role != null)
{
session.Roles = new List<string>(new[] {
user.Role.Name });
}
// Important: You need to save the session!
authService.SaveSession(session, new TimeSpan(0, 30, 0));
}
base.OnAuthenticated(authService, session, tokens, authInfo);
}
}
Added it to the apphost like so:
// Set logging factory.
LogManager.LogFactory = new NLogFactory();
// Setup our user auth session.
container.Register<IAuthSession>(c => new AuthUserSession());
// Setup our infrastructure.
container.Register<IUnitOfWorkFactory>(c => new UnitOfWorkFactory());
container.Register<IAuthTokenService>(c => new ServiceStackAuthTokenService(c.Resolve<IAuthSession>()));
container.Register<IUtilities>(c => new Utilities());
// Daos:
container.Register<IUserDao>(c => new UserDao(c.Resolve<IUnitOfWorkFactory>(), c.Resolve<IAuthTokenService>(), c.Resolve<IUtilities>()));
// Validators:
container.RegisterValidators(typeof(UserDtoValidator).Assembly);
// Add the auth plug-in.
Plugins.Add(new AuthFeature(container.Resolve<IAuthSession>, new IAuthProvider[] { new CustomCredentialsAuthProvider(container.Resolve<IUtilities>(), container.Resolve<IUnitOfWorkFactory>(), container.Resolve<IUserDao>()) }));
Plugins.Add(new ValidationFeature());
container.Register<ICacheClient>(new MemoryCacheClient());
//var userRep = new InMemoryAuthRepository();
//container.Register<IUserAuthRepository>(userRep);
I then whipped up a simple client wrapping the json client. please ignore the code quality here :)
public class UserServiceClient
{
private readonly JsonServiceClient _Client;
if (HttpContext.Current.Session["AuthCookies"] != null)
{
_Client.CookieContainer.Add((CookieCollection)HttpContext.Current.Session["AuthCookies"]);
}
}
public UserDtoResponse Get(Guid id)
{
return _Client.Get<UserDtoResponse>(string.Format("/user/?id={0}", id));
}
public UserDtoResponse GetByUserName(string userName)
{
return _Client.Get<UserDtoResponse>(string.Format("/user/?username={0}", userName));
}
public AuthResponse Authenticate(string userName, string password, bool rememberMe)
{
var result = _Client.Send<AuthResponse>(new Auth{ UserName = userName, Password = password, RememberMe = rememberMe });
HttpContext.Current.Session["AuthCookies"] = _Client.CookieContainer.GetCookies(new Uri("
http://localhost:59532"));
return result;
}
public void LogOut()
{
// None of these appear to log out.
//_Client.HttpMethod = HttpMethod.Delete;
//var result = _Client.Send<AuthResponse>(new Auth());
_Client.Send<AuthResponse>(HttpMethod.Delete, "/auth/logout", new Auth());
// Clear the cookies, removing the auth details provided by ss.
HttpContext.Current.Session["AuthCookies"] = null;
}
}
Thanks!
Maxus
On Friday, June 22, 2012 5:33:34 PM UTC+8, mythz wrote:
The session id is kept in the cookies, I'd read up on Sessions to see how it works:
So you'll need to proxy the Cookies from the browser request into the CookieContainer of the service clients to properly impersonate the original request/user.
Cheers,