oidc-hosted-page-node

Implement SSOJet OIDC (Node.js / Express)

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "oidc-hosted-page-node" with this command: npx skills add ssojet/skills/ssojet-skills-oidc-hosted-page-node

Implement SSOJet OIDC (Node.js / Express)

This expert AI assistant guide walks you through integrating "Sign in with SSO" functionality into an existing login page in a Node.js Express application using SSOJet as an OIDC identity provider. The goal is to modify the existing login flow to add SSO support without disrupting the current traditional login functionality (e.g., email/password).

  1. Prerequisites
  • An existing Node.js application with Express and a login page.

  • Basic knowledge of Express.js routing and middleware.

  • An active SSOJet account.

  • SSO Connection Setup Guide

  • Required libraries: openid-client , express-session .

  1. Implementation Steps

Step 1: Create Application in SSOJet

  • Log in to the SSOJet Dashboard.

  • Navigate to Applications.

  • Create a new application (e.g., "MyNodeApp", type Regular Web App).

  • Configure the callback URI (e.g., http://localhost:3000/auth/callback ).

  • Retrieve Client ID and Client Secret.

  • Copy the Issuer URL from the Advanced > Endpoints section.

Step 2: Modify the Existing Node.js Project

Substep 2.1: Install Dependencies

Run the following command to install the required libraries:

npm install openid-client express-session dotenv

Substep 2.2: Configure Environment Variables

Create a .env file in the project root:

SSOJET_ISSUER_URL=https://auth.ssojet.com SSOJET_CLIENT_ID=your_client_id SSOJET_CLIENT_SECRET=your_client_secret SSOJET_REDIRECT_URI=http://localhost:3000/auth/callback SESSION_SECRET=a_strong_random_secret PORT=3000

Substep 2.3: Configure OIDC Client

Create a dedicated utility file for OIDC configuration (e.g., lib/oidc.js ):

// lib/oidc.js const { Issuer } = require('openid-client');

let _client = null;

async function getClient() { if (_client) return _client;

const ssojetIssuer = await Issuer.discover(process.env.SSOJET_ISSUER_URL); _client = new ssojetIssuer.Client({ client_id: process.env.SSOJET_CLIENT_ID, client_secret: process.env.SSOJET_CLIENT_SECRET, redirect_uris: [process.env.SSOJET_REDIRECT_URI], response_types: ['code'], });

return _client; }

module.exports = { getClient };

Substep 2.4: Update Login Page/UI

Modify your existing login page template (e.g., views/login.ejs or equivalent) to include the "Sign in with SSO" toggle:

<!-- views/login.ejs --> <div class="login-container"> <h1>Sign In</h1>

<form id="loginForm" action="/auth/login" method="POST"> <div> <label for="email">Email</label> <input type="email" id="email" name="email" required /> </div>

&#x3C;div id="passwordField">
  &#x3C;label for="password">Password&#x3C;/label>
  &#x3C;input type="password" id="password" name="password" required />
&#x3C;/div>

&#x3C;input type="hidden" id="isSSO" name="isSSO" value="false" />

&#x3C;button type="submit" id="submitBtn">Sign In&#x3C;/button>

</form>

<button type="button" id="ssoToggle" onclick="toggleSSO()"> Sign in with SSO </button> </div>

<script> function toggleSSO() { const isSSO = document.getElementById('isSSO'); const passwordField = document.getElementById('passwordField'); const submitBtn = document.getElementById('submitBtn'); const ssoToggle = document.getElementById('ssoToggle');

if (isSSO.value === 'false') {
  isSSO.value = 'true';
  passwordField.style.display = 'none';
  document.getElementById('password').removeAttribute('required');
  submitBtn.textContent = 'Continue with SSO';
  ssoToggle.textContent = 'Back to Password Login';
} else {
  isSSO.value = 'false';
  passwordField.style.display = 'block';
  document.getElementById('password').setAttribute('required', 'true');
  submitBtn.textContent = 'Sign In';
  ssoToggle.textContent = 'Sign in with SSO';
}

} </script>

Substep 2.5: Update Backend Logic

Create the necessary routes to handle the OIDC flow.

  1. Login Route (routes/auth.js ):

// routes/auth.js const express = require('express'); const router = express.Router(); const { getClient } = require('../lib/oidc');

// Handle login form submission router.post('/login', async (req, res) => { const { email, isSSO } = req.body;

if (isSSO === 'true') { // Trigger SSO login const client = await getClient();

// Generate a random state for CSRF protection
const state = Math.random().toString(36).substring(2, 15);
req.session.oidc_state = state;

const authorizationUrl = client.authorizationUrl({
  scope: 'openid profile email',
  login_hint: email || undefined,
  state,
});

return res.redirect(authorizationUrl);

}

// Existing password login logic here console.log('Processing traditional login...'); res.redirect('/dashboard'); });

module.exports = router;

  1. Callback Handler Route (routes/callback.js ):

// routes/callback.js const express = require('express'); const router = express.Router(); const { getClient } = require('../lib/oidc');

router.get('/callback', async (req, res) => { const client = await getClient(); const params = client.callbackParams(req);

try { const storedState = req.session.oidc_state; const tokenSet = await client.callback( process.env.SSOJET_REDIRECT_URI, params, { state: storedState } ); const userinfo = await client.userinfo(tokenSet.access_token);

// Clear the OIDC state from session
delete req.session.oidc_state;

// TODO: Create a session for the user based on `userinfo`
req.session.user = userinfo;
console.log('Authenticated User:', userinfo);

// Redirect to the dashboard or intended page
res.redirect('/dashboard');

} catch (error) { console.error('OIDC Callback Error:', error); res.redirect('/login?error=oidc_failed'); } });

module.exports = router;

  1. Main Application Setup (app.js ):

// app.js require('dotenv').config(); const express = require('express'); const session = require('express-session');

const authRoutes = require('./routes/auth'); const callbackRoutes = require('./routes/callback');

const app = express();

app.set('view engine', 'ejs'); app.use(express.urlencoded({ extended: true })); app.use(session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, cookie: { secure: false, httpOnly: true, maxAge: 3600000 }, }));

// Routes app.get('/login', (req, res) => res.render('login')); app.use('/auth', authRoutes); app.use('/auth', callbackRoutes);

app.get('/dashboard', (req, res) => { if (!req.session.user) return res.redirect('/login'); res.send(&#x3C;h1>Dashboard&#x3C;/h1>&#x3C;pre>${JSON.stringify(req.session.user, null, 2)}&#x3C;/pre>&#x3C;a href="/auth/logout">Logout&#x3C;/a>); });

app.listen(process.env.PORT || 3000, () => { console.log(Server running on http://localhost:${process.env.PORT || 3000}); });

Step 3: Test the Modified Connection

  • Start your application: node app.js .

  • Navigate to your login page (e.g., http://localhost:3000/login ).

  • Verify that the traditional login form (Email + Password) is visible by default.

  • Click "Sign in with SSO" and ensure:

  • The password field disappears.

  • The submit button changes to "Continue with SSO".

  • Enter a test email and submit.

  • You should be redirected to the SSOJet login page.

  • Authenticate with SSOJet.

  • You should be redirected back to /auth/callback and then to /dashboard .

  1. Additional Considerations
  • Error Handling: Enhance the callback route to handle specific OIDC errors gracefully.

  • Styling: Adapt the example HTML/CSS to match your application's design system.

  • Security: Use express-session with a production-ready store (e.g., Redis, MongoDB) and enable secure: true for cookies in production.

  • Environment Variables: Never commit .env to source control. Use secrets management in production.

  1. Support
  • Contact SSOJet support: Reach out if you have integration questions.

  • Check application logs: Use server-side logging to debug OIDC flow issues.

  • Library Documentation: Refer to the openid-client documentation for advanced configuration.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

oidc-hosted-page-angular

No summary provided by upstream source.

Repository SourceNeeds Review
General

oidc-hosted-page-nextjs

No summary provided by upstream source.

Repository SourceNeeds Review
General

oidc-hosted-page

No summary provided by upstream source.

Repository SourceNeeds Review