OAuth error: invalid_client - Invalid client credentials

Hello again,
i've another Sphinx related question/problem.
I want to realise a Server-to-server authentification but receive the Error:

OAuth error: invalid_client - Invalid client credentials

I guess, that i don't use the correct way to transmit the Secret.
Below is my attempt to realise the automatic authentification.
I double checked the authority, CliendID and Scope in the TSphinxLogin component.
(Authentification from WebCore to the same Sphinx Server works fine! Thanks again).

Server Side Configuration:

  Client := SphinxConfig.Clients.Add;
  Client.ClientId := 'server';
  Client.DisplayName := 'VCL Client';
  Client.RequireClientSecret := True;
  Client.AllowedGrantTypes := [TGrantType.gtClientCredentials];
  Client.AddSha256Secret(THashSHA2.GetHashBytes('test'));
  Client.ValidScopes.Add('Projekt');

Client Side Authentification Attempt

  TokenResult := SphinxLogin1.RequestToken(THashSHA2.GetHashString('test'));
  Edit1.Text:=TokenResult.AccessToken;

Kind regards,

The secret is test, this is how you should use it:

  TokenResult := SphinxLogin1.RequestToken('test');
  Edit1.Text:=TokenResult.AccessToken;

In the server you add the Sha256 hash of the secret, but from client, you have to send the secret itself.

The Error still remains when i pass 'test' as Parameter.
Do i have to create a Pseudo-user for the Server in the Dataset? Could that be the problem?
It's the same Sphinx Server i use to Authenticate my Web-Users and which returns the TenantId.
So i also have the two functions OnConfigureTokens and OnGetSigningData configured.
May that be a/the problem?

Kind regards,

No, the client_credentials flow doesn't have a user involved.

Also no, those events do not affect authentication using client_credentials.

Are you setting `SphinxLogin1.ClientId to "server"?

Other than this, can you please maybe send me a sample project reproducing the issue? If we can compile and reproduce the problem here, I'm sure we can quickly see why it's failing.

I changed the Sphinx Simple Demo and get the same Error.
The ClientID from the VCL matched with the Configuration on the sphinx Server.

Test.zip (142.0 KB)

Thank you for the project. You've hit a bug in TMS Sphinx. We have fixed this internally and next released version will work properly, but in the meanwhile you can work around this issue by moving the code from ConfigureClients method to the OnGetClient event of SphinxConfig1 component. This should be the code in the event:

procedure TForm7.SphinxConfig1GetClient(Sender: TObject; Client: TSphinxClientApp; var Accept: Boolean);
begin
  // The following properties can be simply set at design-time using the TSphinxConfig.Clients property
  // We keep it in the code here for learning purposes

  // Create desktop client
  if Client.ClientId = 'desktop' then
  begin
    Client.ClientId := 'desktop';
    Client.DisplayName := 'My App';
    Client.RequireClientSecret := True;
    Client.AllowedGrantTypes := [TGrantType.gtClientCredentials];
    Client.AddSha256Secret(THashSHA2.GetHashBytes('test'));
    Client.ValidScopes.Add('openid');
    Client.ValidScopes.Add('email');
    Accept := True;
  end;

  // Create web client
  if Client.ClientId = 'web' then
  begin
    Client.ClientId := 'web';
    Client.DisplayName := 'My App';
    Client.RedirectUris.Add('http://localhost:2001/tms/WebClient/');
    Client.RequireClientSecret := False;
    Client.AllowedGrantTypes := [TGrantType.gtAuthorizationCode];
    Client.ValidScopes.Add('openid');
    Client.ValidScopes.Add('email');
    Accept := True;
  end;
end;

Also note that since you are now accepting non-impersonated requests, you should improve the code in OnConfigureToken event to test is Args.User is nil (which will be the case for client credentials token requests):

procedure TForm7.SphinxConfig1ConfigureToken(Sender: TObject; Args: TConfigureTokenArgs);
var
  TenantId: string;
  P: Integer;
begin
  if Args.User <> nil then
  begin
    TenantId := Args.User.Email.ValueOrDefault;
    P := Pos('@tmssoftware.local', TenantId);
    if P > 1 then
      TenantId := UpperCase(Copy(TenantId, 1, 1)) + Copy(TenantId, 2, P - 2);
    Args.Token.Claims.AddOrSet('tenantId', TenantId)
  end;
end;

Thanks a lot.
Works now.

1 Like

This topic was automatically closed 60 minutes after the last reply. New replies are no longer allowed.