Please upgrade here. These earlier versions are no longer being updated and have security issues.
HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

Passing Additional User Information

judgejjudgej
edited September 2010 in Vanilla 2.0 - 2.8
I am looking at ProxyConnect to provide single-signon with a Xaraya CMS. I had my own custom athentication module for Vanilla 1 that worked in a similar way, but operated over a "push" mechanism (the CMS pushed the user details to Vanilla, and logged in using Vanilla's cookie). That all worked fine, but now I am upgrading to Vanilla 2 and so it makes sense to adopt the new ways of doing things.

One thing I would like to carry forward is the ability to send additional information with the user details. These include:

* A personal name. This is distinct from the username, and may change from time-to-time. The personal name will be written to some store - a custom module or "AboutMe" or something.
* The user's roles on the CMS, which will be used to set up the user with roles in Vanilla. The roles may also change from time-to-time.

So as well as setting these details up for a new user, I also need ensure the user is updated each time they are logged in; a personal name may change, and the user can be switched between roles.

My main question is this: is there a simple way to hook this additional functionality into the ProxyConnect module? i.e. is it "expansion ready"? Or do I need to fork the plugin in my own domain and hack away at it?

-- Jason

PS If any of this stuff will be useful to others, or any starts have already been made to similar functionality, then sharing my code would not be a problem.

Just a note on the roles thing: there would be a list of roles in Vanilla that the CMS could turn on and off for the user. There would also be a list of roles that would not be touched by the interface. For example, "Member" may be given to all Vanilla users and that could not be removed by logging in to the CMS (only the Vanilla admin would remove that through the admin screens). Another role "Project Leader" would not be locked in the same way and the Vanilla user would be added to or removed from that role according to how that user is set up in the CMS at the moment they log in.

The reason for me using a "push" interface for my first implementation was so that once a user logged into the CMS, they would be logged into the forum without even visiting it. The CMS could then display RSS feeds of comments from the forum using the current user's role. I think this will work fine too, as the user should be created and/or logged into Vanilla the moment the first RSS feed is fetched (I send the user's cookies from the CMS in the RSS request). Thinking about it, when I log into the CMS, I think I am going to have to do an immediate request of the home page of the forum so that Vanilla cookies can be passed back to the CMS and then to the user's browser. Oh, it does get complicated!

Comments

  • TimTim Vanilla Staff
    I don't have time today to look into this, but I'll get back to you next week with more information. I have some updates for ProxyConnect that address things like this.

    Vanilla Forums COO [GitHub, Twitter, About.me]

  • Cool. If you have anything you could zip up and send me, that would be much appreciated, but I realise that may be hard to do. This is a pretty tight deadline I'm working to, and would like to get the authentication going before next week, so we may be duplicating some work - I'll have a play and make any code available anyway in case there is anything that could be combined.
  • TimTim Vanilla Staff
    As you know, ProxyConnect works by parsing a list of key-value pairs from the remote application. The parsing is done before the validation, so every key-value is parsed into the resultant array, and we simply check for the item we specifically need. That is, extra key-values don't break anything.

    As such, I could probably meet you halfway and simply fire an event when I log the user in, attaching the complete list of key-values to said event. This would let you write a plugin which handled that event and did whatever jiggery pokery you needed.

    Vanilla Forums COO [GitHub, Twitter, About.me]

  • judgejjudgej
    edited September 2010
    Yes, that sounds ideal.

    One of the things I would like to do is to put the user into various roles (or take the user out of roles). I am not sure if that needs to be done before they log in or whether it can be done safely immediately after they log in.

    Also, would this be a core event or a ProxyConnect plugin event? I have no idea whether a plugin can call an event that another plugin can hook into - just curious.
  • Okay, I must say I am stumped trying to find where such an event call would have to go. I've spent a full day sifting through the ProxyConnect code, and I just cannot see where calls would be put in to allow a plugin to perform additional tasks when a user logs in or is created (and logged in) with access to the full data fetched from the authentication URL.

    So for ProxyConnect 1.8, could you give me any pointers?
  • Gdn_ProxyAuthenticator::_GetForeignCredentials() fetches the key-value pairs, but only returns what the ones needed to log a user in. The rest - custom name/value pairs - are discarded at this point. I guess the full set would need to be saved here so that it can be accessed further in after the user has been authenticated?
  • judgejjudgej
    edited September 2010
    Perhaps I should raise this in the bug/feature tracker, but here is where I have solved this for me. Two changes in the class.proxyauthenticator.php script allow me to hook into the user creation and authentication. There may be better ways of doing it, but here goes:

    In Gdn_ProxyAuthenticator::_GetForeignCredentials() after the first switch statement the parsed data from the remote authentication site is saved (near line 302):

    $this->ProxyRequestResponseResult = $Result;

    In Gdn_ProxyAuthenticator::Authenticate() immediately after the successful login check, an event is fired (near line 65):

    ... if ($AuthResponse == Gdn_Authenticator::AUTH_SUCCESS) { // Everything's cool, we don't have to do anything. $this->EventArguments['ProxyRequestResponseResult'] = $this->ProxyRequestResponseResult; $this->FireEvent('AfterUserAuthenticated'); } elseif ($AuthResponse == Gdn_Authenticator::AUTH_PARTIAL) { ...

    In my plugin I hook into this event:

    public function Gdn_ProxyAuthenticator_AfterUserAuthenticated_Handler(&$Sender) { // Do whatever }

    That event is passed the remote site credentials as an even parameter (an array). The user at this point will also be logged in, and will be the current user, so all the details will be available.

    I have not taken this any further yet, and hope there are no permission checks in the models that put the user into and out of roles, but I am expecting that to work (with permission checks mainly in the controllers).

    @Tim, does that look anything like your "meeting halfway"?

    -- Jason
  • The new event when a user is registered (vanilla 2.0.11) looks useful. This event, however, fires whether a user gets registered or is just logging in. Some things need to be checked or updated for a user's account every single time they log in, and that is where I am coming from with this new event.
Sign In or Register to comment.