@rakered/accounts
v1.6.0
Published
An account package for managing user accounts in mongodb.
Downloads
22
Readme
@rakered/accounts
An account package for managing user accounts in mongodb.
This project aims to be somewhat compatible with Meteor accounts storage, Except for the email verification tokens, resume tokens, and restrictions on usernames. See the FAQ for more specifics about that subject.
Usage
import init from '@rakered/accounts';
const accounts = init();
await accounts.createUser({ username: 'hunter', password: 'hunter2' });
Options can be provided in two ways, passing them as object to init
, or by providing them as environment variables.
Options
There are various options available. In development mode, this library does not require a MAIL_URL
to be set, instead emails will be logged to console.
Environment Variables
MAIL_URL String
The smtp url for the mail server to use.
Optional when running in development mode
JWT_SECRET String
The secret to sign the jwt tokens with.
EMAIL_FROM String
The email address that's being used as sender.
Optional if
options.email.from
is providedBASE_URL String
The url that will be prefixed to magic urls and provided to the email template.
Optional if
options.email.siteUrl
is providedSITE_NAME String
The site name that will be provided to the email template.
Optional if
options.email.siteName
is providedLOGO_URL String
The url for the logo that will be shown in the email.
Optional if
options.email.logoUrl
is provided
Collection
First things first, the database connection. If you don't specify anything, it will be managed for you with @rakered/mongo. The account system will connect to the MongoDB instance that's available under process.env.MONGO_URL
, and will use the users
collection to save and read the documents.
custom collection name
If you just wish to specify a different collection, provide the collection name during initialization.
import init from '@rakered/accounts';
const accounts = init({
collection: 'accounts',
});
custom collection instance
If you need more control, it's also possible to pass in a MongoDB Collection instance to it.
import db from '@rakered/mongo';
import init from '@rakered/accounts';
const accounts = init({
collection: db.users,
});
using native MongoDB driver
Or even using a native MongoDB Collection
import { MongoClient } from 'mongodb';
import init from '@rakered/accounts';
const client = await MongoClient.connect(process.env.MONGO_URL);
const db = await client.db();
const accounts = init({
collection: db.collection('users'),
});
using Meteor.users collection
When migrating away from Meteor, the rawCollection
can be used:
import init from '@rakered/accounts';
const accounts = init({
collection: Meteor.users.rawCollection(),
});
This library uses @rakered/email to send emails for email address verification and to send password reset tokens. The address for the smtp server is read from process.env.MAIL_URL
, be sure to set it to any valid smtp url.
Provide the following options before you deploy to production. The values are used in the email template, and should be replaced with your own.
import init from '@rakered/accounts';
const accounts = init({
email: {
from: '[email protected]',
siteName: 'Example',
siteUrl: 'https://example.com',
logoUrl: 'https://example.com/logo.png',
},
});
Token URLs
When using the email system, it's likely that you need to configure the token URLs. By default, the URLs are configured to use the format as below, but with https://example.com
replaced by the siteUrl
that you've configured under email
. Meaning, the verify-email
URL, would default to ${siteUrl}/verify-email/${token}
. If this schema matches your needs, there is no need to customize. Otherwise, adjust them to accordingly.
import init from '@rakered/accounts';
const accounts = init({
urls: {
verifyEmail: (token) => `https://example.com/verify-email/${token}`,
enrollAccount: (token) => `https://example.com/enroll-account/${token}`,
resetPassword: (token) => `https://example.com/reset-password/${token}`,
},
});
Methods
Methods. This library comes with various methods to manage the accounts.
createUser(options)
Create a new user.
options
Both username
as well as email
are optional, but one of those must be provided.
username String
A unique name for this user. Usernames need to match the same requirements as GitHub usernames.
- may only contain alphanumeric characters and hyphens.
- cannot have multiple consecutive hyphens.
- cannot begin or end with a hyphen.
- has a minimum length of 3 characters
- has a maximum length of 20 characters
In addition to the GitHub requirements, there is also a list of
reserved
usernames, that cannot be claimed. Think.wellknown
,admin
,own
,owner
,you
,yourself
, and a bunch more.Lastly, usernames are not only guaranteed to be unique, but also not look-alike. To prevent confusion by end users, It's not possible to register both
smeijer
as well ass-meijer
.Optional if
email
is providedemail String
The user's email address.
Optional if
username
is providedpassword String | { digest: String, algorithm: 'sha-256' }
Optional - The user's password. The password should not be send in plain text over the wire. Instead, use @rakered/hash to hash it with sha-256 before sending it to the server. When left out, this function won't be returning refresh tokens. We assume that no password, means that the user is being invited. Use
sendEnrollmentEmail
to let them set their initial password.name String Optional - The full name of the user.
roles String[]
Optional - A string array with roles that should be assigned. These roles will be included in the request token, enabling permissions checks without database requests.
setUsername(options)
Change a user's username. Use this instead of updating the database directly. The operation will fail if there is an existing user with a similar looking username, or if the username does not match the conditions as specified under createUser
.
options
userId String
The ID of the user to update
username String
The new username for the user
addEmail(options)
Add an email address for a user. Use this instead of directly updating the database. The operation will fail if there is a different user with the same email address.
options
userId String
The ID of the user to update.
email String
The new email address for the user
verified Boolean
Optional - whether the new email address should be marked as verified. Defaults to false.
removeEmail(options)
Remove an email address for a user. Use this instead of updating the database directly.
options
userId String
The ID of the user to update.
email String
The email address to remove.
verifyEmail(options)
Marks the user's email address as verified and returns an access token.
options
token String
The token retrieved from the verification URL.
resetPassword(options)
Reset the password for a user using a token received in email.
options
token String
The token retrieved from the reset password URL.
password String | { digest: String, algorithm: 'sha-256' }
A new password for the user. The password should not be send in plain text over the wire. Instead, use @rakered/hash to hash it with sha-256 before sending it to the server.
login(options)
Obtain a refreshToken
and accessToken
by using password based authentication.
options
identity String
The
username
oremail
from the user for which the token should be created.password String | { digest: String, algorithm: 'sha-256' }
The user's password. The password should not be send in plain text over the wire. Instead, use @rakered/hash to hash it with sha-256 before sending it to the server.
refreshToken(options)
Obtain a fresh refreshToken
and accessToken
. Note that the current refreshToken
is revoked.
options
refreshToken String
The current refresh token.
accessToken String
The current access token.
revokeToken(options)
Revoke the refreshToken
so it can no longer be used to obtain new accessTokens
.
options
refreshToken String
The token that should be revoked.
accessToken String
The current access token.
sendEnrollmentEmail(options)
Send an email with a link the user can use to set their initial password.
options
userId String
The id of the user to send email to.
email String
Optional. Which address of the user's to send the email to. This address must be in the user's
emails
list. Defaults to the first email in the list.
sendVerificationEmail(options)
Send an email with a link the user can use verify their email address.
options
userId String
The id of the user to send email to.
email String
Optional. Which address of the user's to send the email to. This address must be in the user's
emails
list. Defaults to the first unverified email in the list.
sendResetPasswordEmail(options)
Send an email with a link the user can use to reset their password.
options
userId String
The id of the user to send email to.
email String
Optional. Which address of the user's to send the email to. This address must be in the user's
emails
list. Defaults to the first email in the list.
disconnect
Close the database connection. Useful when using accounts in console scripts.
Properties
collection
The MongoDB Collection is exposed under the accounts.collection
property, for when you need direct access to the collection.
Good to knows
The email verification tokens are incompatible with Meteor, because I've taken a different approach there, to limit the database request to a maximum of 1 call per method. The way Meteor manages the verification tokens requires two requests per email verification attempt.
I've weighted the pros and cons, and came to the conclusion that a single request outweighs the benefit of Meteor compatibility in this area. In the case where this project is connected to an existing Meteor database, it would be trivial to either migrate the tokens to the format of this project, or to let the user request a new verification token.
To migrate existing tokens, check our migration script example
Usernames are more strict than in Meteor, because of this it can be that your existing user collection cannot be used as source for this library. Meteor usernames are case sensitive. Meaning,
alex
,Alex
, andAleX
are different users. We do not support this. We can write a detection script for this, but that's something we still have to do.