Hello,
Thank you in advance for any help provided here. I read the answers on this post and still have a problem with my custom Principal/Identity implementation.
I am using Csla 4.1.0 and seem to be having a cast issue. This is the same scenario as the OP in the linked thread where I am trying to get to custom properties that have been implemented into my CustomIdentity class.
When I try to cast Csla.ApplicationContext.User.Identity to CustomIdentity, I get "Unable to cast object of type 'System.Security.Principal.GenericPrincipal' to 'DMS.Library.Security.CustomIdentity.'
Here's the code in question:
public int UserOrgCount {
get {
var identity = (CustomIdentity)Csla.ApplicationContext.User.Identity;
return identity.Orgs.Count();
}
}
I thought I followed the ebook pretty well and in fact everything seems to be working. The only thing I want to get access to now is the Identity properties so that I can replace individual database calls with data that's already been loaded into my custom properties.
Let me know if there is any other information I can provide.
For reference, here is my CustomPrincipal and CustomIdentity objects:
using System;
using System.Security.Principal;
using Csla.Security;
using Csla.Serialization;
namespace DMS.Library.Security {
[Serializable]
public class CustomPrincipal : CslaPrincipal {
private CustomPrincipal(IIdentity identity)
: base(identity) { }
/// <summary>
///
/// </summary>
/// <param name="username">The user's username</param>
/// <param name="password">The user's password</param>
/// <param name="completed"></param>
public static void BeginLogin(string username, string password, Action<Exception> completed) {
DMS.Library.Security.CustomIdentity.GetCustomIdentity(username, password, (o, e) => {
if (e.Error != null)
Logout();
else
Csla.ApplicationContext.User = new CustomPrincipal(e.Object);
completed(e.Error);
});
}
#if !SILVERLIGHT
/// <summary>
/// NOT IMPLEMENTED - Attempts to login the user with their username and password
/// </summary>
/// <param name="pUserName">The user's username</param>
/// <param name="pPassword">The user's password</param>
/// <remarks>
/// As of 05/07/2015, this function is not used because it will create a circular execution of code.
/// Validation of credentials is handled within the ValidateUser function of each implemented Membership provider.
/// Assuming the ValidateUser function returns true, the Principal's Load function is used instead
/// </remarks>
public static void Login(string username, string password) {
throw new NotImplementedException("The CustomPrincipal Login method has not been implemented. Refer to the remarks section of method's code for an explanation.");
//var identity = DMS.Library.Security.CustomIdentity.GetCustomIdentity(username, password);
//Csla.ApplicationContext.User = new CustomPrincipal(identity);
}
public static void Load(string username) {
var identity = DMS.Library.Security.CustomIdentity.GetCustomIdentity(username);
Csla.ApplicationContext.User = new CustomPrincipal(identity);
}
#endif
/// <summary>
/// Replaces the current CustomPrincipal object with a new one that has an UnauthenticatedIdentity loaded up.
/// </summary>
public static void Logout() {
Csla.ApplicationContext.User = new UnauthenticatedPrincipal();
}
}
}
Hi,
The issue here is that you have lost your custom principal object and now has the default GenericPrincipal which is a built-in type in .NET.
This could be caused by some configuration error (AuthenticationType) or that your code has used async methods that does not transfer the "current" principal to the executing (background) thread.
CSLA contains a custom BackgroundWorker and CslaTaskScheduler that will make sure to transfer the principal and ApplicationContext to background thread.
Hi Jonny,
Thank you for your response and all of your support with CSLA. Personally, I really appreciate it.
Regarding my issue, it looks like the problem has been resolved thanks to some of your suggestions. Essentially, I did the following:
To my knowledge, we are not running anything async. Also, it appears the AuthorizeDataPortal configuration I had in place was not set up correctly. As I recall (from when I would debug) within the AuthorizeDataPortal's Authorize method, I could never get to the CustomPrincipal.Load method. It would always load an UnauthenticatedPrincipal. Once I removed the concept of the AuthorizeDataPortal to avoid passing the Principal object over the wire, I was able to avoid "losing" my Csla.ApplicationContext.User.
As of right now, I believe this was the configuration error you were referring to in your previous post. If anything comes up, I will follow up. Thank you again for all of your support!
Copyright (c) Marimer LLC