by an identical sub.
Previously, it would fail to subscribe. This confused the meteor.currentUser
subscription in accounts_client.js. Reproduction:
- Create user X with email (which sends a confirmation email)
- Log out.
- Log in as User Y in tab 1.
- Follow the confirmation link in tab 2. This leaves you logged in
as User Y.
- Tab 1's localstorage poller notices that there's a new token and logs in
with it.
- After a successful login, Accounts._makeClientLoggedIn unsubs from
meteor.currentUser and immediately resubs. It thinks there's already an
existing sub, so it doesn't send the sub message and does immediately call
the ready callback (which sets userLoaded() to true).
- The unsub gets sent and the object in Meteor.users() gets depopulated.
Now Meteor.userLoaded() is true but Meteor.user() is empty.
In the future we may support use of some of the sub-templates directly (eg, we
might expose a "sign in" template and a "create user" template, and keep the
events and links for switching between them on the outer loginButtons) but we
don't yet. This change leaves us open to change the internal details later.
- additional class on the element with class "login-link-and-dropdown-list"
with information about which of the three password flows we are in
- a wrapper element around each label/input pair in the password forms
- links to go back to the sign up flow from create account or forgot password
Include timestamps with the tokens, so that later we can set expiry/cleanup
policies.
Observable changes:
- tokens can no longer be used to log in as a user which no longer exists
- when you log in with a "reset password" link, all logins in other browsers
lose the ability to reconnect. However, other browser logins are not
immediately disconnected, and "change password" does not invalidate any
tokens.
function Meteor.userLoaded(), which is true if you are logged in and the user
doc is loaded, and a currentUserLoaded Handlebars helper to match.
If logged in and the user doc is not yet loaded, Meteor.user() now returns an
object which only contains _id.
The current user subscription is now named meteor.currentUser rather than being
an unnamed sub. (loginServiceConfiguration is renamed
meteor.loginServiceConfiguration to match.) This subscription is sub'd from when
you log in and unsub'd from when you log out (or if you log in with different
credentials).
I was very careful to make sure that in the case of "sub #1, unsub #1, sub #2,
sub #1 is ready" we do not declare the user to be ready. I could have instead
modified livedata_connection to not call ready callbacks for unsub'd
subscriptions (add a "delete self.sub_ready_callbacks[obj._id]" to the self.subs
removed function) but this seemed less invasive.
The password and email tests use this to take a more rigorous approach to
waiting for the data to load, and they change the localStorage keys so that
multiple tabs running tests don't interact via localStorage.
(Well, and services with names like "registerLoginHandler", but whatever.)
This prevents this attack:
- Alice launches site with Facebook login
- Mallory sends configureLoginService method to configure the Twitter service
- Alice runs "meteor add accounts-twitter" and is impressed that Twitter integration
Just Works with no configuration
- Now the app is using Mallory's credentials
- Split login_buttons.html and login_buttons.js into multiple files
- Specifically, make it easier to reason about the display of loginButtons whether it is in dropdown mode or not
- Split templates into subtemplates to make it easier to read the login button .html files as "tables of contents"
- Introduce Meteor._loginButtonsSession, which makes it easier to access internal session fields for loginButtons
- Unify code that calls the various Meteor.loginWithFoo() functions
Breaking change: rename "configureLoginServicesDialogForFoo" to "configureLoginServiceDialogForFoo" (in packages such as accounts-facebook)
This is an internal function only used by OAuth implementations and the
equivalent, so rename to a more specific name:
Accounts.updateOrCreateUserFromExternalService.
Change the signature to directly take serviceName and serviceData instead of a
nested data structure with a very specific structure. Similarly, change
Accounts.oauth.registerService's handleOauthRequest callback to un-nest the
service data.
Throw errors on misuse (if you try to use it with the "password" or
soon-to-be-introduced "resume" services, or if you don't provide an id).
Avoid doing no-op user updates if there is nothing new in "extra".
Rename internal accounts packages to start with meteor_ (better namespacing) and
contain no dots (easier to use in Mongo shell).
We leave "users" un-namespaced but note that we will eventually allow
configuration.
Note that the two token collections may soon be merged into users.
- If there are multiple external login services, show the messages at the bottom
of the login dropdown
- If there is just one external login service, show it in a standalone dialog
- If you're using accounts-password, or you are using more than one oauth provider,
show a dropdown instead of the logout button. (This means that loginButtons either always
shows a dropdown or never)
- If you have a username or email set, show "Change password" and "Logout" in the dropdown.
- If you don't have a username or email set, just show "Logout"
While at it, refactored some code I touched.