Security with MongoDB
Install
npm i -S @bluelibs/security-bundle @bluelibs/security-mongo-bundleimport { SecurityBundle } from "@bluelibs/security-bundle";import { SecurityMongoBundle } from "@bluelibs/security-mongo-bundle";import { MongoBundle } from "@bluelibs/mongo-bundle";
kernel.addBundles([  // Make sure you have both security and mongo bundle in your kernel  new SecurityBundle(),  new MongoBundle({    uri: "mongodb://localhost:27017/test",  }),
  // Order doesn't really matter.  new SecurityMongoBundle(),]);Purpose
We need to blend MongoBundle which handles our connection to the database with SecurityBundle which is a database-agnostic way to handle authentication, authorization and complex permissioning.
We are doing this by creating the persistence layers (users, sessions, permissions) as MongoDB collections.
Customise
You can opt-out of certain collections, or bring your own collection to the picture:
import { UsersCollection } from "./app/Users.collection.ts";
const kernel = new Kernel({  bundles: [    // the rest    new SecurityMongoBundle({      // override one (example below)      usersCollection: UsersCollection,      // cancel storing one      sessionsCollection: null,      permissionsCollection: null,    }),
    // The collections need to be a constructor of: IUserPersistance, ISessionPersistance, IPermissionPersistance    // which we get from @bluelibs/security-bundle.  ],});The use case for null-ifying is (for example) if you wanted to use Redis you could create a custom persistence layer
which you set in SecurityBundle, and you then wouldn't want this bundle (SecurityMongoBundle) to perform any modifications to use its MongoDB one.
Accessing the MongoBundle collections, for raw access to your data:
import {  UsersCollection,  SessionsCollection,  PermissionsCollection,} from "@bluelibs/security-mongo-bundle";
// Note that this works only if you haven't modified the collectionsconst usersCollection = container.get(UsersCollection);const sessionsCollection = container.get(SessionsCollection);const permissionsCollection = container.get(PermissionsCollection);Custom Users Collection
You have the option to make changes to your collection, for example if you user is linked to other collections or you simply want a different collection name:
import {  UsersCollection as BaseUsersCollection,  PermissionsCollection,} from "@bluelibs/security-mongo-bundle";import { IUser } from "@bluelibs/security-bundle";
class User extends IUser {  _id: ObjectId;  profileId: ObjectId;}
export class UsersCollection extends BaseUsersCollection<User> {  static collectionName = "users"; // override it, by default it's "users"
  static links = {    profile: {      collection: () => ProfilesCollection,      field: "profileId",    },  };
  // static indexes = [];  // you could override anything you wish  // and make sure you pass this class to `SecurityMongoBundle()` options.}The pattern above is a very common scenario in almost every application, we recommend you start with it.
new SecurityMongoBundle({  usersCollection: UsersCollection,});Decoupling
If you have an independent bundle that works with SecurityMongoBundle, and you want to use the UsersCollection, but you don't know if other bundles have stored custom ones, and you would like to work with the main one, the solution is to use the following tokens:
import {  USERS_COLLECTION_TOKEN,  PERMISSIONS_COLLECTION_TOKEN,  SESSIONS_COLLECTION_TOKEN,} from "@bluelibs/security-mongo-bundle";
// You have to check if it exists: container.has(USERS_COLLECTION_TOKEN)const usersCollection = container.get(USERS_COLLECTION_TOKEN);
// If as value we get passed null, we won't register such token inside the container
// Typically you should not interact with `UsersCollection` from a separate bundle,// you interact with the `SecurityService` from `SecurityBundle`Meta
Summary
This joins Security with Mongo and gives you ability to customise it and do lots of nice things.
Challenges
- Create a project in which you override the Users collection and use a custom-made, in-memory Session Management