I'm authenticating users of an asp.net mvc web site by using ADFS Server 2016 passive redirection, and I cannot get claims from a SQL attribute store. I'm interested in discovering what I am doing wrong or missing.
Side note: I'm using the System.Identity libraries from Framework 4.5 (I'm not referencing the Microsoft.Identity libraries created for older framework versions; most ADFS code samples that I stumble across use these old libraries).
The basics are working well. All of this is in one domain. I have my asp.net web.config set up to redirect users to my ADFS server for authentication. The ADFS server successfully authenticates and redirects users back to my asp.net web site. On the ADFS I have one Claim Issuance Policy rule where I simply pass back all claims from the Active Directory.
On the web site I am able to iterate through the user's Claims collection and display them. Here is the code from the *.cshtml page where I iterate though the claims, it works fine:
@using System.Security.Claims;
@{
var currentPrincipalIdentity = (ClaimsIdentity)System.Threading.Thread.CurrentPrincipal.Identity;
}
@foreach (Claim claim in currentPrincipalIdentity.Claims)
{
<br/>@claim.Type : @claim.Value
}
In addition to these claims from Active Directory, I want to fetch a bunch of roles from a SQL Server database and add them to the Claims collection as roles. I'm fetching the roles from a legacy asp.net Membership database. As step 1 I just want to hard-code the username in the SQL statement (eventually I will need to figure out how to pass the username as a parameter to the SQL statement, but that will be step 2).
First, I gave the identity that the ADFS server runs under read/write/execute permissions on my SQL Server (when I take these permissions away I get a permissions error, which gives me confidence that my SQL statement is executing).
In my AD FS I added a SQL Server Attribute Store by right-clicking the "Attribute Stores" node, selecting an Attribute store type of "SQL", named is "SQLServer", and added a connection string like so:
Server=SqlDev01; Database=MyLegacyMembershipDatabase; Integrated Security=SSPI;
I then select the "Relying Party Trusts" folder, select the trust I am interested in, and select "Edit Claim Issuance Policies." I have one rule there that works; it simply passes back all Active Directory claims. I can see all of these claims on my web page (upn, name, windowsaccountname, all of my group sids, and etc):
c:[]
=> issue(claim = c);
I'm trying to add a 2nd custom rule to read a legacy membership database. In my ADFS I click "Add Rule", "Send Claims Using a Custom Rule", and add this as the rule:
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"]
=> add(store = "SQLServer", types =
("http://schemas.microsoft.com/ws/2008/06/identity/claims/role"), query =
"select r.RoleName AS Role from dbo.aspnet_Roles r INNER JOIN
dbo.aspnet_UsersInRoles uir ON r.RoleId = uir.RoleId INNER JOIN
dbo.aspnet_Users u ON uir.UserId = u.UserId WHERE u.UserName = '[hard-coded
value here]' OR u.UserName={0}", param = c.Value);
It saves fine, but when I re-run the page nothing changes; I still get the original collection of Active Directory claims, but not the data from SQL Server.
I am confident the SQL Server statement is executing, because if I remove permissions for the identity that ADFS runs under from the SQL Server I get an error, and if I deliberately garble the SQL syntax I get an error. If I reverse these deliberate mistakes then the page functions properly again. But I never see the Roles that I want to see in the Claims collection.
From my understanding of custom rules, "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" is passed as a parameter into the query, that is why I have the OR statement above; my ultimate goal is to pass the user's UPN as a parameter into the SQL query.
Am I missing something or doing something wrong? Bonus question--assuming I get this working, can you tell me how to pass the user's UPN as a parameter into the SQL query?
Try an "issue" rule rather than an "add".