I have a working custom UserNamePasswordValidator that calls into my Oracle DB.
This class derives from System.IdentityModel.Selectors.UserNamePasswordValidator and
I have exactly the same issue.
I am using an API to connect to my underlying Oracle Database, and I "validate" logon details by opening a connection.
I then want to store this connection somewhere (easy enough, I will create a connection pool for all the different users), but also create a custom Identity and Principal representing this user, so that once it gets to my custom IAuthorizationPolicy, it doesn't need to reload this information.
I have done a lot of searching and not found anything so my plan is to do this:
Validate login details in custom UserNamePasswordValidator by opening API connection.
Store opened connection in connection pool under the user name.
When my custom IAuthorizationPolicy.Evaluate() is called, I will look at the generic identity provided:
IIdentity GetClientIdentity(EvaluationContext evaluationContext)
{
object obj;
if (!evaluationContext.Properties.TryGetValue("Identities", out obj))
throw new Exception("No Identity found");
IList identities = obj as IList;
if (identities == null || identities.Count <= 0)
throw new Exception("No Identity found");
return identities[0];
}
(sorry I can't get rid of this poor HTML escaping)
I then grab a connection from the pool based on the IIdentity.Name, use this connection to load up user-specific data from the database and store this in a custom Identity and Principal which I set in the EvaluationContext:
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
IIdentity identity = GetClientIdentity(evaluationContext);
if (identity == null)
throw new Exception();
// These are my custom Identity and Principal classes
Identity customIdentity = new Identity();
Principal customPrincipal = new Principal(customIdentity);
// populate identity and principal as required
evaluationContext.Properties["Principal"] = customPrincipal;
return true;
}
Then I should have access to my custom identity and principal whenever I need it by using System.Threading.Thread.CurrentPrincipal or CurrentIdentity.
Hope this helps in some way; I'm not sure it's the best way to go about it, but it's the best I've come up with so far...
Steve