Roadmap: System Authentication Library and Third Party Authentication

We have posted a blog entry on how we'd like to handle single sign-on, the normalization of authentication types, third party authentication, and some more items. I'd like to use this thread to get feedback on it. This is fully spec'd and I'd be happy to answer questions about how to handle it. We'd love to include it, but I'm not sure when we'll be able to tackle it without community help:

EDIT: Updated the link (old one was dead.)

View Replies:
andrew replied on at Permalink Reply
Anyone reading this – does this spec fall short anywhere? We're keeping it fairly vague and open rather than forcing all solutions to work in a really rigid way.

Also, should this spec cover avatar support in some way? It'd be nice to be able to import facebook avatars, for example, but I think this may be outside this spec.
Mnkras replied on at Permalink Reply
In the table setup, whats the PK?

I think that the core login method should be disable-able, but if the active one does not exist then fallback to it.

How do you want to store the userinfo? each auth type has its own table? user attributes?

For the tabs, jQueryUI?

Could we possibly get a branch for this? so that we don't have a few people working from scratch on this at the same time.

Thanks for the Spec :)
andrew replied on at Permalink Reply
Excellent questions.

The PK column is the primary key (e.g. the handle for the authentication type is unique and should be all that is necessary to make this system work.) It's also not user-enterable so it should be fine. If it's necessary to add an authTypeID column that's a numeric primary key field, that'd be fine too.

I wrestled with whether to make the core login disable-able or not. The problem is that if you disable it and screw things up you'll be unable to log back into your site. I'd entertain ways to solve this while making the core login form disable-able. You can also obviously disable it with a custom single page, if you know what you're doing. Perhaps we include a ENABLE_CORE_LOGIN_FORM define() in config/base.php, and it's set, by default, to true, but you can also set it to false?

I wasn't sure about the tabs. jQuery UI makes sense for how to get them up and running quickly, probably (Though we might have to customize it heavily for presentation.)

For User Info, let's store this data in User Attributes. It works well. Generally, all of these methods will ultimately create concrete5 user objects (like how the login via facebook add-ons and the openID code works.)

Once we iron out some of this stuff I will definitely create a branch. Good suggestion.
Mnkras replied on at Permalink Reply
I think giving them IDs would be good,

How about if you disable the core login, then only people in the Administrators group can login via that form and its "hidden", like you have to add to view that form but normal users won't see it?

What do you mean they will create userinfo objects? like get a user by their facebook ID and using that ID get the user?

and a new question, most (all?) services require a return url, how do you want to handle that? tool?
andrew replied on at Permalink Reply
Ok, let's add authTypeID to that list. Makes sense.

I like the idea of adding a define() named ENABLE_CORE_LOGIN_FORM and being able to set it to false, and having that be able to hide the core login form. Then, if you get tripped up, you can temporarily enable it to get back into your site. Plus it makes you go through a couple extra steps to disable it, but you don't have to fork code a lot to make it happen.

Check out the bundled OpenID code currently in concrete5 for examples on how we create user objects that come from OpenID providers. This is usually how we handle single sign on: the first time a user signs in from the third party provider, we create the user account in concrete5 seamlessly, and then log them in as this. This is how the facebook signon providers work that have been just added to the marketplace.

Usually these user accounts will have a few extra user attributes (like the facebook add-on gives you users a facebook UID attribute.)

Why don't you fork the current concrete5 authentication repository into a new repo and give people commit access to it as they want it. I imagine jshannon might want it. I'll want it. etc...

And yes, we'll typically use a tools URL for callbacks.
Mnkras replied on at Permalink Reply
"Why don't you fork the current concrete5 authentication repository into a new repo... "

there isn't a current one, just checked github to make sure, do you want me to make one?
mulderjoe replied on at Permalink Reply
I would love to see some sort of CAS Apache SSO integration. I imagine embedding PHPCAS would be a possible solution.

Just my 2 cents.
jshannon replied on at Permalink Reply
I think that if this spec doesn't include avatars, then it'll be a missed opportunity.

Not knowing much about these SSO auth mechanisms, I would think that adding avatar support simply means having:

a) an "avatar URL" property/attribute on the userinfo account. I expect that most web services prefer that you hotlink to the avatar on their site, rather than download and store locally.

b) an easy API to import the avatar image to c5, for those that don't support a.

The individual auth plugins would then be responsible for updating the avatar, probably on every login (though a 3rd party URL shouldn't change).

This would require a change to the avatar html helper.

I'm not sure exactly how this would work with gravatar, which was a popular request until I created an add-on. It would be easy enough to integrate into the core auth plugin, but it might make more sense to have it at a "higher" level (ie, as a system-wide default). On the other hand, maybe the "model" of having facebook/google/whatever auth means you always rely on them for avatars, and don't really do a default from another service.
detha replied on at Permalink Reply
One more question: what happens if a user was created using a third-party login, and (s)he subsequently tries to log in, but the third-party authentication now fails (e.g. account was closed down)?

I needed something like this for a project, with some extra bells and whistles. 'Normal' users are just C5 users, but there are 3 levels of admin that need to be authenticated against ADS, and get given privileges based on AD group membership. With the additional requirements that if the AD server goes AWOL admin users must still be allowed in using the last password verified against AD, and if the AD account is revoked the corresponding C5 account needs to be closed too.

Fairly simple to do hacking around in controllers/login.php a bit, but these requirements are probably not the typical use case for 3rd-party authentication.

Also, what happens in case of password changes? In the SSO scenario we have AD is the master, and if AD says the password is OK, we update the C5 user. Again, not sure if that should always happen though.
ijessup replied on at Permalink Reply
AFAIK, this would all depend on how the 3PA system was written. However, a thorough add-on should provide the ability to choose the intended result.

I wrote an AD 3PA add-on for c5 that would update the password of the c5 user so that if LDAP was determined unusable, it would then check the c5 userbase so that the c5 account wasn't unusable.

However, it could be extended to read the account attributes received through LDAP to determine account legitimacy, as well as to ignore all login attempts while the AD server is unreachable (at least for all accounts that require authentication via LDAP).
jordanlev replied on at Permalink Reply
I'm not an expert in this stuff and haven't yet needed to build a C5 site with third-party login integration, but my high-level feedback is:

1) The current markup for the login single_page is very difficult to comprehend and hence not conducive to styling. I would suggest that before any new features are added to it, it should be cleaned up a bit. The reason I thought of this is because my initial look at the tabs in your mockup made me think "that's probably good enough for a generic default that works with anything, but if I were building a client site I would need to style it so everything is on one page with big logos for the various services", and then I shuddered at the thought of having to customize the login page as it currently stands :)

Here's a forum thread where some people have already cleaned it up a bit -- perhaps this can be rolled into the core first before additional modifications are made:
(specfifically, the attachment from MrNiceGaius -- not the one Carlos is working on because that's less of a customizable template and more of the beginnings of a complex addon he's building)

2) I would think it's important that site owners know who's logging in with the third-party credentials, and that the best way to do this is to have a C5 user account for these logins. The specification should provide as much detail as possible about how this is going to work in both the underlying data model as well as how one needs to integrate the account creation process into their own code (and also how to check if the account has already been created and be able to match them up).

jshannon replied on at Permalink Reply
For #2:

It's not clear to me if there's a 1-1 relationship between c5 accounts and the 3rd party auth accounts from birth of the c5 account.

So what I mean is that, say you have a pool of c5 accounts (A, B, C).

1. Can I retroactively associate my account B with my Facebook account?
2. If I create an account D through the facebook mechanism, can I then associate with twitter and login that way? Or can I go back to core login?

I would think the desired answer is "no". And thus, shouldn't there be some sort of "auth id" on the user object, and some check that the correct auth mechanism is logging you in?
Mnkras replied on at Permalink Reply
Yea im slightly confused aswell,

Like, user register via c5, that makes an acct,
User registers via facebook, that makes an acct with a user attribute?

or are we somehow connecting accts?
andrew replied on at Permalink Reply
I don't know that there would have to be an option to explicitly "connect" accounts. I don't think people care about that and I think that use case is pretty low. I do think, however, that there might be times when a user has a concrete5 account on the site (and by concrete5 account I mean a regular, registered user account on their website) and then later logs in via facebook.

If that happens, and the email addresses exist, I think you dump the user to a screen where they have to login via their concrete5 account.

Check out the open ID portion of the login flow in the login.php single page to see this. There is a conditional for whether a user is logging in via open ID and their email already exists in the system.
jshannon replied on at Permalink Reply
Yeah. I was concerned about the case where I was able to login to someone's c5 account by creating a twitter account with the same username. Or their twitter-linked account by creating a FB account, etc.

So, if the accounts aren't permanently linked, there'll definitely have to be something that allows a post-facto linkage...
utomo replied on at Permalink Reply
IMHO we need a connection.
example we have Facebook account, Twitter, Google, Yahoo and others.

by having this connections. there is possibilities that someone will create add on for displaying Facebook status, twitter tweet and others at concrete5 wall.
by doing this we can make user more stick to concrete5 wall. and no need to leave it because they want to check facebook status or twitter and others

Just my 2c
ijessup replied on at Permalink Reply
From what I read, it looks like the only focus is on the "Login" page. What about blocks, and other programatic logins? Would we still use...
$u = new User($username, $password);
... and expect this to automatically use the enabled AuthenticationTypes? OR is it expected that the programatic logins would need to specify which AuthenticationType to use?

I could see how this might cause some legacy issues, so this probably just wishful thinking, but... It would be nice to see the User class get a little more fluid.
$u = User($username, $password_1, $password_2, ..., $password_X);
In this case, c5 just passes the arguements to each enabled AuthenticationType's controller until it gets the green light. If the arguement count doesn't match up, we can auto fail the authetication attempt and move on to the next enabled controller.
Mnkras replied on at Permalink Reply
That is a good point, Lets say that the core login is disabled, when we add a new user, how to we associate their accounts (with the 3rd party services)?

andrew replied on at Permalink Reply
It would be different for each service. The Facebook addon would create a Facebook user Id attribute for example.

This is much the same way that current Facebook and twitter addons work, just a more unified way of building them so that they all show up in one spot in the core, all can be built In the same way generally speaking.
jshannon replied on at Permalink Reply
My understanding of a lot of the "typical" authentication types is that you never deal with a password -- it's all oauth (and authentication window) and cookies based.

So, the idea of validating a user in this way (ie, passing a password to a function) won't work. Theoretically, today, I could call User('a', 'a'), User('b', 'b'), User('c', 'c') in succession and end up with 3 different users objects... I don't think this model will work with, e.g., facebook.

Instead, add-ons would basically just run a function which loads a new page (or ajax) which pops up the oauth window.

... this is all based on my memory of looking into this last year...

andrew replied on at Permalink Reply
Agreed. The core concrete5 login methods would remain unchanged. The authentication frameworks would have their own authentication methods - and some like oauth based ones might not even have any, since they move the user over to other services to be authenticated.
notzen replied on at Permalink Reply

Is there any news about this topic?

thank you,
ijessup replied on at Permalink Reply
Just waiting for 5.5's release. We'll see what we can do with it when we get it. :)
utomo replied on at Permalink Reply
5.5.1 is available.

Is there any news about this ?
I Think it is useful.
I hope it will be released soon.
Or maybe any add on ?
Mnkras replied on at Permalink Reply
As far as I know, this has not been started (it may have been started, but it hasn't been developed far enough to call it something)
utomo replied on at Permalink Reply
Thanks for the Info.

Is there any add on which can fill the gap for a while ?
jshannon replied on at Permalink Reply
There appear to be a lot of "gotchas" in this. Does anybody have experience with another framework (joomla, etc) that's already implemented a authentication framework?
jshannon replied on at Permalink Reply
So I spent a lot of yesterday thinking about and researching this. Even created a github fork. I think I've considered a lot of the gotchas. Maybe I'm making missing something simple, and making this overly complex, but below are my thoughts. It definitely requires tweaking of the original requirements doc & vision, which is why I wanted to lay it out here for discussion before I go forward.

Objective is to enable modular registration and authentication.

A c5 account has associated data which is important to retain. (ie, c5 accounts "disposable" like in some "use these third parties to comment".) An association to a c5 account has to be made.

1. User with existing c5 account wants to associate that account with an additional authentication method.
2. User wants to create a new account using 3PA provider.
3. Use wants to log in to existing account using 3PA.
4. User has existing account, possibly with an associated 3PA, but forgets provider. Tries to "log in" with incorrect one.

So... there are 3 Actions: New Account, Associate Existing Account, Log in using association

New Account
What's the best way to create a new c5 user with my FB credentials? I don't think you make them create a c5 account, then associate. It has to be one logical action. Plus, that would require that password auth sticks around.
Can probably get most info from provider
Might need additional info (attributes required on registration)
Probably not wise to automatically create a new account without confirmation (such as case #4 -- user should be told that they couldn't be automatically logged in, so we're creating an account... or they can try to log in with another provider)
--> 3PA plugin should drop a new user into a core page to finish off registration

Probably not safe to associate automatically (based, e.g., on email address being the same). Also, might be a different identifier (e.g., linkedin provides an unrecorded email address).
--> association requires you to be logged in, or to log in, to complete association
--> --> might get complex to authenticate with, e.g., Google in order to associate with Facebook. At least for v1, assocations can only be done by using the core password authentication (which will be "hardcoded" into this process)

Log In
Nothing special identified

For Callbacks
Some callbacks are programmatic, others are client redirects. The redirects will have to go to the auth controller, with an argument to specify the plugin, which will then get invoked. The programmatic callbacks can use tools, but the /tools/? handler will have to be modified (tools are hardcoded) and the 3PA plugin won't necessarily be a package.

Storage of data
I can see some plugins having to store lots of various bits. Maybe the "advanced password" authentication would store last date password changed, last 5 password hashes, number of failed attempts, etc. And oauth stuff could have a few different fields, per plugin. If you're trying to use attributes to store, you might end up with 20 new attributes, not all of which should be cluttering up the user's profile. If the plugins want to use attribute, fine, but I think managing their own table should be an option.

Non-interface plugins
Many plugins won't have much of an interface. FB, Google, etc are just a button. Even OpenID is just a single text field, and doesn't have all the "forgot password" stuff. I don't think tabs make much sense. I can imagine people will download a half dozen 3PA plugins for their c5 site (google, fb, linkedin, twitter, etc). Seems silly to have 6 tabs, most of which will just be a button. Plugins should be able to say that they only need a button, and provide the code... the login page will show a list of buttons outside of the tab box.

Usernames and email addresses in c5 need to be unique. It appears that the openid auth creates a username from the openid ID. This isn't very clean and lots of sites use the usernames publicly (so we can't set the username to FB1234).

New Account
The registration page should be similar to today, but with a tab setup similar to the login page. It should have the "list of buttons". If I click on one of those, I go through the "association" and come back to the registration page, but with as many fields as possible filled out. I still need to fill out the remaining required fields. An OpenID style plugin would work similarly. Password authentication would add a password box, etc. (not sure how to best implement this into the UI)

Associate / Log In
At least for v1, association happens through the log in. No post-login association.

User goes to log in. They have the normal tabbed choice of plugins, plus the one-click buttons. There are really 3 outcomes (success, failed, success-without-association). Success and fail are treated normally, but without-association would have to redirect to the registration page.
Willemh replied on at Permalink Reply 1 Attachment
Good to see there is movement here. I have just finished the skeleton as Andrew described in the PDF. This allows for installation of custom authentication types. It is written as a package, so i am not messing up with core.

Tonight i am working on the settings page per authentication type, when that is working i will share the code on github. I looking forward to build twitter, facebook and google authentication asap.

I will also look into how to associate profile information from facebook with a user profile. Thinking about listing the custom attributes on a profile, and then provide a select box with the options that facebook provides. This will allow you to capture all the good stuff that facebook has.

Screenshot of the dashboard attached
RadiantWeb replied on at Permalink Reply
that looks very cool. can't wait to test it out.

hanicker replied on at Permalink Reply
I have a package in marketplace that enables third party login using hybridauth library.

It's in approval process from ~november and it seems to work without bugs, even to other users.

Hope it will be approved, as some people may be interested in it.
12345j replied on at Permalink Reply
Ive gotten some work done on this is the past few days
the only issue I still have with the core login is with the helper functions- like forgot password. I can't figure out how to load the correct controller and call the function. I tried using the __call magic method but still get a page not found error.

Should I just assume that core login is the only one that has these functions?

The other forms that core login is complicating other things too. Any advice appreciated.
jshannon replied on at Permalink Reply
Thanks. I'm glad somebody has started this.

I don't think it's safe to assume that core login is the only one with a forgot password. Probably one of the few, but it seems artificially limiting.

Is it ready to get hacked up? I've only looked at the code (not installed), but the first thing that pops out at me is the lack of "extensions". For example, you have 3 (or 4?) "AuthenticationControllers" and none extend others. Maybe I'm missing another class, but I think that thoughtful extending of a core class also solves the "helper function" problem.

However... I'd really like some responses (and consensus) to my detailed post of a month ago (not just from you, from others). For example, I really don't think each "icon" login should get a tab (which seems to be how this package does it). Imagine having FB, LI, Google, Github, etc, etc, etc... all with their own tab (and you know that site owners will go with the "more is better" approach with 3PA plugins).

Similarly... what about registration? I think we're missing any "registration" here as well.

Similarly, ljessup's comment about how this is exposed to blocks and packages.

Really... andrew's doc was a good start, but I don't think there's enough understanding of the big picture or consensus of the details to do much coding before a simple proof of concept.

12345j replied on at Permalink Reply
Pretty soon after I started on open id I realized that a lot of things are going to need helper functions. so only core will definitely not work.

I don't think thoughtful extension will work because basically you would need to dynamically extend the class, because you don't know what authentication library controller you nee to use.

I think registration should be taken care of actually. The way the core does it with open id seems to be fairly elegant. (but needs the use of those helper functions)

I disagree on the tab login structure. I think its a fairly elegant way to present the data, and it doesn't clutter the screen unnecessarily.

The package situation seems to be fairly straightforward. Am I missing something about it?

Now, in response to your older comment

First, take everything witha grain of salt. Im far from an expert on these authentication systems.

new account
this is pretty much the way the core does it right now with open id. I think thats a good
approach. It just gives you a form with some information already filled out with the info openid provides.

think thats probably about right. you might be able to get by without using tools. Either way, Id say this is a library by library thing, not one that involves the framework.

makes sense. Id think that installing the attribute and not using show attribute on profile would work.

think this is really personal preference. you could probably put up a wrapper with a setting for either one.

the open id plugin gets users to fill in a username for themselves in the sign up process. I think that would be good for most cases.

i don't know if the registration needs to be cluttered with all the buttons. maybe just a link to the button/tab page or something like that.
wcravens replied on at Permalink Reply
This feature is paramount for our acceptance of C5 for a project. So much so that if it's not done / being done then we'll have to see if we have the bandwidth to do it.

But not sure if it's really in your plans or not... the URL is 404'd

hanicker replied on at Permalink Reply
Have you checked Social Login package? Regards, Nick
andrew replied on at Permalink Reply
I'd love to have help on this. It's a priority for 5.7 but that won't be coming out til close to the end of the year. I'd be happy to give feedback on it as you're working on it (rather than all at once toward the end.)

Here is the post (not sure when it got moved):

Obviously that document is a little out of date and the UI would have to conform to our 5.5/5.6 plans. Send me a private message if you'd like to know more.
wcravens replied on at Permalink Reply
I still lack the bandwidth to help with this but I am still very interested in it. We basically mothballed our plans that would make use of C5 but I think they are going get opened back up again around Feb.

So are there any updates? Is there any progress that needs testing? We can definitely help with that if there's something to play with.
wcravens replied on at Permalink Reply
I finally have some bandwidth to apply to this problem. How can I help? I do still really need this for the application I have in mind for C5 so I'm keen.
jshannon replied on at Permalink Reply
Hi... If you do build this, you should review the above discussions. Lots of people (including me) put some thoughts down that should be considered before going forward. Also, a few months ago I implemented a really solid (much better than the social login plugin, which I used as my base and then modified for 3 days) FB login, and you'll come across a few more gotchas, though, if I recall, a lot of those were specific to trying to not modify the core.

novologic replied on at Permalink Reply
ActiveCollab and Moodle both do a Good job at allowing 3rd party apps or DB's to be used for authentication. Might be worth looking into this.

We have done considerable SSO implementations for some of our large fortune 1000 clients. And could lend a hand in this if still needed