XSRF - как установить кросс-источник cookie

Я разработал REST API и два клиента JavaScript (одностраничное приложение и нативное приложение - на основе электроники). В обоих клиентах мои пользователи проходят аутентификацию через поток OAuth2:

  1. отправляет пароль пользователя на сервер
  2. получает access_token (в виде простого текста) и refresh_token (в файле cookie httponly)
  3. по истечении срока действия токена они обновляют его, отправляя запрос в конечную точку /refresh (сервер считывает refresh_token из cookie-файла)

Теперь я хотел бы реализовать защиту CSRF. Так что я реализовал это на моей стороне (Spring):

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
                .authorizeRequests().antMatchers("/", "/index.html", "/token/**").permitAll()
                .anyRequest().authenticated();
    }

Мой SPA работает отлично, angular читает XSRF-TOKEN из cookie и отправляет его в заголовке X-XSRF-TOKEN. У меня проблема с электронным приложением. У него нет доступа к cookie (из-за разного происхождения - электрон работает на file:// url), поэтому невозможно установить заголовок X-XSRF-TOKEN.

Как я могу справиться с такой проблемой? Есть ли какой-нибудь способ создать "перекрестное" печенье? Или, может быть, я могу каким-то образом получить значение cookie через API API для электронной магии электронов (если у него есть доступ к файловой системе, возможно, у него есть доступ к любому cookie, созданному на машине)?

0 ответов

У меня была та же проблема, и в конце концов мне удалось ее исправить, реализовав угловой перехватчик http, например:

@Injectable()
export class HttpXsrfInterceptor implements HttpInterceptor {

  constructor(private tokenExtractor: HttpXsrfTokenExtractor, //from angular
              private nativeAuthService: NativeAuthService) { //my native service
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    //this works in web
    const headerName = 'X-XSRF-TOKEN';
    const token = this.tokenExtractor.getToken() as string;
    if (token !== null && !req.headers.has(headerName)) {
      req = req.clone({ headers: req.headers.set(headerName, token) });
      return next.handle(req);
    }

    //this works in electron
    return this.nativeAuthService.getCookieValue('XSRF-TOKEN').pipe(
      mergeMap((xsrfToken: string) => {
        if (xsrfToken && !req.headers.has(headerName)) {
          req = req.clone({ headers: req.headers.set(headerName, xsrfToken) });
        }
        return next.handle(req);
      }),
    );
  }
}

А мой nativeAuthService просто вызывает этот метод в основном процессе электрона:

export function getCookieValue(cookieName: string): Observable<string> {
  return from(session.defaultSession.cookies.get({ name: cookieName })
    .then((cookies: Electron.Cookie[]) => {
      if (cookies.length == 1) {
        return cookies[0].value;
      } else {
        if (cookies.length > 1) {
          throw Error(`There is more than one cookie with the name: ${ cookieName }.`);
        }
        return '';
      }
    }));
}
Другие вопросы по тегам