Did ADFS change recently with respect to how the upn gets mapped to User.Identity.Name in ASP.NET?
What I know:
ASP.NET web app that authenticates externally via ADFS
test environment worked OK with no outgoing Name claim defined in ADFS a few months ago
test environment was fired up recently and ADFS login failed. ADFS server did not have any configuration changes
issue is that User.Identity.Name is null even though Request.IsAuthenticated is true
root cause is that there is no Name claim and there appears to be no explicit mapping in web.config to use upn for this
From Microsoft:
https://msdn.microsoft.com/en-us/library/mt740689(v=vs.85).aspx
When you pass a valid security token to the AD FS Web Agent, it
creates an session cookie and processes the token's claims into the
session's User object. This object is derived from IPrincipal, and
exposes one method, IsInRole(), with which you can query the User and
determine whether that user asserts the specified role claim (using a
string to specify the role).
IPrincipal also exposes one property, Identity, which returns the
user's identity, represented as an IIdentity object. This object can
be used by the default.aspx page to determine whether the User is
authenticated (by calling IsAuthenticated(). It also allows you to
determine whether the user is asserting a name claim by accessing the
Name property, which returns a string representing the User's name.
The snippet here illustrates the use of both of these techniques.
I have questions about this that I can't find in Microsoft docs:
What specifically is meant (as in: which xml attribute or specific ADFS claim string) by "the user is asserting a name claim" ? (it is ambiguous: is it "name" claim? because it reads more like "name claim" where "name" could be loosely defined as user name, and often upn is used for this, and was working in the past)
What is the exact logic used by .NET for setting User.Identity.Name when using configuration-based identity with ADFS (defined in web.config)?
AFAIK, this "Name" logic did not change in the latest versions of the framework.
As explained here for instance, by default the claim type used to populate the Identity.Name property has always been:
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
So if your SAML token contains such claim, it will be used as the "name" of the user (it is up to you to decide which AD attribute you want to put in this claim: userPrincipalName, displayName, mail, ...).
This default attribute can be overriden in code, or in your web.config. This page mentions a "<nameClaimType />" element, honestly I don't remember if it has changed in the meantime.
a
Note: your link is really old. The "ADFS Web Agent" was something from the first version of ADFS, but it was rapidely superseded by WIF.
Related
I have set up a Blazor application in .NET Core 3.1 and I'm implementing authentication/authorization, but it is clear I just don't have a great understanding of how default authentication works.
I set up an "AuthorizeView" tag as follows, fully expecting it to fail:
<AuthorizeView Context="auth" Roles="Admin">
<Authorized>
Content
</Authorized>
<NotAuthorized>
You do not have access to this page.
</NotAuthorized>
</AuthorizeView>
but instead it works fine. I am able to see the "Content" section, despite the fact I have not set up ANY authorization. I'm assuming this defaults back to something like Windows Authentication (which is what I'm using in my Blazor app) but I'm not specifying to use AD Authorization anywhere.
Can anyone point me to where I would go, or help me understand, how this is working by default and where it is pulling this "Admin" role from?
You can control and limit access to your resources using authorization. You can control access depending on the roles of the user, claims and authorization policy.
Using the AuthorizeView above and setting the Roles attribute to "Admin", you tell Blazor that if the user belongs to the Admin role, he is authorized to access the content within Authorized element.
I guess that you've set your Blazor app to authenticate users accessing your app by selecting Windows Authentication, when creating your app, right ?
When you try to access your app, you are asked to provide your credentials which are passed from IIS (express) to your app...
Roughly speaking a Claims Principle( or Windows Principle) object is created by Blazor and passed to an object named ServerAuthenticationStateProvider as an AuthenticationState object. This object, meaning the AuthenticationState object is also provided to the AuthorizeView whose base class AuthorizeViewCore contains the logic to call the IAuthorizationService, passing it the claims principle. Now the authorization service inspect the Claims Principle object, what claims it has, what roles it has, and of course it looks for a role claim with the value "Admin", if found, true is returned, and at the end of the pipe line it is decided that you are allowed to access the restricted content.
where it is pulling this "Admin" role from
From your Windows AD if you've one or from windows user accounts, etc. Remember, you told the wizard that you want to use Windows authentication (this is my supposition, otherwise everything I've said may be wrong).
You had better go to the docs and acquaint yourself with services like AuthenticationStateProvider, ServiceAuthenticationStateProvider ,etc.
Using the ASP.Net Identity 2 provider model in conjunction with plain Authorize attributes.
Anonymous access is true, Windows authentication is disabled.
HttpRequestBase.IsAuthenticated will return true, how-ever, the HttpRequestBase.LogonUserIdentity will not return the actual ClaimsIdentity but instead an impersonated user (me as I'm running IIS Express locally).
The actual authenticated and returned ClaimsIdentity from the provider is accessible via e.g.
HttpContext.Current.User... and/or System.Threading.Thread.CurrentPrincipal...
Q: Why not via HttpRequestBase.LogonUserIdentity?
First time I see this property used. The documentation says this property should return WindowsIdentity of the current user. MVC app does not know about WindowsIdentity of the logged in user, because there is no such thing.
Also in source code for this property eventually asks for server variables.
I usually access currently logged-in user via ClaimsPrincipal.Current and never seen user retrieved from HttpRequestBase.LogonUserIdentity.
Also HttpRequestBase.IsAuthenticated is identical to calling HttpContext.Current.User.IsAuthenticated with few null-checks.
I like to know, when will the GetPropertyValue() Method called?
I have written a proxy pattern for sql profile provider and i tried using the profile properties in my application.
I tried both authenticated and anonymous user mode, when ever the profile property values are accessed, profileProvider GetPropertyValue() method is called and it is hitting the DB to fetch the values.
I like to know, when will the profile values presist in the context?
For each & every request, I m seeing the profileProvider is called to fetch the values. If so, then what is use of having Profile in HttpContext.Current?
I am developing an ASP.NET website. I am planning to use Forms authentication in order to guarantee authentication/authorization, but I am facing two problems regarding the authorization:
I know how to set in the web config that the authenticated users are allowed to visit a webpage (say myPage.aspx). But I do not know how to define that UserA is able to access myPage to retrieve his information, not UserB's information.
I was thinking about generating a token when the user authenticates, so I am able to check to whom this token belongs to and verify if this information is available to him.
What do you think about this approach? Does the Form Authentication generates a token like that? (I couldn't find any mention about it in my research). If not, could I adapt the Form authentication mechanisms in order to generate or would I need to write everything on my own?
I would like to access webservices, and these should only return information if the user is logged. For this reason, I would like to use the same token explained above. What do you think about it? Is it a good approach?
I am asking this because I have no experience on designing authentication/authorization mechanisms, any help/hint would be appreciated.
Regarding question one, after forms authentication occurs in an ASP.Net web forms app, the user's identity is exposed as a FormsIdentity object in the Page.User.Identity property. This object has a Name property which contains the username that a user use to log into your site. You can use this value to restrict what a user can access. For example, let's say you have a table in your database with user information containing the following fields:
userId int
userName varchar(25)
...more fields containing user information...
You can restrict a user to only access information from the row in this table in which the userName equals the Page.User.Identity.Name property, either directly if you are using direct ADO.Net or via your query to your ORM-mapped (i.e. nHibernate or EF) domain object.
Regarding question two, the FormsIdentity object exposed by Page.User.Identity has a boolean "IsAuthenticated" property. You can use this to restrict access to your web service as follows:
if(Page.User.Identity.IsAuthenticated)
{
//Call your web service in a secure manner
}
I'm having trouble figuring out this issue I'm having with cookies and asp.net applications.
A webservice is used to get user info with the following method call:
GetUser(token)
The token parameter comes from a cookie named "token". A user visits the website, and a token cookie is created. The website needs to interract with a third-party application in the same domain, so they share the token cookie, and the third-party app will make the GetUser call with the token.
For some reason the third-party app is expecting the prefix "token=" in the cookie's value.
If the token cookie's value is "ABC123", the call doesn't work, but if I manually edit the content of the cookie so the value is "token=ABC123" -- then it works. However, I know the webservice method is still being called as: GetUser("ABC123") even though "token=" seems to be in the value.
Why does the third-party app seem to need the cookie's name in the value to actually work?
Because the web service is parsing the value you pass to extract the value, probably in order to support more data values in addition to the username, for features that you are not using (like "token=ABC123,active=True", for only retrieving an active user). Or was originally built that way.