Http Unknown Error status 0 -> Angular/ ionic frontend - Spring Boot backend

I use Spring Boot at backend and ionic 6.20.4 and Angular 12.x.x at frontend. At the backend I have the following rest service to authenticate users:

@CrossOrigin(origins = { "*" }, allowedHeaders = { "Content-Type", "x-auth-token" })
@RestController
public class AuthRestService extends AbstractRestService {

...
@RequestMapping(value = "/login", method = { RequestMethod.POST }, consumes = "application/json;charset=utf-8")
public UserTransferObject login(final @RequestBody LoginData loginData, final HttpServletRequest request) throws BusinessException {
...

and the following XAuthTokenFilter:

@Component
@EnableConfigurationProperties
@ConfigurationProperties(locations = "classpath:application.properties", ignoreUnknownFields = true, prefix = "myconfigfile.login")
public class XAuthTokenFilter extends GenericFilterBean {

protected final Logger logger = LoggerFactory.getLogger(getClass());

private UserDetailsService detailsService;
private final TokenUtils tokenUtils = new TokenUtils();
private String xAuthTokenHeaderName; // configured in application.properties

public XAuthTokenFilter() {
}

public UserDetailsService getDetailsService() {
    return detailsService;
}

public void setDetailsService(final UserDetailsService detailsService) {
    this.detailsService = detailsService;
}

@ResponseStatus(HttpStatus.OK)
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain)
        throws IOException, ServletException {
    try {
        final HttpServletRequest httpServletRequest = (HttpServletRequest)request;
        final String authToken = httpServletRequest.getHeader(this.xAuthTokenHeaderName);

        logger.debug("filter request for token '{}' in XAuthTokenFilter#doFilter", authToken);

        if (StringUtils.hasText(authToken)) {
            final String username = this.tokenUtils.getUserNameFromToken(authToken);

            final UserDetails details = this.detailsService.loadUserByUsername(username);

            final boolean isTokenValid = this.tokenUtils.validateToken(authToken, details);
            logger.debug("token is valid = '{}' in XAuthTokenFilter#doFilter for user with user name '{}'", isTokenValid, username);
            if (isTokenValid) {
                final UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(details,
                    details.getPassword(), details.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(token);
            } else {
                logger.info("token '{}' is not valid for user '{}' in AuthTokenFilter", authToken, username);
                // throw new Exception("token is not valid in XAuthTokenFilter#doFilter");
            }
        }
        final HttpServletResponse resp = (HttpServletResponse)response;
        resp.setHeader("Access-Control-Allow-Origin", "*");
        resp.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, DELETE, PATCH, OPTIONS");
        resp.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, x-auth-token");
        resp.setHeader("Access-Control-Max-Age", "3600");
        if ("OPTIONS".equalsIgnoreCase(((HttpServletRequest)request).getMethod())) {
            resp.setStatus(HttpServletResponse.SC_OK);
        } else {
            filterChain.doFilter(request, response);
        }
    } catch (Exception ex) {

        // @ExceptionHandler is not available at filter-therefore own json-response is created and sent to client
        ((HttpServletResponse)response).setStatus(HttpServletResponse.SC_UNAUTHORIZED);

        final ErrorAdviceHolder errorAdviceHolder = new ErrorAdviceHolder();
        errorAdviceHolder.setTimestamp(new Timestamp(System.currentTimeMillis()));
        errorAdviceHolder.setError(ex.getStackTrace()[0].toString());
        errorAdviceHolder.setMessage(ex.getMessage());
        errorAdviceHolder.setPath("XAuthTokenFilter#doFilter");
        errorAdviceHolder.setStatus("Error");
        errorAdviceHolder.setException(ex.getClass().getName());

        final ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
        final String errorAdviceHolderJson = ow.writeValueAsString(errorAdviceHolder);

        ((HttpServletResponse)response).getWriter().write(errorAdviceHolderJson);
        ((HttpServletResponse)response).getWriter().flush();
        ((HttpServletResponse)response).getWriter().close();
    }
}

public String getxAuthTokenHeaderName() {
    return xAuthTokenHeaderName;
}

public void setxAuthTokenHeaderName(final String xAuthTokenHeaderName) {
    this.xAuthTokenHeaderName = xAuthTokenHeaderName;
}

@Override
public String toString() {
    return "[XAuthTokenFilter: xAuthTokenHeaderName: " + xAuthTokenHeaderName + "]";
}
}

In frontend I use the following environment.ts file:

export const environment = {
   production: true,
   envName: 'prod',
   apiEndpoint: 'https://app.mydomain.com/api/'
};

and the following methods to invoke the backend login method:

this.authService.login(this.ngForm.value).subscribe(response => {
  // ...
}, error => {
  this.errorMessage = error;
  // ...
});

// authService
login(loginData: LoginData):Observable<any>  {
  const url = environment.apiEndpoint + 'login';
  return this.httpClient.post(url, loginData);
}

The app-http-interceptor looks like this:

@Injectable()
export class AppHttpInterceptor implements HttpInterceptor {

constructor(protected authService: AuthService, private router: Router) { }

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return from(this.authService.getToken()).pipe(
        switchMap((token) => {
            const tokenString: string = token as string;
            if(token) {
                let authReq = req.clone({
                    setHeaders: {  
                        'x-auth-token': tokenString,
                        'Content-Type': 'application/json'
                        }
                });
                return next.handle(authReq);
            } else {
                return next.handle(req);
            } 
        })
    );
}
} 

Now if I start the frontend either with ng serve or ionic serve I can login at backend without any problems - all works fine.

But if I deploy the app on an android device with ionic capacitor run android, deployment works also fine but if I try to login than I get the following error:

errorMessage : { { "headers": {"normalizedNames": {}, "lazyUpdate": null, "headers": {}},
"status": 0, "statusText": "Unknown Error", "url": "https://app.mydomain.com/api/login", "ok": 
false, "name": "HttpErrorResponse", "message": "Http failure response for 
https://app.mydomain.com/api/login: 0 Unknown Error", "error": {"isTrusted": true} }

Does anyone have any idea what I am doing wrong in order to get this error. Thanks for any hint! I’m still a little bit desparate.