From 650ca27da528b15ae063271d87b3f02a07fcc0ba Mon Sep 17 00:00:00 2001 From: Gabriel Gutierrez Date: Thu, 10 Feb 2022 12:19:03 +0100 Subject: [PATCH 1/3] Added CSRF Session Storage config properties and html transformer --- .../core/SwaggerUiConfigProperties.java | 46 +++++++++++++++++++ .../ui/AbstractSwaggerIndexTransformer.java | 26 +++++++++++ 2 files changed, 72 insertions(+) diff --git a/springdoc-openapi-common/src/main/java/org/springdoc/core/SwaggerUiConfigProperties.java b/springdoc-openapi-common/src/main/java/org/springdoc/core/SwaggerUiConfigProperties.java index ce7bd3bb2..bd91a92b5 100644 --- a/springdoc-openapi-common/src/main/java/org/springdoc/core/SwaggerUiConfigProperties.java +++ b/springdoc-openapi-common/src/main/java/org/springdoc/core/SwaggerUiConfigProperties.java @@ -145,6 +145,11 @@ public static class Csrf { */ private boolean useLocalStorage; + /** + * Use Session storage. + */ + private boolean useSessionStorage; + /** * The Cookie name. */ @@ -155,6 +160,11 @@ public static class Csrf { */ private String localStorageKey = Constants.CSRF_DEFAULT_LOCAL_STORAGE_KEY; + /** + * The Session storage key. + */ + private String sessionStorageKey = Constants.CSRF_DEFAULT_LOCAL_STORAGE_KEY; + /** * The Header name. */ @@ -187,6 +197,15 @@ public boolean isUseLocalStorage() { return useLocalStorage; } + /** + * Use Session storage boolean. + * + * @return the boolean + */ + public boolean isUseSessionStorage() { + return useSessionStorage; + } + /** * Sets useLocalStorage. * @@ -196,6 +215,15 @@ public void setUseLocalStorage(boolean useLocalStorage) { this.useLocalStorage = useLocalStorage; } + /** + * Sets useSessionStorage. + * + * @param useSessionStorage the use local storage + */ + public void setUseSessionStorage(boolean useSessionStorage) { + this.useSessionStorage = useSessionStorage; + } + /** * Gets cookie name. * @@ -223,6 +251,15 @@ public String getLocalStorageKey() { return localStorageKey; } + /** + * Gets session storage key. + * + * @return the cookie name + */ + public String getSessionStorageKey() { + return sessionStorageKey; + } + /** * Sets local storage key. * @@ -232,6 +269,15 @@ public void setLocalStorageKey(String localStorageKey) { this.localStorageKey = localStorageKey; } + /** + * Sets local storage key. + * + * @param sessionStorageKey the local storage key + */ + public void setSessionStorageKey(String sessionStorageKey) { + this.sessionStorageKey = sessionStorageKey; + } + /** * Gets header name. * diff --git a/springdoc-openapi-common/src/main/java/org/springdoc/ui/AbstractSwaggerIndexTransformer.java b/springdoc-openapi-common/src/main/java/org/springdoc/ui/AbstractSwaggerIndexTransformer.java index fb399e715..c31ab8797 100644 --- a/springdoc-openapi-common/src/main/java/org/springdoc/ui/AbstractSwaggerIndexTransformer.java +++ b/springdoc-openapi-common/src/main/java/org/springdoc/ui/AbstractSwaggerIndexTransformer.java @@ -145,6 +145,8 @@ protected String defaultTransformations(InputStream inputStream) throws IOExcept if (swaggerUiConfig.isCsrfEnabled()) { if (swaggerUiConfig.getCsrf().isUseLocalStorage()) html = addCSRFLocalStorage(html); + else if (swaggerUiConfig.getCsrf().isUseSessionStorage()) + html = addCSRFSessionStorage(html); else html = addCSRF(html); } @@ -241,6 +243,30 @@ protected String addCSRFLocalStorage(String html) { return html.replace(PRESETS, stringBuilder.toString()); } + /** + * Add csrf string from Session storage. + * + * @param html the html + * @return the string + */ + protected String addCSRFSessionStorage(String html) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("requestInterceptor: (request) => {\n"); + stringBuilder.append("\t\t\tconst value = window.sessionStorage.getItem('"); + stringBuilder.append(swaggerUiConfig.getCsrf().getSessionStorageKey() + "');\n"); + stringBuilder.append("\t\t\tconst currentURL = new URL(document.URL);\n"); + stringBuilder.append("\t\t\tconst requestURL = new URL(request.url, document.location.origin);\n"); + stringBuilder.append("\t\t\tconst isSameOrigin = (currentURL.protocol === requestURL.protocol && currentURL.host === requestURL.host);\n"); + stringBuilder.append("\t\t\tif (isSameOrigin) "); + stringBuilder.append("request.headers['"); + stringBuilder.append(swaggerUiConfig.getCsrf().getHeaderName()); + stringBuilder.append("'] = value;\n"); + stringBuilder.append("\t\t\treturn request;\n"); + stringBuilder.append("\t\t},\n"); + stringBuilder.append("\t\t" + PRESETS); + return html.replace(PRESETS, stringBuilder.toString()); + } + /** * Add syntax highlight string. * From 8418aa846957b19321c066d468b50747ef671673 Mon Sep 17 00:00:00 2001 From: Gabriel Gutierrez Date: Thu, 10 Feb 2022 15:45:09 +0100 Subject: [PATCH 2/3] Deleted apostrophes/quotation marks from CSRF token header value. This may cause issues with Spring CSRF filter validation --- .../java/org/springdoc/ui/AbstractSwaggerIndexTransformer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/springdoc-openapi-common/src/main/java/org/springdoc/ui/AbstractSwaggerIndexTransformer.java b/springdoc-openapi-common/src/main/java/org/springdoc/ui/AbstractSwaggerIndexTransformer.java index c31ab8797..7bd884135 100644 --- a/springdoc-openapi-common/src/main/java/org/springdoc/ui/AbstractSwaggerIndexTransformer.java +++ b/springdoc-openapi-common/src/main/java/org/springdoc/ui/AbstractSwaggerIndexTransformer.java @@ -260,7 +260,7 @@ protected String addCSRFSessionStorage(String html) { stringBuilder.append("\t\t\tif (isSameOrigin) "); stringBuilder.append("request.headers['"); stringBuilder.append(swaggerUiConfig.getCsrf().getHeaderName()); - stringBuilder.append("'] = value;\n"); + stringBuilder.append("'] = value.replace(/['\"]+/g,'');\n"); stringBuilder.append("\t\t\treturn request;\n"); stringBuilder.append("\t\t},\n"); stringBuilder.append("\t\t" + PRESETS); From e9bab25a2211cfbdb3b3ce4d5e1f40e8110c9bec Mon Sep 17 00:00:00 2001 From: Gabriel Gutierrez Date: Thu, 10 Feb 2022 17:28:20 +0100 Subject: [PATCH 3/3] Fixed addCSRFLocalStorage indentation issue: Some backslashes were missing producing Uncaught SyntaxError: Unexpected token 'const' at index.html --- .../ui/AbstractSwaggerIndexTransformer.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/springdoc-openapi-common/src/main/java/org/springdoc/ui/AbstractSwaggerIndexTransformer.java b/springdoc-openapi-common/src/main/java/org/springdoc/ui/AbstractSwaggerIndexTransformer.java index 7bd884135..c705dfcd0 100644 --- a/springdoc-openapi-common/src/main/java/org/springdoc/ui/AbstractSwaggerIndexTransformer.java +++ b/springdoc-openapi-common/src/main/java/org/springdoc/ui/AbstractSwaggerIndexTransformer.java @@ -228,16 +228,16 @@ protected String addCSRF(String html) { protected String addCSRFLocalStorage(String html) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("requestInterceptor: (request) => {\n"); - stringBuilder.append("t\t\tconst value = window.localStorage.getItem('"); + stringBuilder.append("\t\t\tconst value = window.localStorage.getItem('"); stringBuilder.append(swaggerUiConfig.getCsrf().getLocalStorageKey() + "');\n"); - stringBuilder.append("t\t\tconst currentURL = new URL(document.URL);\n"); - stringBuilder.append("t\t\tconst requestURL = new URL(request.url, document.location.origin);\n"); - stringBuilder.append("t\t\tconst isSameOrigin = (currentURL.protocol === requestURL.protocol && currentURL.host === requestURL.host);\n"); - stringBuilder.append("t\t\tif (isSameOrigin) "); + stringBuilder.append("\t\t\tconst currentURL = new URL(document.URL);\n"); + stringBuilder.append("\t\t\tconst requestURL = new URL(request.url, document.location.origin);\n"); + stringBuilder.append("\t\t\tconst isSameOrigin = (currentURL.protocol === requestURL.protocol && currentURL.host === requestURL.host);\n"); + stringBuilder.append("\t\t\tif (isSameOrigin) "); stringBuilder.append("request.headers['"); stringBuilder.append(swaggerUiConfig.getCsrf().getHeaderName()); stringBuilder.append("'] = value;\n"); - stringBuilder.append("t\t\treturn request;\n"); + stringBuilder.append("\t\t\treturn request;\n"); stringBuilder.append("\t\t},\n"); stringBuilder.append("\t\t" + PRESETS); return html.replace(PRESETS, stringBuilder.toString());