Blazor default role provider - asp.net

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.

Related

Customizing CQ / AEM Authentication

What exactly do you have to do to authenticate users against an external source while accessing pages on a CQ publish instance?
From what I have read, a custom AuthenticationHandler can be used for this. The AuthenticationHandler can be configured to be called against the paths requiring authentication and inside the extractCredentials() method, the users will be authenticated against the external source and an AuthenticationInfo object will be returned.
If the supplied credentials are invalid, null would be returned from this method to indicate the same. The SlingAuthenticator will then call requestCredentials() where the user can be redirected to the login page.
Is this understanding correct? If so, what does SlingAuthenticator do with the AuthenticationInfo object returned from extractCredentials()?
In some places, having a custom LoginModule (by overriding AbstractLoginModule) is also suggested for the same purpose. Are these 2 different approaches (custom AuthenticationHandler and Loginmodule) for having custom authentication or are they used together somehow? If so, how do they interact?
And also, the concept of CUG (Closed User Group) can be used to redirect users to the login page if they don't have access to a page. Can CUG still be used with a custom auth mechanism or it only works if the users are present in CQ repository?
Any light shed on this would be much appreciated :)
Your understanding is correct. The AuthenticationInfo object ultimately contains a JCR user id -- but rather than having to use the JCR password for the user, a 3rd party service basically says "this user has authenticated successfully and can access the repository as X".
Example: you're using OpenID or SAML to verify a user is X. user X is then mapped to a user Y in the repository.
I haven't used LoginModule but from what I'm reading, that's just extending login processing for the JackRabbit repo. So, rather than using AuthenticationHandler to redirect a user to some other place and processing the response, you're plugging further down into the chain where there's already AuthenticationInfo (or something like that) being given to JackRabbit to verify and return a session for a user.
So, let's say you did successfully authenticate with OpenID but the user you're mapped to doesn't exist. You could write a login module to create the user in this case (and assign user to a default group). For instance, if user came in with a gmail id, the JCR user could be gmail_$id. And the login module, seeing the name starts with gmail, will know it's ok to create that user automatically.
As far as CUG, yes, all the above can be used in conjunction with it. Basically, if a request doesn't have access to a resource and the request hasn't been authenticated, the authentication handling system kicks in. If a user has authenticated but still doesn't have access to the resource (e.g. not part of a group that can read it), a 403 will be generated.

ASP.Net Identity 2, HttpRequestBase.LogonUserIdentity

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.

What's the practical workflow using claims for authentication and authorization in a web application?

I just don't still get Claim Based Authentication/Authorization workflow.
The application allows authentication via Facebook.com
After the user is authenticated, an admin can give her/him a claim of having the role of Manager, which creates another claim (where?)
Of course, this claim won't be on the facebook.com server, question 1: where should that claim be stored?
When the user log in again later, I get the claim of facebook.com and I should get the claim from the application. and merge them?
How is the workflow? Trying to understand claims in practical usage.
Basically, Facebook tells me that I'm john#doe.com, and 'field in the blanks' adds a claim that I'm also a manager of domain.com
then I pass those claims to domain.com?
How should I configure in asp.net the application at domain.com to trust Facebook and 'filled in the blank piece' and request claims from both?
I guess I'm using external providers for Authentication and my own provider for Authorization, how this is created on ASP.NET (web API / MVC)?
UPDATE (for clarification)
Let's get backwards. I create a web application where users can register.
'Somehow' there's an trusted ClaimsBased authority somewhere (this should be another application??) where I request the claims for a particular user to see if have particular rights on my application.
So I imagine something like :
/authserver/claims
and my validation checks if X claim is met to do certain operations.
later I add to Facebook. now I have
/facebook/claims
which tells me the user is X
and
/authserver/claims to see if can do operation X on resource Y.
how this is managed on ASP.NET? and where my own claims should be created/exposed/developed.
I think I'm missing something fundamental here.
I think the important thing to understand is the difference between authentication and authorization.
Authentication - the act of confirming the truth of an attribute of a datum or entity.
Authorization - the function of specifying access rights to resources, which is related to information security and computer security in general and to access control in particular.
So, typically for secured system, the workflow starts with Authentication. When a user first connects/uses a system, then are not authenticated (lets say this user is of a type/group Anonymous). The act of the system determining the user is not authenticated is an Authentication in and of it self. Based on being Anonymous, then the act of the system determining what that type of user anonymous has access too is now authorizing what the user can do. For very secure system, the only access anonymous has is to the login screen/page. Once logged in the user is assigned a unique identity and assigned some type of group policy/role (if not already created).
with a web-based application and having a website (#1) authenticate for another website(#2) it becomes a bit more complicated. When I log into StackOverflow(#1), I use my Gmail(#2) account. I get redirected to Google with some special way for Google to know that the page I came from/to go back to. This could be a special key/url combination or for less restrictive access, usually has to do with return url (after I say, yes, where I go back too). Google will create a special authentication token that is specific to the url I am returning to. It is tied to the URL because that means that my token on StackOverflow won't allow me or anyone else to log into say NewEgg for example (in other words someone at StackOverflow with access to the database can't use my token to authenticate as me on some other website, but technically they could log in as me on StackOverflow, but they own the website, so that doesn't really matter). Now I am authenticated on StackOverflow (but technically StackOverflow doesn't even need to know any information about me, just my Token).
On StackOverflow as a new user, a new account is created. This account probably has a one to many relationship to my unique account on Stack Overflow and multiple of logins (and type of logins, OAuth, OpenID or SO Login). Once the account is created, I have whatever access they have setup by default. If I need more or some trigger (lets say based on my Reputation points :) I now have access to Administrative functionality (given some role). That role is tied to my account and indirectly tied to my authentication. This means that I can create additional logins (say a Local SO Login) but keep my Account.
As for each Authentication resource (Google, Facebook, etc) there will be difference schemes for Authentication, but there will always be at least a token (or more than one token) for a website to say who I am (in a generic way).
So website #1 (Stack Overflow) has requested website #2 (Google) to Authenticate me. But only website #1 knows what am I Authorized for.
For role specific functionality, there are a good number of answer on SO dealing with ASP.Net Identity and the Role Manager:
Creating Roles in Asp.net Identity MVC 5
mvc 5 check user role
A much more Indepth look into Identity with MVC - Extending Identity Accounts and Implementing Role-Based Authentication in ASP.NET MVC 5
If you're using ASPNET.Identity (http://www.asp.net/identity/overview/getting-started/introduction-to-aspnet-identity), you can add a Role claim type to the user. It'll be associated with the userlogin, so when the user authenticates with Facebook, these user claims will be added and available in MVC.
See the following code fragment:
var acRes = await UserManager.AddClaimAsync(userId, new Claim(ClaimTypes.Role, "MyRole"));

ASP.NET Membership - Two providers on site

Our site has got two ASP.NET membership providers. The built in one, and a custom one (SqlMembershipProvider.
I am able to log into both no problems, but I don't necessary require the ability to have both logged in at the same time.
The issue I have is as follows:
User "person_a#site.com" logs into the built in provider. They then navigate to the section of the site where we require the custom provider.
On this page, I can check if they are authenticated, and get their username. I can then get a MembershipUser object form the custom providers GetUser method. (HttpContext.Current.User.Identity.Name)
It is possible (and very likely) that the username "person_a#site.com" could also exist in the users for the custom provider.
But, I don't want them to be logged in here, as they haven't authenticated against the custom provider.
So, is it possible to check which proivider HttpContext.Current.User was generated from.
Hope this all makes sense!!
Yes, if you notice on the RolePrincipal there is a property called ProviderName.
Typically when people roll their own providers they omit usage of this field.
In your case, simply modify your custom provider to identify itself, if it does not already, and check that property of the user.

How do you get the logged in Windows domain account from an ASP.NET application?

We have an ASP.NET application that manages it's own User, Roles and Permission database and we have recently added a field to the User table to hold the Windows domain account.
I would like to make it so that the user doesn't have to physically log in to our application, but rather would be automatically logged in based on the currently logged in Windows domain account DOMAIN\username. We want to authenticate the Windows domain account against our own User table.
This is a piece of cake to do in Windows Forms, is it possible to do this in Web Forms?
I don't want the user to be prompted with a Windows challenge screen, I want our system to handle the log in.
Clarification: We are using our own custom Principal object.
Clarification: Not sure if it makes a difference or not, but we are using IIS7.
Integration of this sort is at the server level, it's IIS that decides that the user is not logged in; and it's IIS that sends back the authentication prompt to the user, to which the browser reacts.
As you want to use the domain login there is only one way to do this; integrated windows authentication. This will only work if the IIS server is also part of the domain and the users are accessing the machine directly, not through a proxy, and from machines which are also part of the domain (with the users suitably logged in).
However your custom principal object may create fun and games; authentication of this type will be a WindowsPrincipal and a WindowsIdentity; which you can access via the User object (see How To: Use Windows Authentication in ASP.NET 2.0)
I assume you want a custom principal because of your custom roles? I doubt you can get the two to play nicely; you could create a custom role provider which looks at your data store or look at you could look at ADAM, an extension to AD which provides roles on a per program basis and comes with nice management tools.
I did pretty much exactly what you want to do a few years ago. Im trying to find some code for it, though it was at a previous job so that code is at home.
I do remember though i used this article as my starting point. You set up the LDAP provider so you can actually run a check of the user vs the LDAP. One thing to make sure of if you try the LDAP approach. In the setting file where you set up the LDAP make sure LDAP is all caps, if it is not it will not resolve.
using System.Security.Principal;
...
WindowsPrincipal wp = (WindowsPrincipal)HttpContext.Current.User;
to get the current domain user. Of course you have to make sure that the IIS is set up to handle Windows Authentication.
This might be helpful:
WindowsIdentity myIdentity = WindowsIdentity.GetCurrent();
WindowsPrincipal myPrincipal = new WindowsPrincipal(myIdentity);
string name = myPrincipal.Identity.Name;
string authType = myPrincipal.Identity.AuthenticationType;
string isAuth = myPrincipal.Identity.IsAuthenticated.ToString();
string identName = myIdentity.Name;
string identType = myIdentity.AuthenticationType;
string identIsAuth = myIdentity.IsAuthenticated.ToString();
string iSAnon = myIdentity.IsAnonymous.ToString();
string isG = myIdentity.IsGuest.ToString();
string isSys = myIdentity.IsSystem.ToString();
string token = myIdentity.Token.ToString();
Disclaimer: I got this from a technet article, but I can't find the link.
You can use System.Threading.Thread.CurrentPrincipal.
Request.ServerVariables["REMOTE_USER"]
This is unverified for your setup, but I recall using this awhile back.
Try Request.ServerVariables("LOGON_USER").
If the directory security options are set so that this directory does not allow anonymous users, when the surfer hits this page they will be prompted with the standard modal dialog asking for username and password. Request.ServerVariables("LOGON_USER") will return that user.
However, this will probably not work for you because you are using your own custom security objects. If you can figure out how to get around that logon box, or pass in NT credentials to the site before it askes for them, then you would be all set.
Have you thought about impersonation? You could store the user's NT logon credentials in your custom security object, and then just impseronate the user via code when appropriate.
http://msdn.microsoft.com/en-us/library/aa292118(VS.71).aspx

Resources