I just implemented my own authentication provider performing facebook authentication. It works for exactly one request and then it goes:
There is no user provider for user "Nourdine\BasicBundle\Security\User\FacebookUser"
The thing is:
1 - a FacebookProvider is there and kicking.
2 - I registered it as a service:
<service id="facebook_user_provider" class="Nourdine\BasicBundle\Security\User\FacebookUserProvider" />
3 - and made it available in security.xml
First question: Why does he now "see" it?
Second question: is it mandatory that one creates a related user provider every time he implements an authentication provider?
Thanks
I think you have something wrong with your user provider refreshUser method. This method is used when you use session persistence (token is serialized and stored in session) so user can be fetched from database (or other place) next requests.
It see provider cause you register it as service and use service id in security.yml
UserProvider is responsible for fetch user from db or other layer (webservice or something) and AuthenticationProvider authenticate user (do authentication logic) and it can use provider but it is not necessary most the time we use Symfony\Component\Security\Core\User\UserProviderInterface not concrete implementation. So not mandatory
Related
My Symfony (4.4) app uses the OneloginSamlBundle bundle to authenticate users against a SAML identity provider. This works fine. I receive the SAML response and the User Provider instantiates my User class correctly. However, I want that once I get the authentication SAML response, the corresponding user is instead fetched from my database. How could I do this ?
I guess I need to create a custom user provider which would use the OneloginSamlBundle userprovider AND then fetch the user, but I don't know how I am supposed to do it with Symfony.
I am trying to use the following:
1) form_login_ldap just for user authentification
2) A custom UserProvider for retrieving user roles from a MySQL database
Everything seems to work fine: I am able to login, the roles are used etc.
As soon as I change the roles in the database, isEqualTo() kicks in - the user is redirected to the login page. There the browser hangs in an endless loop. After using tcpdump I realized that form_login_ldap is trying to authenticate the user without a password.
I think I am generally missing the point how the password will be handled in this scenario. My UserProvider can't retrieve an (encrypted) password as he is querying MySQL and the user is authenticated using LDAP.
If the "refreshUser function of my UserProvider returns a new user object with the new roles, the password seems to be lost.
If within the UserProvider i just modify the array of roles for the user, the web application does not recognize that and old roles apply (I guess the session must be updated?).
How are form_login_ldap and my UserProvider supposed to interact? How do I make sure that upon "refreshUser" the password is still available?
What am I missing for my general picture?
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.
I'm writing my first Symfony2 app after a few years with Symfony and am having trouble converting our user management code. It seems that to fit in with Symfony2's authentication model I have to provide user details including their (encrypted) passwords. We authenticate via a webservice that takes the username and password and responds with a confirmation and user level (user, admin etc), but it never sends the real password back to us.
What I want to do is accept the login details from a form, confirm they are valid and then set the user's roles according to the webservice's response. Where do I start?
You need to use a custom authentication provider to authenticate against your webservice. It is explained quite clearly in this blog post
You can create an user provider and its loadUserByName you can call the webservice. If success return the new UserInterface object with the password of the form empty salt string and the roles returned by the service. Also set encoder of the UserInterface to plaintext in security.yml. And then set the new created user provider in form_login auth provider in the firewall.
I am reading on form authentication in ASP.NET and cannot understand some moment:
James enters a username-password, they are saved in the db. A cookie from username is created, encrypted and attached to a response. As I understand then, when we get a request we need to recognise that cookie received are from James and so we can show his customised page.
What I would like to understand is how system will retrieve username form cookie and then load his info from db?
Forms Auth is storage agnostic. It doesn't have to use a database, indeed you can use it with usernames and passwords in web.config.
So what happens is
A user logs in.
The user is authenticated against the membership provider (which can use SQL, Active DIrectory, web.config, Oracle, MySQL, whatever)
A forms authentication token is created for the user, and is placed on the user machine via a cookie.
Each subsequent request reads the forms authentication token, and queries the provider to get the user details.
The user details are used to populate the user identity in the HttpContext and current thread for the request which is then available to your code to use.
In your code you can check the User property in the Page class (WebForms) or the User property in the controller class (MVC).
While you can get at it via the current thread, or the current context it's not advised, especially once you start using background tasks, where the identity may not propagate to the thread, or the context may change.
You'll note that nothing is stored in a database when the user logs in. It's all in the forms authentication token, and the work of retrieving the user from it's store on each request is done for you.
Afaik Forms Authentication does not store or load anything in any database. You can use a database to store the username and password, or you can put them in the web.config. How you store user credentials and validate them is up to you, and can happen separately from Forms Authentication.
Once you have validated a user (against database or some other logical storage), you use FormsAuthentication to write the authentication cookie. You do not need to worry about decrypting the cookie.
You can get the username from System.Threading.Thread.CurrentPrincipal.Identity.Name. To retrieve user's info from the database, you would query the database using the value if the principal identity name.
Response to comments
Right, you can use forms authentication with the membership provider, active directory, or your own custom user database. FormsAuth doesn't care about the password at all, unless it is stored in web.config (as noted in blowdart's more complete answer). It just writes the cookie, which is decrypted and used to create the thread identity automatically.
Additional Info
Even though this was marked as the answer, blowdart's response is much more complete. You really should not get the identity from the thread if you need it in an ASPX page or MVC controller, use the properties he referenced.
You get the username in your web form by calling User.Identity.Name, e.g. like this:
protected void Page_Load(object sender, EventArgs e)
{
string userName = User.Identity.Name;
}
ASP.NET interprets the cookie for you, you don't have to read it yourself. Or is your question how to store the user and password in the DB?