getting access violation in Sphinx

Just revisiting this after a while, with probably a couple of Sphinx updates in between, I'm hitting a GPF here, right after a user registration - see attached.

FMap is not assigned here. And the stack trace goes all the way back to nowhere. I don't think I made any changes that could cause anything like this.

The registration screen is not being helpful:
image

But I can see the user has been created in the DB.

Is this something new you could fix?

That error in such specific call stack is strange. Is this in your application? Does the same problem happens in the existing Sphinx demo?

Are you able to send us a project reproducing the issue?

Not sure exactly why, but this one is gone now. I have however discovered that it's enough to call SphinxServer1.CreateContext; inside ConfigureToken event to cause random problems later, even if you do not do anything with the returned Context. I think this GPF was related. It feels like getting Context somehow corrupts stack: I can F8 though this code just fine, but then it bombs out somewhere later. I was just trying to get to the authenticatorkey through UserManager, as per the code example you have published somewhere earlier. Now I read user tokens instead, from the user object supplied in the parameters, it works without AV's.

That kind of leaves me stranded: I'm trying to Args.User.TwoFactorEnabled := TRUE; but that has no effect, I think I have to do this through UserManager and as soon as I touch it in ConfigureToken event, all hell breaks loose. ConfigureToken is the place for me, because of how I'm doing it. I need to be able to update the user properties in that event. What should I do?

For some reason ConfigureToken is called twice after login. 1st time it works fine, but the 2nd time it crashes on trying to access "Args.User.Tokens.Count" (this is done before I create Context in the procedure).

The client receives this back:
500 / Internal Server Error [{"error":"server_error","error_description":"Internal server error: MdL9q_KiGd_-vquQ4d65-zEJNU1BNEBKTossgweVcRU"}]

If I don't touch Context, it works fine both times.

Can you please organize this support request, sending a compilable project and listing the issues including steps to reproduce each of them.

In the Demos\Simple\Server folder, SphinxServer demo project, replace procedure TForm7.SphinxConfig1ConfigureToken event code with:

procedure TForm7.SphinxConfig1ConfigureToken(Sender: TObject; Args: TConfigureTokenArgs);
var
TenantId: string;
P: Integer;
Context : ISphinxContext;
User : TUser;
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) ;

Args.Token.Claims.AddOrSet('upn', Args.User.Email.ValueOrDefault);
if not Args.User.TwoFactorEnabled then
begin
Context := SphinxServer1.CreateContext;
User := Context.UserManager.FindByName(Args.User.UserName);
User.TenantId := TenantId;
User.TwoFactorEnabled := True;
Context.UserManager.UpdateUser(User);
end;
if Args.User.TenantId.ValueOrDefault <> '' then
Args.Token.Claims.AddOrSet('tid', Args.User.TenantId.ValueOrDefault);
end;

Put a breakpoint there and run through: 1st time it's all good, 2nd time, the Args.User has no values, but it ticks through this code fine - only to crash somewhere later.

Is this sufficient?

PS: I was lucky it was reproducible so easily, it would typically be much harder, if at all possible.

PPS: I am updating User here, because I want to send the encrypted TOTP secret in the 1st token (if TwoFactorEnabled is FALSE) and immediately enable 2FA afterwards, so I never send the secret again. I want the user to register immediately on this single opportunity.

To my original report, it actually consistently happens when 1) no tables existed before server starts, so it has to create them first, 2) right after the 1st user registration.

Annoyingly, some user setup has already happened, so there's no way to re-register the same user. And the screen stays on that blank pink message box, with no indication of what is to happen next:
image

If I add an extra check in the begging of the ConfigureToken:

if Args.User.UserName.ValueOrDefault.IsEmpty then
Exit;

to skip the second round, then even though no subsequent code is executed, it still GPF's later on.

I'm no longer sure, this started happening again after every new user registration, whether there is a DB or not:

It's not happening in the Demo Server, so I would not be able to come up with a simple project where this can be reproduced. Anything else we can do?

In Aurelius.Entity.ObjectMap unit, I can see FMap being created, an object added and it's being freed. And then this CleanUp is called from TXDataBaseRequestHandler.InnerProcessRequest; after it was freed.

Ok, I could reproduce it in the Demo Server project: just add an OnUserCreated event and use this code:

procedure TForm7.SphinxConfig1UserCreated(Sender: TObject; Args: TUserCreatedArgs);
var
User: TUser;
Context: ISphinxContext;
Key : string;
begin
Context := SphinxServer1.CreateContext;
User := Context.UserManager.FindByName(Args.User.UserName);
if Context.UserManager.GetAuthenticatorKey(User) = '' then
Context.UserManager.ResetAuthenticatorKey(User);
Key := Context.UserManager.GetAuthenticatorKey(User);
end;

Then run it and try registering a new user. Interestingly enough, this worked for me sometimes before...

Thank you. Indeed this is an issue with memory management in Sphinx context, in a specific situation.

We fixed this at our side, but you can do there as well, it's a simple modification. In unit Sphinx.Comp.Server, method TSphinxServer.CreateContext, line 138, you should add an extra False parameter in the call of TSphinxContext.Create:

  if Manager <> nil then
    // In the following line, add the fourth "False" parameter to the call
    Result := TSphinxContext.Create(Options, Factory, Manager, False)
  else
    Result := TSphinxContext.Create(Options, Factory, GetConnectionPool);

Then don't forget to rebuild the packages using tms build in Smart Setup.

Please let me know if this solves all your problems, if not, please let me know again the exact steps to reproduce any pending issues.

Ok, thanks, it does resolve those 2 issues. What I have now is this: right after a 2FA prompt, Sphinx silently (no exceptions raised in the debugger) returns "500 / Internal Server Error [{"error":"server_error","error_description":"Internal server error: ysZthedkLhcOqEidBR6MGQh25tp8Qj-HeZn2bufT-_Q"}]" (formatting is mine, but the error is from Sphinx).

It would be a lot of effort to modify demo project for 2FA, with the registration and all. I hope the above is sufficient for you to reproduce it.

The actual line is this:

BTW, if the previous session has failed, the browser is sending some old cookie to Sphinx and it starts an avalanche of these:
image
Maybe it should clear this cookie after it sees the 1st one like that?

Do you see what may be causing it? I was unable to reproduce it in the Demo Simple Server without adding more to it, unfortunately. But I'm hoping that there's enough information above to indicate what the issue might be...

If I understood your screenshots correctly, the error occurs in a call to:

 TokenBuilder.BuildToken(TokenContext)

That requires more details to be displayed, what I mean is, there are more lines being executed there, so the call stack is missing those details. And among the lines being executed there might be also your own code in the OnConfigureToken or OnGetSigningKey event. Can you please inspect better this?

Can you please provide more details on it? It would be good if you open a separate topic for that, to avoid confusion.