For internal RegardingWork services using SSO
A Mini-App is a trusted service that's part of the RegardingWork ecosystem family. Mini-Apps use SSO (Single Sign-On) for seamless user authentication without complex OAuth flows.
Mini-apps should offer two authentication methods for the best user experience:
One-click login via RegardingWork Hub
Manual username/password entry
User visits your mini-app and clicks login button.
Mini-app redirects to Hub's SSO authorization endpoint.
Hub authenticates user (login form if needed).
Hub redirects back with JWT token in URL.
Mini-app validates token with Hub API.
sequenceDiagram
participant User
participant MiniApp
participant Hub
User->>MiniApp: Click Login
MiniApp->>Hub: Redirect to /api/auth/sso/authorize
Hub->>User: Login form (if needed)
User->>Hub: Credentials
Hub->>MiniApp: Redirect with ?token=jwt
MiniApp->>Hub: Validate token /api/auth/validate
Hub->>MiniApp: User data
MiniApp->>User: Logged in dashboard
User provides RegardingWork username and password.
Mini-app calls Hub's login API directly.
Hub returns access and refresh tokens.
Mini-app stores tokens for API calls.
sequenceDiagram
participant User
participant MiniApp
participant Hub
User->>MiniApp: Enter username/password
MiniApp->>Hub: POST /api/auth/login
Hub->>Hub: Validate credentials
Hub->>MiniApp: Access & refresh tokens
MiniApp->>User: Logged in dashboard
Follow the alivefor.com/login pattern for optimal user experience:
<!-- Primary SSO Option -->
<div class="sso-section">
<h3>Login to [Your App Name]</h3>
<p>Save your data and access your profile</p>
<a href="#" onclick="startSSO()" class="btn btn-primary btn-lg w-100 mb-3">
<i class="fa fa-shield"></i> Sign in with RegardingWork Hub
</a>
<p class="text-muted">Unified access across all RegardingWork services</p>
</div>
<!-- Divider -->
<div class="text-center my-4">
<span class="text-muted">Or sign in directly</span>
</div>
<!-- Secondary Direct Login -->
<form onsubmit="loginDirect(event)" class="direct-login-form">
<div class="mb-3">
<label>RegardingWork Username</label>
<input type="text" name="username" class="form-control" required>
</div>
<div class="mb-3">
<label>Password</label>
<input type="password" name="password" class="form-control" required>
</div>
<button type="submit" class="btn btn-outline-primary w-100">
Login Directly
</button>
</form>
<!-- Registration Link -->
<div class="text-center mt-4">
<p>Don't have a RegardingWork account?</p>
<a href="https://hub.regardingwork.com/register" class="btn btn-link">
Create RegardingWork Account
</a>
<p class="text-muted small">Register at RegardingWork Hub for full ecosystem access</p>
</div>
Contact Hub admin to add your domain to the SSO allowed domains list.
*.regardingwork.com
tx.licensedbank.com
, alivefor.com
// SSO login function
function startSSO() {
const redirectUri = encodeURIComponent('https://your-app.com/api/auth/callback');
const ssoUrl = `https://hub.regardingwork.com/api/auth/sso/authorize?redirect_uri=${redirectUri}&service=your-app`;
window.location.href = ssoUrl;
}
// Direct login function
async function loginDirect(event) {
event.preventDefault();
const formData = new FormData(event.target);
try {
const response = await fetch('https://hub.regardingwork.com/api/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: formData.get('username'),
password: formData.get('password')
})
});
const result = await response.json();
if (result.access_token) {
// Store tokens
sessionStorage.setItem('access_token', result.access_token);
sessionStorage.setItem('refresh_token', result.refresh_token);
// Redirect to dashboard
window.location.href = '/dashboard';
} else {
alert('Login failed: ' + result.error);
}
} catch (error) {
alert('Login error: ' + error.message);
}
}
Create an endpoint to receive the token from Hub:
// SSO callback endpoint: /api/auth/callback
app.get('/api/auth/callback', (req, res) => {
const token = req.query.token;
if (!token) {
return res.redirect('/login?error=no_token');
}
// Store token in session/cookie
res.cookie('auth_token', token, {
httpOnly: true,
secure: true,
sameSite: 'strict'
});
// Redirect to dashboard
res.redirect('/dashboard');
});
For protected API calls, validate tokens with Hub:
// Token validation middleware
async function validateToken(req, res, next) {
const token = req.cookies.auth_token || req.headers.authorization?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
try {
const response = await fetch('https://hub.regardingwork.com/api/auth/validate', {
headers: {
'Authorization': `Bearer ${token}`
}
});
const result = await response.json();
if (!result.valid) {
return res.status(401).json({ error: 'Invalid token' });
}
req.user = result.user;
next();
} catch (error) {
return res.status(500).json({ error: 'Token validation failed' });
}
}
Clear tokens and optionally redirect to Hub logout:
// Logout endpoint
app.post('/api/auth/logout', (req, res) => {
// Clear local token
res.clearCookie('auth_token');
// Optional: Redirect to Hub logout for complete SSO logout
const logoutUrl = 'https://hub.regardingwork.com/logout';
res.json({ redirect: logoutUrl });
});
Endpoint | Method | Purpose | Parameters |
---|---|---|---|
/api/auth/sso/authorize |
GET | SSO authorization | redirect_uri , service |
Endpoint | Method | Purpose | Parameters |
---|---|---|---|
/api/auth/login |
POST | Direct login with username/password | username , password |
Endpoint | Method | Purpose | Parameters |
---|---|---|---|
/api/auth/validate |
GET | Token validation | Authorization: Bearer {token} |
/api/auth/refresh |
POST | Refresh token | refresh_token |
/api/auth/me |
GET | Get user profile | Authorization: Bearer {token} |
Authorization: Bearer {token}
https://hub.regardingwork.com/api/auth/validate