Browser or port opening problem in the background

Hi Support team,

Our application uses TSpinxLogin component to achieve an openid authentication with OneLogin.
However in the production environment the browser doesn't show up. I think some kind of restriction causes this behaviour.
There is no exception just nothing happens.
There is edge installed on the machine and it is running on a windows terminal server (Windows Server 2019) .
We don't have any information that the component is able to open a port or not, or the browser is started by the component or not. Do you have any solution to get detailed information what is happening in the background?
Do you have any idea what we should check?

Best regards,
István Hegyes

Hi @L-SOFT_ZRT,

What do you mean by "production environment"? You mean it works in your development machine but not in user's machine?

Since you mentioned "port" and "browser" it's not exactly clear what's not working. The user web browser is never launched? Or the redirect URL is never reached? Can you please be more specific?

If it's the web browser not being launched, this looks simply like a restriction in user machine. It has nothing to do with TCP ports.

To launch the browser, Sphinx just asks Windows to open URL, the code is as simple as this:

  ShellExecute(0, PChar('open'), PChar(AUrl), nil, nil, SW_NORMAL);

You can maybe create a separate VCL application and check if such code works in your user computer.

  • Checked the event viewer ? If there are restrictions, there should be something in security or application logs.
  • Have you tried running it as administrator?
  • Is Edge configured as default browser for the user profile?
  • In some cases, Edge may not open in a terminal server session if the user has another active session. Server 2019 Terminal Server Edge Browser on Multiple Sessions
1 Like

Thank you for your feedback.
It works on my development machine, and doesn't work in production environment.
The production environment is a terminal server with a lot of restriction applied.
When we call SphinxLogin.Login nothing happens. The browser is never launched.

I think two things happens when we call SphinxLogin.Login: It tries to open a port for getting back a response from the browser. Launch a browser.

I forward your feedback to the admin team for further investigation.

I got some update.
We had a hidden exception in the background:

Could not perform WinHttp operation. Error: (12002) The request has timed out.

I think it is related the to the port opening. What can cause this error?
Can you share the code how the component tries to open the port?

Have you created and run the test project I suggested? Just create an empty project that launches a browser at a generic address (Google URL, for example) and see if it opens.

Please provide a call stack if you have one.
I don't think a timeout is related to port opening. A timeout is a try to connect to some server which is not responding.

This is the exact code that launches a local server that will listen to a port:

procedure TSystemBrowser.StartListener(UrlCallback: TCallbackUrlProc);
var
  BaseUrl: string;
  Uri: IUri;
  Port: Integer;
  FinishedProc: TProc;
begin
  Uri := TUri.Create(Options.EndUrl);
  Port := Uri.Port;
  BaseUrl := Format('http://127.0.0.1:%d%s', [Port, Uri.AbsolutePath]);

  FinishedProc :=
    procedure
    begin
      TThread.Queue(nil, procedure
        begin
          FHttpServer.Active := False;
        end);
    end;

  FHttpServer.Free;
  FHttpServer := TIndySparkleHTTPServer.Create(nil);
  FHttpServer.Dispatcher.AddModule(TCallbackServerModule.Create(BaseUrl, UrlCallback, FinishedProc));
  FHttpServer.Active := false;
  FHttpServer.Bindings.Clear;
  FHttpServer.Bindings.Add.SetBinding('127.0.0.1', Port);
  FHttpServer.Active := true;  
end;

Thank you for your efforts.

Have you created and run the test project I suggested? Just create an empty project that launches a browser at a generic address (Google URL, for example) and see if it opens.

Yes I created a sample application. Afterall the browser is started. I need to mention that there is a force login before using the browser, but at the end the browser is started and get back the desired page.

Please provide a call stack if you have one.

I started to get the callstack. I need more time to get this. Let's get back here later.

Thank you for the code. We will create a sample application and check how it is working in the production environment.

Update:
During the login process in the component at the line: FHttpServer.Active := true; we got the following exception: Socket Error # 10013. Access denied.

That indeed looks like a restriction in your customer computer. The internal server that listens for the callback URL cannot be started.

You should contact your admin to know how to allow that.

We did some research and let me summarize what we have.

So the original problem is that the OpenID login process not working, the browser is not launching in production environment. In development environment it is working.

We created some debug software to check where is the problem.
We always get a command timeout exception as I showed you earlier.

It is raised in the Sparkle.Http.Client.pas, in the THttpClient.Send function at the line Result := FEngine.Send(Request);

It is trying to get the metadata from the server. However it is not matter what is the url.
We tried to get the same url with NetHttpClient and it is worked.
We came to the conclusion that the request is a bit different if we create it with the Sparkle.Http.Client.

I just shared our results maybe you can give us some ideas what to check.

Can you please create a totally separated test project, a minimal one, that performs the same request to the same URL, using Sparkle HTTP Client and then NetHttpCLient?

Then, can you please confirm the behavior in the production environment, that the request works for NetHttpClient and failed for Sparkle with timeout?

Then, with all confirmed, can you please send the project to us?

In any case, it looks like your production machine is very, very restrictive and maybe you could talk to your administrator to investigate WHAT is being restricted. A simple request to a URL is basic behavior and if your production environment restricts that, I'm not sure what we can do about it.

Dear support,

We made a test project which is attached to this comment. It has two buttons which simple send a "get" request. The first button uses original Embarcadero component. The second button uses Sparkle component. Both of them are working fine in our enviroment. But only at the production customer's enviroment (Windows Server 2012 -Terminal server) the Sparkle method fails. We get back the following error message shown error1.png.
error1

After removing try-except blocks in "Sparkle.WinHttp.Engine.pas" the error message is changing to: error2.png:
error2

What is the difference which can cause the error message in the production enviroment?
SparkleVsEmbarcadero.zip (2.2 MB)

You are getting a timeout. Maybe your production server needs a proxy to access the internet.

Try to enable automatic proxy to see if it helps:

Hi,

It seems to us the solution is the proxy mode is set to "THttpProxyMode.Auto" in the Sparkle.WinHttp.Engine.pas:
"... ProxyMode := THttpProxyMode.Auto; ... "

How can we prepare the ProxyMode in our appilcation without editing the compoent source code itself.

In our case we only have "TSphinxLogin" component and we call the "Login" method.

How can we configure the "TSphinxLogin" component to use the proxy "auto" mode.

Thanks.

We have just released an update of Sparkle which allows you to set the global default proxy mode:

uses Sparkle.WinHttp.Engine;
...
TWinHttpEngine.DefaultProxyMode := THttpProxyMode.Auto;

Hi,

How to configure default proxy server name and port for custom mode? (THttpProxymode.custom)

Thanks.

There is no such feature for now. But if the native HTTP client component works out of the box without you setting any proxy properties, it means that it's simply using the proxy settings configured in the Windows system, which is what "Auto" option does.

Thanks for your answer, but our client expects to be able to set the custom mode parameters (server, port).
We have to meet this expectation.

Please ensure your support and we are waiting for your answer as to when it will be available.

We will do some modifications for the next version (to be released maximum next week) where you will be able to do something like this:

  SphinxLogin1.Client.OnHttpClienCreate :=
    procedure(Client: THttpClient)
    var
      Engine: TWinHttpEngine;
    begin
      Engine := TWinHttpEngine(Client.Engine);
      Engine.ProxyMode := THttpProxyMode.Custom;
      Engine.ProxyName := 'foo';
    end;