mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-08-02 13:48:15 +02:00
wip - /view-pdf not loading properly
This commit is contained in:
parent
6a7328ff3d
commit
017b737b72
@ -9,7 +9,9 @@
|
|||||||
"Bash(find:*)",
|
"Bash(find:*)",
|
||||||
"Bash(grep:*)",
|
"Bash(grep:*)",
|
||||||
"Bash(rg:*)",
|
"Bash(rg:*)",
|
||||||
"Bash(strings:*)"
|
"Bash(strings:*)",
|
||||||
|
"Bash(pkill:*)",
|
||||||
|
"Bash(true)"
|
||||||
],
|
],
|
||||||
"deny": []
|
"deny": []
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ security:
|
|||||||
google:
|
google:
|
||||||
clientId: '' # client ID for Google OAuth2
|
clientId: '' # client ID for Google OAuth2
|
||||||
clientSecret: '' # client secret for Google OAuth2
|
clientSecret: '' # client secret for Google OAuth2
|
||||||
scopes: email, profile # scopes for Google OAuth2
|
scopes: https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile # scopes for Google OAuth2
|
||||||
useAsUsername: email # field to use as the username for Google OAuth2. Available options are: [email | name | given_name | family_name]
|
useAsUsername: email # field to use as the username for Google OAuth2. Available options are: [email | name | given_name | family_name]
|
||||||
github:
|
github:
|
||||||
clientId: '' # client ID for GitHub OAuth2
|
clientId: '' # client ID for GitHub OAuth2
|
||||||
@ -51,20 +51,20 @@ security:
|
|||||||
provider: '' # The name of your Provider
|
provider: '' # The name of your Provider
|
||||||
autoCreateUser: true # set to 'true' to allow auto-creation of non-existing users
|
autoCreateUser: true # set to 'true' to allow auto-creation of non-existing users
|
||||||
blockRegistration: false # set to 'true' to deny login with SSO without prior registration by an admin
|
blockRegistration: false # set to 'true' to deny login with SSO without prior registration by an admin
|
||||||
registrationId: stirling # The name of your Service Provider (SP) app name. Should match the name in the path for your SSO & SLO URLs
|
registrationId: stirlingpdf-dario-saml # The name of your Service Provider (SP) app name. Should match the name in the path for your SSO & SLO URLs
|
||||||
idpMetadataUri: https://dev-XXXXXXXX.okta.com/app/externalKey/sso/saml/metadata # The uri for your Provider's metadata
|
idpMetadataUri: https://authentik.dev.stirlingpdf.com/api/v3/providers/saml/5/metadata/ # The uri for your Provider's metadata
|
||||||
idpSingleLoginUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/sso/saml # The URL for initiating SSO. Provided by your Provider
|
idpSingleLoginUrl: https://authentik.dev.stirlingpdf.com/application/saml/stirlingpdf-dario-saml/sso/binding/post/ # The URL for initiating SSO. Provided by your Provider
|
||||||
idpSingleLogoutUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/slo/saml # The URL for initiating SLO. Provided by your Provider
|
idpSingleLogoutUrl: https://authentik.dev.stirlingpdf.com/application/saml/stirlingpdf-dario-saml/slo/binding/post/ # The URL for initiating SLO. Provided by your Provider
|
||||||
idpIssuer: '' # The ID of your Provider
|
idpIssuer: authentik # The ID of your Provider
|
||||||
idpCert: classpath:okta.cert # The certificate your Provider will use to authenticate your app's SAML authentication requests. Provided by your Provider
|
idpCert: classpath:authentik-Self-signed_Certificate_certificate.pem # The certificate your Provider will use to authenticate your app's SAML authentication requests. Provided by your Provider
|
||||||
privateKey: classpath:saml-private-key.key # Your private key. Generated from your keypair
|
privateKey: classpath:private_key.key # Your private key. Generated from your keypair
|
||||||
spCert: classpath:saml-public-cert.crt # Your signing certificate. Generated from your keypair
|
spCert: classpath:certificate.crt # Your signing certificate. Generated from your keypair
|
||||||
jwt:
|
jwt:
|
||||||
enableKeyStore: true # Set to 'true' to enable JWT key store
|
enableKeyStore: true # Set to 'true' to enable JWT key store
|
||||||
enableKeyRotation: true # Set to 'true' to enable JWT key rotation
|
enableKeyRotation: true # Set to 'true' to enable JWT key rotation
|
||||||
|
|
||||||
premium:
|
premium:
|
||||||
key: 00000000-0000-0000-0000-000000000000
|
key: 3R3T-WFPY-UNRW-LJFA-MMXM-YVJK-WCKY-PCRT # fixme: remove
|
||||||
enabled: false # Enable license key checks for pro/enterprise features
|
enabled: false # Enable license key checks for pro/enterprise features
|
||||||
proFeatures:
|
proFeatures:
|
||||||
SSOAutoLogin: false
|
SSOAutoLogin: false
|
||||||
|
@ -135,7 +135,7 @@ public class SecurityConfiguration {
|
|||||||
boolean v2Enabled = appConfig.v2Enabled();
|
boolean v2Enabled = appConfig.v2Enabled();
|
||||||
|
|
||||||
if (v2Enabled) {
|
if (v2Enabled) {
|
||||||
http.addFilterAt(
|
http.addFilterBefore(
|
||||||
jwtAuthenticationFilter(),
|
jwtAuthenticationFilter(),
|
||||||
UsernamePasswordAuthenticationFilter.class)
|
UsernamePasswordAuthenticationFilter.class)
|
||||||
.exceptionHandling(
|
.exceptionHandling(
|
||||||
@ -145,8 +145,8 @@ public class SecurityConfiguration {
|
|||||||
}
|
}
|
||||||
http.addFilterBefore(
|
http.addFilterBefore(
|
||||||
userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
|
userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
|
||||||
.addFilterAfter(rateLimitingFilter(), userAuthenticationFilter.getClass())
|
.addFilterAfter(rateLimitingFilter(), UserAuthenticationFilter.class)
|
||||||
.addFilterAfter(firstLoginFilter, rateLimitingFilter().getClass());
|
.addFilterAfter(firstLoginFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
|
|
||||||
if (!securityProperties.getCsrfDisabled()) {
|
if (!securityProperties.getCsrfDisabled()) {
|
||||||
CookieCsrfTokenRepository cookieRepo =
|
CookieCsrfTokenRepository cookieRepo =
|
||||||
|
@ -88,6 +88,8 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
try {
|
try {
|
||||||
jwtService.validateToken(jwtToken);
|
jwtService.validateToken(jwtToken);
|
||||||
} catch (AuthenticationFailureException e) {
|
} catch (AuthenticationFailureException e) {
|
||||||
|
// Clear invalid tokens from response
|
||||||
|
jwtService.clearTokenFromResponse(response);
|
||||||
handleAuthenticationFailure(request, response, e);
|
handleAuthenticationFailure(request, response, e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -129,7 +131,9 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||||
SecurityContextHolder.getContext().setAuthentication(authToken);
|
SecurityContextHolder.getContext().setAuthentication(authToken);
|
||||||
|
|
||||||
log.debug("JWT authentication successful for user: {}", username);
|
log.info(
|
||||||
|
"JWT authentication successful for user: {} - Authentication set in SecurityContext",
|
||||||
|
username);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new UsernameNotFoundException("User not found: " + username);
|
throw new UsernameNotFoundException("User not found: " + username);
|
||||||
|
@ -63,7 +63,15 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String requestURI = request.getRequestURI();
|
String requestURI = request.getRequestURI();
|
||||||
|
|
||||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
log.info(
|
||||||
|
"UserAuthenticationFilter - Authentication from SecurityContext: {}",
|
||||||
|
authentication != null
|
||||||
|
? authentication.getClass().getSimpleName()
|
||||||
|
+ " for "
|
||||||
|
+ authentication.getName()
|
||||||
|
: "null");
|
||||||
|
|
||||||
// Check for session expiration (unsure if needed)
|
// Check for session expiration (unsure if needed)
|
||||||
// if (authentication != null && authentication.isAuthenticated()) {
|
// if (authentication != null && authentication.isAuthenticated()) {
|
||||||
@ -218,4 +226,37 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean shouldNotFilter(HttpServletRequest request) {
|
||||||
|
String uri = request.getRequestURI();
|
||||||
|
String contextPath = request.getContextPath();
|
||||||
|
String[] permitAllPatterns = {
|
||||||
|
contextPath + "/login",
|
||||||
|
contextPath + "/signup",
|
||||||
|
contextPath + "/register",
|
||||||
|
contextPath + "/error",
|
||||||
|
contextPath + "/images/",
|
||||||
|
contextPath + "/public/",
|
||||||
|
contextPath + "/css/",
|
||||||
|
contextPath + "/fonts/",
|
||||||
|
contextPath + "/js/",
|
||||||
|
contextPath + "/pdfjs/",
|
||||||
|
contextPath + "/pdfjs-legacy/",
|
||||||
|
contextPath + "/api/v1/info/status",
|
||||||
|
contextPath + "/site.webmanifest"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (String pattern : permitAllPatterns) {
|
||||||
|
if (uri.startsWith(pattern)
|
||||||
|
|| uri.endsWith(".svg")
|
||||||
|
|| uri.endsWith(".mjs")
|
||||||
|
|| uri.endsWith(".png")
|
||||||
|
|| uri.endsWith(".ico")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ public class JwtKeystoreService implements JwtKeystoreServiceInterface {
|
|||||||
|
|
||||||
public static final String KEY_SUFFIX = ".key";
|
public static final String KEY_SUFFIX = ".key";
|
||||||
private final JwtSigningKeyRepository repository;
|
private final JwtSigningKeyRepository repository;
|
||||||
private final ApplicationProperties.Security.Jwt jwtConfig;
|
private final ApplicationProperties.Security.Jwt jwtProperties;
|
||||||
private final Path privateKeyDirectory;
|
private final Path privateKeyDirectory;
|
||||||
|
|
||||||
private volatile KeyPair currentKeyPair;
|
private volatile KeyPair currentKeyPair;
|
||||||
@ -47,7 +47,7 @@ public class JwtKeystoreService implements JwtKeystoreServiceInterface {
|
|||||||
public JwtKeystoreService(
|
public JwtKeystoreService(
|
||||||
JwtSigningKeyRepository repository, ApplicationProperties applicationProperties) {
|
JwtSigningKeyRepository repository, ApplicationProperties applicationProperties) {
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
this.jwtConfig = applicationProperties.getSecurity().getJwt();
|
this.jwtProperties = applicationProperties.getSecurity().getJwt();
|
||||||
this.privateKeyDirectory = Paths.get(InstallationPathConfig.getConfigPath(), "jwt-keys");
|
this.privateKeyDirectory = Paths.get(InstallationPathConfig.getConfigPath(), "jwt-keys");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ public class JwtKeystoreService implements JwtKeystoreServiceInterface {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isKeystoreEnabled() {
|
public boolean isKeystoreEnabled() {
|
||||||
return jwtConfig.isEnableKeystore();
|
return jwtProperties.isEnableKeystore();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadOrGenerateKeypair() {
|
private void loadOrGenerateKeypair() {
|
||||||
|
@ -82,7 +82,6 @@ public class JwtService implements JwtServiceInterface {
|
|||||||
.expiration(new Date(System.currentTimeMillis() + EXPIRATION))
|
.expiration(new Date(System.currentTimeMillis() + EXPIRATION))
|
||||||
.signWith(keyPair.getPrivate(), Jwts.SIG.RS256);
|
.signWith(keyPair.getPrivate(), Jwts.SIG.RS256);
|
||||||
|
|
||||||
// Add key ID to header if keystore is enabled
|
|
||||||
String keyId = keystoreService.getActiveKeyId();
|
String keyId = keystoreService.getActiveKeyId();
|
||||||
if (keyId != null) {
|
if (keyId != null) {
|
||||||
builder.header().keyId(keyId);
|
builder.header().keyId(keyId);
|
||||||
@ -136,8 +135,11 @@ public class JwtService implements JwtServiceInterface {
|
|||||||
if (specificKeyPair.isPresent()) {
|
if (specificKeyPair.isPresent()) {
|
||||||
keyPair = specificKeyPair.get();
|
keyPair = specificKeyPair.get();
|
||||||
} else {
|
} else {
|
||||||
log.warn("Key ID {} not found in keystore, using active keypair", keyId);
|
log.warn(
|
||||||
keyPair = keystoreService.getActiveKeypair();
|
"Key ID {} not found in keystore, token may have been signed with a rotated key",
|
||||||
|
keyId);
|
||||||
|
throw new AuthenticationFailureException(
|
||||||
|
"JWT token signed with unknown key ID: " + keyId);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
keyPair = keystoreService.getActiveKeypair();
|
keyPair = keystoreService.getActiveKeypair();
|
||||||
@ -233,7 +235,7 @@ public class JwtService implements JwtServiceInterface {
|
|||||||
.getHeader()
|
.getHeader()
|
||||||
.get("kid");
|
.get("kid");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// Token might not have a key ID or be malformed
|
log.debug("Failed to extract key ID from token header: {}", e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user