# Description of Changes
When password login is disabled UI changes to have central style SSO
button

<img width="2057" height="1369" alt="image"
src="https://github.com/user-attachments/assets/8f65f778-0809-4c54-a9c4-acf3a67cfa63"
/>

Auto SSO login functionality

Massively increases auth debugging visibility: verbose console logging
in ErrorBoundary, AuthProvider, Landing, AuthCallback.

Improves OAuth/SAML testability: adds Keycloak docker-compose setups +
realm JSON exports + start/validate scripts for OAuth and SAML
environments.

Hardens license upload path handling: better logs + safer directory
traversal protection by normalizing absolute paths before startsWith
check.

UI polish for SSO-only login: new “single provider” centered layout +
updated button styles (pill buttons, variants, icon wrapper, arrow).


<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing)
for more details.
This commit is contained in:
Anthony Stirling
2026-02-05 12:26:41 +00:00
committed by GitHub
parent a844c7d09e
commit 00136f9e20
22 changed files with 1951 additions and 88 deletions
@@ -22,7 +22,43 @@ export default class ErrorBoundary extends React.Component<ErrorBoundaryProps, E
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
console.error('ErrorBoundary caught an error:', error, errorInfo);
// Enhanced logging for diagnosis
console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.error('🔴 ErrorBoundary caught an error');
console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.error('Error:', error);
console.error('Error name:', error.name);
console.error('Error message:', error.message);
console.error('Error stack:', error.stack);
console.error('Component stack:', errorInfo.componentStack);
console.error('Current URL:', window.location.href);
console.error('Current pathname:', window.location.pathname);
console.error('Current hash:', window.location.hash);
console.error('Current search:', window.location.search);
console.error('Timestamp:', new Date().toISOString());
console.error('User agent:', navigator.userAgent);
// Check for React error codes
if (error.message.includes('Minified React error')) {
const errorCodeMatch = error.message.match(/#(\d+)/);
if (errorCodeMatch) {
const errorCode = errorCodeMatch[1];
console.error(`React Error #${errorCode}: https://react.dev/errors/${errorCode}`);
}
}
// Check localStorage for auth state
try {
const jwt = localStorage.getItem('stirling_jwt');
console.error('Auth state:', {
hasJWT: !!jwt,
jwtLength: jwt?.length || 0,
});
} catch (e) {
console.error('Could not check localStorage:', e);
}
console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
}
retry = () => {
@@ -37,14 +73,33 @@ export default class ErrorBoundary extends React.Component<ErrorBoundaryProps, E
}
return (
<Stack align="center" justify="center" style={{ minHeight: '200px', padding: '2rem' }}>
<Stack align="center" justify="center" style={{ minHeight: '200px', padding: '2rem', maxWidth: '800px', margin: '0 auto' }}>
<Text size="lg" fw={500} c="red">Something went wrong</Text>
{process.env.NODE_ENV === 'development' && this.state.error && (
<Text size="sm" c="dimmed" style={{ textAlign: 'center', fontFamily: 'monospace' }}>
{this.state.error.message}
</Text>
<>
<Text size="sm" c="dimmed" style={{ textAlign: 'center', fontFamily: 'monospace', marginTop: '1rem' }}>
{this.state.error.message}
</Text>
{this.state.error.stack && (
<details style={{ marginTop: '1rem', width: '100%' }}>
<summary style={{ cursor: 'pointer', marginBottom: '0.5rem' }}>
<Text size="sm" component="span">Show stack trace</Text>
</summary>
<pre style={{
fontSize: '0.75rem',
overflow: 'auto',
backgroundColor: '#f5f5f5',
padding: '1rem',
borderRadius: '4px',
maxHeight: '300px'
}}>
{this.state.error.stack}
</pre>
</details>
)}
</>
)}
<Button onClick={this.retry} variant="light">
<Button onClick={this.retry} variant="light" mt="md">
Try Again
</Button>
</Stack>
@@ -12,6 +12,9 @@ interface AccountLogoutDeps {
export function useAccountLogout() {
return async ({ signOut, redirectToLogin }: AccountLogoutDeps): Promise<void> => {
try {
if (typeof window !== 'undefined') {
window.sessionStorage.setItem('stirling_sso_auto_login_logged_out', '1');
}
await signOut();
} finally {
redirectToLogin();
@@ -15,6 +15,7 @@ export interface LoginPageData {
showDefaultCredentials: boolean;
firstTimeSetup: boolean;
enableLogin: boolean;
ssoAutoLogin?: boolean;
}
/**