A server-side Node.js library for integrating OwnID passwordless authentication with Azure Active Directory B2C.
This package provides a server-side solution for integrating OwnID with Azure B2C by exposing three required endpoints:
-
/setOwnIDDataByLoginId
- Store OwnID data for a user -
/getOwnIDDataByLoginId
- Retrieve OwnID data for a user -
/getSessionByLoginId
- Generate authentication tokens after successful OwnID authentication
npm install @ownid/azure-b2c
- Node.js 16+ and npm
- Existing Azure B2C tenant
- OwnID account and application
Create a .env
file with your Azure and OwnID credentials:
AZURE_TENANT_ID=your-tenant-id
AZURE_CLIENT_ID=your-client-id
AZURE_CLIENT_SECRET=your-client-secret
AZURE_B2C_EXTENSION_APP_ID=your-extension-app-id
B2C_TENANT_NAME=yourtenant.onmicrosoft.com
OWNID_SHARED_SECRET=your-ownid-shared-secret
// server.js
require('dotenv').config();
const express = require('express');
const { createOwnIdAzureB2CRouter } = require('@ownid/azure-b2c');
const app = express();
const port = process.env.PORT || 3000;
// Required middleware for parsing JSON requests
app.use(express.json());
// Create and mount the OwnID router
const ownidRouter = createOwnIdAzureB2CRouter({
azureTenantId: process.env.AZURE_TENANT_ID,
azureClientId: process.env.AZURE_CLIENT_ID,
azureClientSecret: process.env.AZURE_CLIENT_SECRET,
azureB2cExtensionAppId: process.env.AZURE_B2C_EXTENSION_APP_ID,
b2cTenantName: process.env.B2C_TENANT_NAME,
ownIdSharedSecret: process.env.OWNID_SHARED_SECRET,
// disableRequestVerification: true // Uncomment to disable request verification (not recommended for production)
});
// Mount the router at /ownid
app.use('/ownid', ownidRouter);
// Start the server
app.listen(port, () => {
console.log(`Server running on port ${port}`);
console.log(`Endpoints available:`);
console.log(` POST http://localhost:${port}/ownid/setOwnIDDataByLoginId`);
console.log(` POST http://localhost:${port}/ownid/getOwnIDDataByLoginId`);
console.log(` POST http://localhost:${port}/ownid/getSessionByLoginId`);
});
The library creates three Express endpoints required by OwnID:
-
Set OwnID Data -
POST /ownid/setOwnIDDataByLoginId
- Stores OwnID authentication data for a user identified by email address
- Request includes:
loginId
(email) andownIdData
(OwnID data)
-
Get OwnID Data -
POST /ownid/getOwnIDDataByLoginId
- Retrieves OwnID authentication data for a user identified by email address
- Request includes:
loginId
(email)
-
Generate Session -
POST /ownid/getSessionByLoginId
- Creates authentication tokens for a user after successful OwnID authentication
- Request includes:
loginId
(email) - Returns access tokens that can be used for authentication
All endpoints include signature verification by default, requiring ownIdSharedSecret
to be provided. Verification can be explicitly disabled with disableRequestVerification: true
.
You can provide your own session token generation logic, such as custom JWT creation:
const { createOwnIdAzureB2CRouter } = require('@ownid/azure-b2c');
const jwt = require('jsonwebtoken');
// Custom session generator function
const customSessionGenerator = async (userId, email, user) => {
// Create a custom JWT token
const token = jwt.sign(
{
sub: userId,
email: email,
name: user?.displayName,
// Add custom claims as needed
},
process.env.JWT_SECRET,
{ expiresIn: '1h' }
);
return {
accessToken: token,
expiresIn: 3600,
tokenType: 'Bearer'
};
};
// Create router with custom session generator
const ownidRouter = createOwnIdAzureB2CRouter({
azureTenantId: process.env.AZURE_TENANT_ID,
azureClientId: process.env.AZURE_CLIENT_ID,
azureClientSecret: process.env.AZURE_CLIENT_SECRET,
azureB2cExtensionAppId: process.env.AZURE_B2C_EXTENSION_APP_ID,
b2cTenantName: process.env.B2C_TENANT_NAME,
ownIdSharedSecret: process.env.OWNID_SHARED_SECRET,
customSessionGenerator: customSessionGenerator
});
app.use('/ownid', ownidRouter);
You can directly access the core services for custom integration:
const { OwnIDB2CAuth, OwnIDB2CUserService } = require('@ownid/azure-b2c');
// Create auth service
const auth = new OwnIDB2CAuth({
azureTenantId: process.env.AZURE_TENANT_ID,
azureClientId: process.env.AZURE_CLIENT_ID,
azureClientSecret: process.env.AZURE_CLIENT_SECRET,
azureB2cExtensionAppId: process.env.AZURE_B2C_EXTENSION_APP_ID,
b2cTenantName: process.env.B2C_TENANT_NAME,
ownIdSharedSecret: process.env.OWNID_SHARED_SECRET
});
// Create user service
const userService = new OwnIDB2CUserService(auth);
// Use the services
async function findUser(email) {
return await userService.findUserByEmail(email);
}
This library includes built-in request verification using HMAC signatures to ensure all incoming requests from OwnID are legitimate. By default, verification is required and you must provide ownIdSharedSecret
.
The signature verification uses:
- Request body
- Request timestamp
- Shared secret
Requests are rejected if:
- No shared secret is provided (unless explicitly disabled)
- Required headers are missing
- Signature doesn't match
- Request is too old (timestamp validation)
If you need to disable verification (not recommended for production), you can set disableRequestVerification: true
in the configuration.
You'll need to register a dedicated application in your Azure B2C tenant and configure it with the appropriate permissions:
- Register an application in your B2C tenant for OwnID integration
- Create a client secret and note it down
-
Configure API permissions: Add
User.ReadWrite.All
permission to Microsoft Graph - Grant admin consent for the added permissions
- Find your B2C extension app ID (the special b2c-extensions-app that's automatically created in your tenant)
For detailed step-by-step instructions, refer to instructions.md in the GitHub repository.
MIT