diff --git a/backend/src/main/java/SecurityInit.java b/backend/src/main/java/SecurityInit.java
new file mode 100644
index 00000000..00b8b504
--- /dev/null
+++ b/backend/src/main/java/SecurityInit.java
@@ -0,0 +1,5 @@
+import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
+import org.springframework.web.WebApplicationInitializer;
+
+public class SecurityInit extends AbstractSecurityWebApplicationInitializer implements WebApplicationInitializer {
+}
diff --git a/backend/src/main/java/ru/micord/ervu/security/CsrfTokenAwareLogoutSuccessHandler.java b/backend/src/main/java/ru/micord/ervu/security/CsrfTokenAwareLogoutSuccessHandler.java
new file mode 100644
index 00000000..8c9b1895
--- /dev/null
+++ b/backend/src/main/java/ru/micord/ervu/security/CsrfTokenAwareLogoutSuccessHandler.java
@@ -0,0 +1,34 @@
+package ru.micord.ervu.security;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;
+import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
+import org.springframework.security.web.csrf.CsrfToken;
+import org.springframework.security.web.csrf.CsrfTokenRepository;
+
+public class CsrfTokenAwareLogoutSuccessHandler implements LogoutSuccessHandler {
+
+ private final CsrfTokenRepository csrfTokenRepository;
+
+ private final LogoutSuccessHandler delegate = new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK);
+
+ public CsrfTokenAwareLogoutSuccessHandler(CsrfTokenRepository csrfTokenRepository) {
+ this.csrfTokenRepository = csrfTokenRepository;
+ }
+
+ @Override
+ public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException,
+ ServletException {
+ CsrfToken csrfToken = this.csrfTokenRepository.generateToken(request);
+ this.csrfTokenRepository.saveToken(csrfToken, request, response);
+ this.delegate.onLogoutSuccess(request, response, authentication);
+ }
+
+}
diff --git a/backend/src/main/java/ru/micord/ervu/security/SecurityConfig.java b/backend/src/main/java/ru/micord/ervu/security/SecurityConfig.java
index 44a4223b..6df367d7 100644
--- a/backend/src/main/java/ru/micord/ervu/security/SecurityConfig.java
+++ b/backend/src/main/java/ru/micord/ervu/security/SecurityConfig.java
@@ -10,9 +10,14 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
+import org.springframework.security.web.csrf.CsrfTokenRequestHandler;
+import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler;
import ru.micord.ervu.security.webbpm.jwt.filter.JwtAuthenticationFilter;
import ru.micord.ervu.security.webbpm.jwt.UnauthorizedEntryPoint;
+import static ru.micord.ervu.security.SecurityConstants.ESIA_LOGOUT;
+
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@@ -22,19 +27,31 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
-
httpConfigure(http);
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
protected void httpConfigure(HttpSecurity httpSecurity) throws Exception {
- String[] permitAll = {"/esia/url", "/esia/auth", "esia/refresh"};
-
+ String[] permitAll = {"/version","/esia/url", "/esia/auth", "esia/refresh"};
+ CookieCsrfTokenRepository tokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
+ tokenRepository.setCookiePath("/");
+ XorCsrfTokenRequestAttributeHandler delegate = new XorCsrfTokenRequestAttributeHandler();
+ delegate.setCsrfRequestAttributeName(null);
+ // Use only the handle() method of XorCsrfTokenRequestAttributeHandler and the
+ // default implementation of resolveCsrfTokenValue() from CsrfTokenRequestHandler
+ CsrfTokenRequestHandler requestHandler = delegate::handle;
httpSecurity.authorizeRequests()
.antMatchers(permitAll).permitAll()
.antMatchers("/**").authenticated()
.and()
- .csrf().disable()
+ .csrf((csrf) -> csrf
+ .csrfTokenRepository(tokenRepository)
+ .csrfTokenRequestHandler(requestHandler)
+ )
+ .logout((logout) -> logout
+ .logoutUrl(ESIA_LOGOUT)
+ .logoutSuccessHandler(new CsrfTokenAwareLogoutSuccessHandler(tokenRepository))
+ )
.exceptionHandling().authenticationEntryPoint(entryPoint())
.and()
.sessionManagement()
diff --git a/backend/src/main/java/ru/micord/ervu/security/SecurityConstants.java b/backend/src/main/java/ru/micord/ervu/security/SecurityConstants.java
new file mode 100644
index 00000000..1853716d
--- /dev/null
+++ b/backend/src/main/java/ru/micord/ervu/security/SecurityConstants.java
@@ -0,0 +1,5 @@
+package ru.micord.ervu.security;
+
+public class SecurityConstants {
+ public static final String ESIA_LOGOUT = "/esia/logout";
+}
diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/controller/EsiaController.java b/backend/src/main/java/ru/micord/ervu/security/esia/controller/EsiaController.java
index d408ff4d..42aecf09 100644
--- a/backend/src/main/java/ru/micord/ervu/security/esia/controller/EsiaController.java
+++ b/backend/src/main/java/ru/micord/ervu/security/esia/controller/EsiaController.java
@@ -3,12 +3,13 @@ package ru.micord.ervu.security.esia.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import ru.micord.ervu.security.SecurityConstants;
import ru.micord.ervu.security.esia.model.OrgInfoModel;
import ru.micord.ervu.security.esia.service.EsiaAuthService;
import ru.micord.ervu.security.esia.service.EsiaDataService;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@@ -24,37 +25,37 @@ public class EsiaController {
@Autowired
private EsiaDataService esiaDataService;
- @RequestMapping(value = "/esia/url")
+ @GetMapping(value = "/esia/url")
public String getEsiaUrl() {
return esiaAuthService.generateAuthCodeUrl();
}
- @RequestMapping(value = "/esia/auth", params = "code", method = RequestMethod.GET)
+ @GetMapping(value = "/esia/auth", params = "code")
public boolean esiaAuth(@RequestParam("code") String code, HttpServletRequest request, HttpServletResponse response) {
return esiaAuthService.getEsiaTokensByCode(code, request, response);
}
- @RequestMapping(value = "/esia/refresh")
+ @PostMapping(value = "/esia/refresh")
public void refreshToken(HttpServletRequest request, HttpServletResponse response) {
esiaAuthService.getEsiaTokensByRefreshToken(request, response);
}
- @RequestMapping(value = "/esia/org")
+ @GetMapping(value = "/esia/org")
public OrgInfoModel getOrgInfo(HttpServletRequest request) {
return esiaDataService.getOrgInfo(request);
}
- @RequestMapping(value = "/esia/userfullname")
+ @GetMapping(value = "/esia/userfullname")
public String getUserFullname(HttpServletRequest request) {
return esiaDataService.getUserFullname(request);
}
- @RequestMapping(value = "/esia/orgunitname")
+ @GetMapping(value = "/esia/orgunitname")
public String getOrgUnitName(HttpServletRequest request) {
return esiaDataService.getOrgUnitName(request);
}
- @RequestMapping(value = "/esia/logout")
+ @PostMapping(SecurityConstants.ESIA_LOGOUT)
public String logout(HttpServletRequest request, HttpServletResponse response) {
return esiaAuthService.logout(request, response);
}
diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java b/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java
index a0170d61..e035a42a 100644
--- a/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java
+++ b/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java
@@ -200,11 +200,19 @@ public class EsiaAuthService {
.build()
.send(postReq, HttpResponse.BodyHandlers.ofString());
String responseString = postResp.body();
- EsiaTokenResponse tokenResponse = objectMapper.readValue(responseString, EsiaTokenResponse.class);
- if (tokenResponse != null && tokenResponse.getError() != null) {
+ EsiaTokenResponse tokenResponse = objectMapper.readValue(responseString,
+ EsiaTokenResponse.class
+ );
+
+ if (tokenResponse == null) {
+ throw new IllegalStateException("Got empty esia response");
+ }
+
+ if (tokenResponse.getError() != null) {
throw new RuntimeException(tokenResponse.getError_description());
}
String accessToken = tokenResponse.getAccess_token();
+
boolean hasRole = ulDataService.checkRole(accessToken);
if (!hasRole) {
throw new RuntimeException("The user does not have the required role");
diff --git a/frontend/src/resources/template/app/component/log_out.html b/frontend/src/resources/template/app/component/log_out.html
index cf7831d2..319b0904 100644
--- a/frontend/src/resources/template/app/component/log_out.html
+++ b/frontend/src/resources/template/app/component/log_out.html
@@ -1,6 +1,6 @@
-
-
+
+
\ No newline at end of file
+
diff --git a/frontend/src/ts/ervu/component/fileupload/ErvuFileUpload.ts b/frontend/src/ts/ervu/component/fileupload/ErvuFileUpload.ts
index 3e0da6a8..4ed140be 100644
--- a/frontend/src/ts/ervu/component/fileupload/ErvuFileUpload.ts
+++ b/frontend/src/ts/ervu/component/fileupload/ErvuFileUpload.ts
@@ -11,6 +11,8 @@ import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef} from
import {FileItem, FileUploader} from "ng2-file-upload";
import {FileLikeObject} from "ng2-file-upload/file-upload/file-like-object.class";
import {EmployeeInfoFileFormType} from "./EmployeeInfoFileFormType";
+import {CookieService} from "ngx-cookie";
+import {TokenConstants} from "../../../modules/security/TokenConstants";
@Component({
moduleId: module.id,
@@ -59,6 +61,7 @@ export class ErvuFileUpload extends InputControl {
private messagesService: MessagesService;
private isUploadErrorOccurred = false;
private appConfigService: AppConfigService;
+ private cookieService: CookieService;
constructor(el: ElementRef, cd: ChangeDetectorRef) {
super(el, cd);
@@ -69,6 +72,7 @@ export class ErvuFileUpload extends InputControl {
super.initialize();
this.messagesService = this.injector.get(MessagesService);
this.appConfigService = this.injector.get(AppConfigService);
+ this.cookieService = this.injector.get(CookieService);
this.url = `/${this.appConfigService.getParamValue(ErvuFileUpload.BACKEND_URL)}/employee/document`;
this.uploader.setOptions({
@@ -99,6 +103,10 @@ export class ErvuFileUpload extends InputControl {
{
name: "Client-Time-Zone",
value: Intl.DateTimeFormat().resolvedOptions().timeZone
+ },
+ {
+ name: TokenConstants.CSRF_HEADER_NAME,
+ value: this.cookieService.get(TokenConstants.CSRF_TOKEN_NAME)
}
]
});
@@ -129,6 +137,24 @@ export class ErvuFileUpload extends InputControl {
private setUploaderMethods() {
this.uploader.onBeforeUploadItem = (fileItem: FileItem) => {
+
+ //refresh headers
+ this.uploader.setOptions({
+ headers: [
+ {
+ name: "X-Employee-Info-File-Form-Type",
+ value: EmployeeInfoFileFormType[this.formType]
+ },
+ {
+ name: "Client-Time-Zone",
+ value: Intl.DateTimeFormat().resolvedOptions().timeZone
+ },
+ {
+ name: TokenConstants.CSRF_HEADER_NAME,
+ value: this.cookieService.get(TokenConstants.CSRF_TOKEN_NAME)
+ }
+ ]
+ });
this.fileUploadStartEvent.trigger();
this.isDropZoneVisible = false;
this.isFilesListVisible = false;
@@ -239,4 +265,4 @@ export class ErvuFileUpload extends InputControl {
this.isUploadErrorOccurred = false;
this.cd.markForCheck();
}
-}
\ No newline at end of file
+}
diff --git a/frontend/src/ts/esia/OrgDataRoot.ts b/frontend/src/ts/esia/OrgDataRoot.ts
index feee9eb9..901362ed 100644
--- a/frontend/src/ts/esia/OrgDataRoot.ts
+++ b/frontend/src/ts/esia/OrgDataRoot.ts
@@ -2,10 +2,10 @@ import {AnalyticalScope, Behavior, Container, ControlWithValue} from "@webbpm/ba
import {HttpClient} from "@angular/common/http";
import {OrgData} from "./OrgData";
import {OrgInfoModel} from "../generated/ru/micord/ervu/security/esia/model/OrgInfoModel";
-import {CookieService} from "ngx-cookie";
+import {AuthenticationService} from "../modules/security/authentication.service";
@AnalyticalScope(Container)
-export class OrgDataRoot extends Behavior{
+export class OrgDataRoot extends Behavior {
private container: Container;
@@ -14,8 +14,9 @@ export class OrgDataRoot extends Behavior{
this.container = this.getScript(Container);
let orgScripts: OrgData[] = this.container.getScriptsInThisAndChildren(OrgData);
let httpClient = this.injector.get(HttpClient);
- let cookieService = this.injector.get(CookieService);
- if (cookieService.get("webbpm.ervu-lkrp-ul")) {
+ let cookieService = this.injector.get(AuthenticationService);
+
+ if (cookieService.isAuthenticated()) {
httpClient.get("esia/org")
.toPromise()
.then(orgInfoModel => {
@@ -23,9 +24,9 @@ export class OrgDataRoot extends Behavior{
return;
}
for (let orgData of orgScripts) {
- let control: ControlWithValue = orgData.getScriptInObject(orgData.getObjectId(),
- 'component.ControlWithValue');
- control.setValue(orgInfoModel[orgData.dataId]);
+ let control: ControlWithValue = orgData.getScriptInObject(orgData.getObjectId(),
+ 'component.ControlWithValue');
+ control.setValue(orgInfoModel[orgData.dataId]);
}
});
}
diff --git a/frontend/src/ts/modules/app/app.module.ts b/frontend/src/ts/modules/app/app.module.ts
index 092f4970..b752669f 100644
--- a/frontend/src/ts/modules/app/app.module.ts
+++ b/frontend/src/ts/modules/app/app.module.ts
@@ -1,4 +1,4 @@
-import {forwardRef, NgModule} from "@angular/core";
+import {APP_INITIALIZER, forwardRef, NgModule} from "@angular/core";
import {NgbModule} from "@ng-bootstrap/ng-bootstrap";
import {CommonModule, registerLocaleData} from "@angular/common";
import localeRu from '@angular/common/locales/ru';
@@ -25,6 +25,7 @@ import {FileUploadModule} from "ng2-file-upload";
import {ErvuFileUpload} from "../../ervu/component/fileupload/ErvuFileUpload";
import {InMemoryStaticGrid} from "../../ervu/component/grid/InMemoryStaticGrid";
import {ErvuDownloadFileButton} from "../../ervu/component/button/ErvuDownloadFileButton";
+import {AuthenticationService} from "../security/authentication.service";
registerLocaleData(localeRu);
export const DIRECTIVES = [
@@ -39,6 +40,10 @@ export const DIRECTIVES = [
forwardRef(() => InMemoryStaticGrid)
];
+function checkAuthentication(authService: AuthenticationService): () => Promise {
+ return () => authService.checkAuthentication();
+}
+
@NgModule({
imports: [
CommonModule,
@@ -60,6 +65,13 @@ export const DIRECTIVES = [
DIRECTIVES
],
providers: [
+ AuthenticationService,
+ {
+ provide: APP_INITIALIZER,
+ useFactory: checkAuthentication,
+ deps: [AuthenticationService],
+ multi: true,
+ },
{ provide: ProgressIndicationService, useClass: AppProgressIndicationService }
],
bootstrap: [],
diff --git a/frontend/src/ts/modules/app/component/logout.component.ts b/frontend/src/ts/modules/app/component/logout.component.ts
index e8c3b8be..0ac178ae 100644
--- a/frontend/src/ts/modules/app/component/logout.component.ts
+++ b/frontend/src/ts/modules/app/component/logout.component.ts
@@ -1,7 +1,7 @@
import {ChangeDetectorRef, Component, OnInit} from "@angular/core";
import {Router} from "@angular/router";
import {HttpClient} from "@angular/common/http";
-import {CookieService} from "ngx-cookie";
+import {AuthenticationService} from "../../security/authentication.service";
@Component({
moduleId: module.id,
@@ -13,13 +13,12 @@ export class LogOutComponent implements OnInit{
private userFullname: string;
private orgUnitName: string;
-
constructor(private router: Router, private httpClient: HttpClient,
- private cookieService: CookieService, private cd: ChangeDetectorRef) {
+ private authenticationService: AuthenticationService, private cd: ChangeDetectorRef) {
}
ngOnInit(): void {
- let isAuth = this.getIsAuth();
+ let isAuth = this.authenticationService.isAuthenticated();
if (isAuth) {
Promise.all([
this.httpClient.get("esia/userfullname").toPromise(),
@@ -33,20 +32,18 @@ export class LogOutComponent implements OnInit{
}
public logout(): void {
- this.httpClient.get("esia/logout").toPromise().then(url => {
- window.open(url, "_self");
- })
+ this.authenticationService.logout();
}
public getUserFullname(): string {
return this.userFullname;
}
- public getIsAuth(): boolean {
- return this.cookieService.get("webbpm.ervu-lkrp-ul") != null;
+ public isAuthenticated(): boolean {
+ return this.authenticationService.isAuthenticated();
}
public getOrgUnitName(): string {
return this.orgUnitName;
}
-}
\ No newline at end of file
+}
diff --git a/frontend/src/ts/modules/security/TokenConstants.ts b/frontend/src/ts/modules/security/TokenConstants.ts
new file mode 100644
index 00000000..597fe759
--- /dev/null
+++ b/frontend/src/ts/modules/security/TokenConstants.ts
@@ -0,0 +1,4 @@
+export class TokenConstants {
+ public static readonly CSRF_TOKEN_NAME = "XSRF-TOKEN";
+ public static readonly CSRF_HEADER_NAME = "X-XSRF-TOKEN";
+}
diff --git a/frontend/src/ts/modules/security/authentication.service.ts b/frontend/src/ts/modules/security/authentication.service.ts
new file mode 100644
index 00000000..f427b3d1
--- /dev/null
+++ b/frontend/src/ts/modules/security/authentication.service.ts
@@ -0,0 +1,27 @@
+import {Injectable} from '@angular/core';
+import {HttpClient} from '@angular/common/http';
+import {Observable} from "rxjs";
+import {CookieService} from "ngx-cookie";
+import {tap} from "rxjs/operators";
+import {AppConfigService} from "@webbpm/base-package";
+
+@Injectable({providedIn: 'root'})
+export class AuthenticationService {
+
+ constructor(private http: HttpClient,
+ private cookieService: CookieService,
+ private appConfigService: AppConfigService) {
+ }
+
+ checkAuthentication(): Promise{
+ return this.appConfigService.load().then(value => this.http.get("version").toPromise())
+ }
+
+ logout(): Promise {
+ return this.http.post('esia/logout', {}).toPromise();
+ }
+
+ public isAuthenticated(): boolean {
+ return this.cookieService.get('webbpm.ervu-lkrp-ul') != null;
+ }
+}
diff --git a/frontend/src/ts/modules/security/guard/auth.guard.ts b/frontend/src/ts/modules/security/guard/auth.guard.ts
index 95c2271e..b41e5b3a 100644
--- a/frontend/src/ts/modules/security/guard/auth.guard.ts
+++ b/frontend/src/ts/modules/security/guard/auth.guard.ts
@@ -2,8 +2,8 @@ import {Injectable} from "@angular/core";
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from "@angular/router";
import {Observable} from "rxjs";
import {HttpClient, HttpParams} from "@angular/common/http";
-import {CookieService} from "ngx-cookie";
import {MessagesService} from "@webbpm/base-package";
+import {AuthenticationService} from "../authentication.service";
@Injectable({providedIn:'root'})
export abstract class AuthGuard implements CanActivate {
@@ -11,7 +11,7 @@ export abstract class AuthGuard implements CanActivate {
protected constructor(
protected router: Router,
private httpClient: HttpClient,
- private cookieService: CookieService,
+ private authenticationService: AuthenticationService,
private messageService: MessagesService
) {
}
@@ -55,11 +55,7 @@ export abstract class AuthGuard implements CanActivate {
});
}
- private checkAccess(): Promise | boolean {
- return this.getIsAuth() != null;
+ private checkAccess(): boolean {
+ return this.authenticationService.isAuthenticated();
};
-
- public getIsAuth(): string {
- return this.cookieService.get('webbpm.ervu-lkrp-ul');
- }
}
diff --git a/frontend/src/ts/modules/webbpm/interceptor/absolute-url-csrf.interceptor.ts b/frontend/src/ts/modules/webbpm/interceptor/absolute-url-csrf.interceptor.ts
new file mode 100644
index 00000000..ea231886
--- /dev/null
+++ b/frontend/src/ts/modules/webbpm/interceptor/absolute-url-csrf.interceptor.ts
@@ -0,0 +1,26 @@
+import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
+import {Injectable} from '@angular/core';
+import {Observable} from 'rxjs';
+import {CookieService} from "ngx-cookie";
+import {TokenConstants} from "../../security/TokenConstants";
+
+@Injectable()
+export class AbsoluteUrlCsrfInterceptor implements HttpInterceptor {
+
+ constructor(private cookieService: CookieService) {
+ }
+
+ intercept(req: HttpRequest, next: HttpHandler): Observable> {
+
+ let requestToForward = req;
+ let token = this.cookieService.get(TokenConstants.CSRF_TOKEN_NAME) as string;
+
+ if (token != null) {
+ let headers = {};
+ let headerName = TokenConstants.CSRF_HEADER_NAME;
+ headers[headerName] = token;
+ requestToForward = req.clone({setHeaders: headers});
+ }
+ return next.handle(requestToForward);
+ }
+}
diff --git a/frontend/src/ts/modules/webbpm/interceptor/default-interceptors.prod.ts b/frontend/src/ts/modules/webbpm/interceptor/default-interceptors.prod.ts
index 07735d52..6cd9ffe7 100644
--- a/frontend/src/ts/modules/webbpm/interceptor/default-interceptors.prod.ts
+++ b/frontend/src/ts/modules/webbpm/interceptor/default-interceptors.prod.ts
@@ -4,9 +4,11 @@ import {
HttpSecurityErrorInterceptor,
HttpSecurityInterceptor
} from "@webbpm/base-package";
+import {AbsoluteUrlCsrfInterceptor} from "./absolute-url-csrf.interceptor";
export const DEFAULT_HTTP_INTERCEPTOR_PROVIDERS = [
{provide: HTTP_INTERCEPTORS, useClass: HttpSecurityInterceptor, multi: true},
{provide: HTTP_INTERCEPTORS, useClass: HttpSecurityErrorInterceptor, multi: true},
- {provide: HTTP_INTERCEPTORS, useClass: FormDirtyInterceptor, multi: true}
+ {provide: HTTP_INTERCEPTORS, useClass: FormDirtyInterceptor, multi: true},
+ {provide: HTTP_INTERCEPTORS, useClass: AbsoluteUrlCsrfInterceptor, multi: true}
];
diff --git a/frontend/src/ts/modules/webbpm/interceptor/default-interceptors.ts b/frontend/src/ts/modules/webbpm/interceptor/default-interceptors.ts
index ee46e0c2..77b3b401 100644
--- a/frontend/src/ts/modules/webbpm/interceptor/default-interceptors.ts
+++ b/frontend/src/ts/modules/webbpm/interceptor/default-interceptors.ts
@@ -1,9 +1,11 @@
import {HTTP_INTERCEPTORS} from "@angular/common/http";
import {FormDirtyInterceptor, HttpSecurityInterceptor} from "@webbpm/base-package";
import {DevHttpSecurityErrorInterceptor} from "./http-security-error-interceptor.dev";
+import {AbsoluteUrlCsrfInterceptor} from "./absolute-url-csrf.interceptor";
export const DEFAULT_HTTP_INTERCEPTOR_PROVIDERS = [
{provide: HTTP_INTERCEPTORS, useClass: HttpSecurityInterceptor, multi: true},
{provide: HTTP_INTERCEPTORS, useClass: DevHttpSecurityErrorInterceptor, multi: true},
- {provide: HTTP_INTERCEPTORS, useClass: FormDirtyInterceptor, multi: true}
+ {provide: HTTP_INTERCEPTORS, useClass: FormDirtyInterceptor, multi: true},
+ {provide: HTTP_INTERCEPTORS, useClass: AbsoluteUrlCsrfInterceptor, multi: true},
];
diff --git a/frontend/src/ts/modules/webbpm/webbpm.module.ts b/frontend/src/ts/modules/webbpm/webbpm.module.ts
index c9ef120c..3326d6e7 100644
--- a/frontend/src/ts/modules/webbpm/webbpm.module.ts
+++ b/frontend/src/ts/modules/webbpm/webbpm.module.ts
@@ -17,6 +17,8 @@ import {
import {AppRoutingModule} from "../app/app-routing.module";
import {GlobalErrorHandler} from "./handler/global-error.handler.prod";
import {DEFAULT_HTTP_INTERCEPTOR_PROVIDERS} from "./interceptor/default-interceptors.prod";
+import {HttpClientModule, HttpClientXsrfModule} from "@angular/common/http";
+import {TokenConstants} from "../security/TokenConstants";
let IMPORTS = [
BrowserAnimationsModule,
@@ -30,7 +32,10 @@ let IMPORTS = [
CoreModule,
ComponentsModule,
AppModule,
- WebbpmRoutingModule
+ WebbpmRoutingModule,
+ HttpClientModule,
+ HttpClientXsrfModule.withOptions(
+ {cookieName: TokenConstants.CSRF_TOKEN_NAME, headerName: TokenConstants.CSRF_HEADER_NAME})
];
@NgModule({
diff --git a/pom.xml b/pom.xml
index 6d975700..c055fd73 100644
--- a/pom.xml
+++ b/pom.xml
@@ -26,6 +26,27 @@
+
+ org.springframework.security
+ spring-security-bom
+ 5.8.14
+ import
+ pom
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+
ru.cg.webbpm
platform-bom