DEV Community

Part II: Persisting OpenID Server Data on MongoDB with Node.js

Ebrahim Hoseiny Fadae on March 10, 2022

Introduction In this article, we'll explore how to integrate MongoDB with an OIDC (OpenID Connect 1.0) authentication server. We'll be u...
Collapse
 
kaboume profile image
Eric

Thanks a lot for this article !

Collapse
 
ebrahimmfadae profile image
Ebrahim Hoseiny Fadae

You're welcome 😄

Collapse
 
webdiy profile image
web-diy

Does panva/node-oidc-provider support the use of PostgreSQL. I want to use it instead of MongoDB.

I would be grateful for any help.

Because when I try to rewrite the Mongo code, I get a lot of errors.

Type '(_: KoaContextWithOIDC, id: string) => Promise<{ accountId: string; claims(_: string, scope: string): Promise<{} | undefined>; } | null>' is not assignable to type 'FindAccount'.
Type 'Promise<{ accountId: string; claims(_: string, scope: string): Promise<{} | undefined>; } | null>' is not assignable to type 'CanBePromise<Account | undefined>'.
Type 'Promise<{ accountId: string; claims(_: string, scope: string): Promise<{} | undefined>; } | null>' is not assignable to type 'Promise<Account | undefined>'.
Type '{ accountId: string; claims(_: string, scope: string): Promise<{} | undefined>; } | null' is not assignable to type 'Account | undefined'.
Type 'null' is not assignable to type 'Account | undefined'.

Collapse
 
ebrahimmfadae profile image
Ebrahim Hoseiny Fadae • Edited

It supports any database you want. You only need to implement the adapter for postgres instead of mongodb. And I think you faced this error because you have enabled strict mode in tsconfig.

Collapse
 
webdiy profile image
web-diy • Edited

I was able to make an Account model. And the table in PG is created.
But now I am unable to create a BaseModel in PG similar to MongoDB.

I get an error: "original: error: column "payload->>'kind'" does not exist"

`sql: `CREATE UNIQUE INDEX "base_models_key_payload" ON "BaseModels" ("key", "payload->>'kind'")`,`
Enter fullscreen mode Exit fullscreen mode

Perhaps you can tell me how to build the correct model for PG?



const { Sequelize, DataTypes, Op} = require('sequelize');


const dbHost = process.env.DB_HOST || ' ';
const dbPort = parseInt(process.env.DB_PORT || ' ', 10);
const dbName = process.env.DB_NAME || ' ';
const dbUser = process.env.DB_USER || ' ';
const dbPassword = process.env.DB_PASSWORD || ' ';
const sequelize = new Sequelize(dbName, dbUser, dbPassword, {
  host: dbHost,
  port: dbPort,
  dialect: 'postgres',
});

//"BaseModel"
const BaseModel = sequelize.define('BaseModel', {
    key: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    payload: {
      type: DataTypes.JSONB,
      allowNull: false,
    },
    expiresAt: {
      type: DataTypes.DATE,
      allowNull: false,
    },
  }, {

    indexes: [
      { fields: ['key', 'payload->>\'kind\''], unique: true, name: 'base_models_key_payload' },
      { fields: ['payload->>\'uid\''], unique: true, where: { payload: { kind: 'Session' } } },
      { fields: ['payload->>\'grantId\''], unique: true, where: { payload: { kind: ['AccessToken', 'AuthorizationCode', 'RefreshToken', 'DeviceCode', 'BackchannelAuthenticationRequest'] } } },
      { fields: ['payload->>\'userCode\''], unique: true, where: { payload: { kind: 'DeviceCode' } } },
      { fields: ['expiresAt'], where: { expiresAt: { [Op.lt]: new Date() } } },
    ],
  });

// Synchronizing the model with the database
(async () => {
  try {
    await sequelize.sync();
    console.log('OK "BaseModel" ');
  } catch (error) {
    console.error('Error "BaseModel":', error);
  }
})();

export  {BaseModel};


Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
ebrahimmfadae profile image
Ebrahim Hoseiny Fadae

I'm not familiar with creating indexes on an unstructured JSONB object in relational databases. I looked for an answer and found stackoverflow.com/a/69575659. I hope this helps.

Collapse
 
kaboume profile image
Eric

Have you used this oidc server in production? Are you satisfied because I hesitate between panva node-oidc-provider and Ory Hydra. I wonder if panva node-oidc-provider will be well maintained over time...

Collapse
 
ebrahimmfadae profile image
Ebrahim Hoseiny Fadae

I have not used panava/node-oidc-provider in production. My primary goal was to show the OpenID protocol implementation. In my opinion ory/hydra is way better and more performant. Also, it is written in go, Which i love. Don't know about the future, But currently, panava/node-oidc-provider is under active development. In the end, what matters is the protocol itself, Implementation could vary based on different factors.

Collapse
 
kaboume profile image
Eric

Thanks a lot for your answer. !

Collapse
 
kaboume profile image
Eric

And did you wrote an Account Class for MongoDB ?

Collapse
 
ebrahimmfadae profile image
Ebrahim Hoseiny Fadae

Do you mean Account.ts?

Collapse
 
kaboume profile image
Eric

In the file "account.service.ts", you import { accounts } from "../db/memory".
If I want to use MongoDB as database for accounts, I have to import in the "account.service.ts" file a db/mongodb.js file which uses the db/mongodb/Account.ts file ?

Thread Thread
 
ebrahimmfadae profile image
Ebrahim Hoseiny Fadae

Yes, It's correct. I will update the article to mention this.