mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-20 23:26:41 +02:00
feat(auth): implement cross-subdomain SSO for all web apps
Add Single Sign-On (SSO) support across all mana.how subdomains: - Add trySSO() method to @manacore/shared-auth that exchanges session cookies for JWT tokens - Add /api/v1/auth/session-to-token endpoint to mana-core-auth service - Update all 15 web apps to try SSO during auth initialization SSO Flow: 1. User logs in on any app (e.g., calendar.mana.how) 2. Session cookie is set with Domain=.mana.how 3. When visiting another app (e.g., todo.mana.how), it checks for local tokens first 4. If no local tokens, tries SSO via session cookie 5. Session cookie is exchanged for JWT tokens via new endpoint 6. User is automatically authenticated Apps updated: calendar, chat, clock, contacts, manacore, manadeck, nutriphi, picture, planta, presi, questions, skilltree, storage, todo, zitare Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
352070fb2f
commit
feaf27dd14
19 changed files with 491 additions and 16 deletions
|
|
@ -76,6 +76,7 @@ export const authStore = {
|
|||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
* Also tries SSO if no local tokens exist (cross-domain authentication)
|
||||
*/
|
||||
async initialize() {
|
||||
if (initialized) return;
|
||||
|
|
@ -89,7 +90,19 @@ export const authStore = {
|
|||
|
||||
loading = true;
|
||||
try {
|
||||
const authenticated = await authService.isAuthenticated();
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ export const authStore = {
|
|||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
* Also tries SSO if no local tokens exist (cross-domain authentication)
|
||||
*/
|
||||
async initialize() {
|
||||
if (initialized) return;
|
||||
|
|
@ -89,7 +90,19 @@ export const authStore = {
|
|||
|
||||
loading = true;
|
||||
try {
|
||||
const authenticated = await authService.isAuthenticated();
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ export const authStore = {
|
|||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
* Also tries SSO if no local tokens exist (cross-domain authentication)
|
||||
*/
|
||||
async initialize() {
|
||||
if (initialized) return;
|
||||
|
|
@ -88,7 +89,19 @@ export const authStore = {
|
|||
|
||||
loading = true;
|
||||
try {
|
||||
const authenticated = await authService.isAuthenticated();
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ export const authStore = {
|
|||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
* Also tries SSO if no local tokens exist (cross-domain authentication)
|
||||
*/
|
||||
async initialize() {
|
||||
if (initialized) return;
|
||||
|
|
@ -89,7 +90,19 @@ export const authStore = {
|
|||
|
||||
loading = true;
|
||||
try {
|
||||
const authenticated = await authService.isAuthenticated();
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ export const authStore = {
|
|||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
* Also tries SSO if no local tokens exist (cross-domain authentication)
|
||||
*/
|
||||
async initialize() {
|
||||
if (initialized) return;
|
||||
|
|
@ -76,7 +77,19 @@ export const authStore = {
|
|||
|
||||
loading = true;
|
||||
try {
|
||||
const authenticated = await authService.isAuthenticated();
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
|
|
|||
|
|
@ -32,11 +32,24 @@ export const authStore = {
|
|||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
* Also tries SSO if no local tokens exist (cross-domain authentication)
|
||||
*/
|
||||
async initialize() {
|
||||
loading = true;
|
||||
try {
|
||||
const isAuth = await authService.isAuthenticated();
|
||||
// First, check if we have valid local tokens
|
||||
let isAuth = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!isAuth) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
isAuth = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isAuth) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = toManaUser(userData);
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ export const authStore = {
|
|||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
* Also tries SSO if no local tokens exist (cross-domain authentication)
|
||||
*/
|
||||
async initialize() {
|
||||
if (initialized) return;
|
||||
|
|
@ -76,7 +77,19 @@ export const authStore = {
|
|||
|
||||
loading = true;
|
||||
try {
|
||||
const authenticated = await authService.isAuthenticated();
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
|
|
|||
|
|
@ -77,8 +77,23 @@ export const authStore = {
|
|||
try {
|
||||
const authService = await getAuthService();
|
||||
if (authService) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Auth initialization error:', error);
|
||||
|
|
|
|||
|
|
@ -69,6 +69,10 @@ export const authStore = {
|
|||
return initialized;
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
* Also tries SSO if no local tokens exist (cross-domain authentication)
|
||||
*/
|
||||
async initialize() {
|
||||
if (initialized) return;
|
||||
|
||||
|
|
@ -81,7 +85,19 @@ export const authStore = {
|
|||
|
||||
loading = true;
|
||||
try {
|
||||
const authenticated = await authService.isAuthenticated();
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ export const auth = {
|
|||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
* Also tries SSO if no local tokens exist (cross-domain authentication)
|
||||
*/
|
||||
async init() {
|
||||
if (initialized) return;
|
||||
|
|
@ -60,7 +61,19 @@ export const auth = {
|
|||
|
||||
loading = true;
|
||||
try {
|
||||
const authenticated = await authService.isAuthenticated();
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,10 @@ export const authStore = {
|
|||
return initialized;
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
* Also tries SSO if no local tokens exist (cross-domain authentication)
|
||||
*/
|
||||
async initialize() {
|
||||
if (initialized) return;
|
||||
|
||||
|
|
@ -77,7 +81,19 @@ export const authStore = {
|
|||
|
||||
loading = true;
|
||||
try {
|
||||
const authenticated = await authService.isAuthenticated();
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
|
|
|||
|
|
@ -70,6 +70,10 @@ export const authStore = {
|
|||
return initialized;
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
* Also tries SSO if no local tokens exist (cross-domain authentication)
|
||||
*/
|
||||
async initialize() {
|
||||
if (initialized) return;
|
||||
|
||||
|
|
@ -82,7 +86,19 @@ export const authStore = {
|
|||
|
||||
loading = true;
|
||||
try {
|
||||
const authenticated = await authService.isAuthenticated();
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@ export const authStore = {
|
|||
return initialized;
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
* Also tries SSO if no local tokens exist (cross-domain authentication)
|
||||
*/
|
||||
async initialize() {
|
||||
if (initialized) return;
|
||||
|
||||
|
|
@ -51,7 +55,19 @@ export const authStore = {
|
|||
|
||||
loading = true;
|
||||
try {
|
||||
const authenticated = await authService.isAuthenticated();
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ export const authStore = {
|
|||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
* Also tries SSO if no local tokens exist (cross-domain authentication)
|
||||
*/
|
||||
async initialize() {
|
||||
if (initialized) return;
|
||||
|
|
@ -96,7 +97,19 @@ export const authStore = {
|
|||
|
||||
loading = true;
|
||||
try {
|
||||
const authenticated = await authService.isAuthenticated();
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ export const authStore = {
|
|||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
* Also tries SSO if no local tokens exist (cross-domain authentication)
|
||||
*/
|
||||
async initialize() {
|
||||
if (initialized) return;
|
||||
|
|
@ -89,7 +90,19 @@ export const authStore = {
|
|||
|
||||
loading = true;
|
||||
try {
|
||||
const authenticated = await authService.isAuthenticated();
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue