AuthenticateResponse Meta property with identity auth

I can’t find any examples of how to add values to the Meta property on the AuthenticateResponse object when using Identity auth.

I tried AuthResponseDecorator

public void Configure(IWebHostBuilder builder) => builder
    .ConfigureServices(async services =>
    {
        services.AddSingleton<IAuthHttpGateway, AuthHttpGateway>();
        services.AddTransient<IExternalLoginAuthInfoProvider, ExternalLoginAuthInfoProvider>();

        services.AddPlugin(new AuthFeature(IdentityAuth.For<ApplicationUser>(options =>
        {
            options.SessionFactory = () => new CustomUserSession();
            options.CredentialsAuth();
            options.JwtAuth(x =>
            {
                x.IncludeConvertSessionToTokenService = true;
                
            });
        }))
        {
            AuthResponseDecorator = (context) =>
            {
                context.AuthResponse.Meta.Add("test", "value");
                return context;
            }
        });
    });

But that didn’t work.

I also tried global filter:

RegisterTypedResponseFilter<AuthenticateResponse>((req, res, dto) =>
{
    dto.Meta ??= [];
    dto.Meta.Add("test", "value");
});

But it doesn’t fire.

The docs say the request/response models stay the same for clients but changed for internals so I am not sure how to access it.

ServiceStack’s Identity Auth Integration
ServiceStack’s Identity Auth integration is focused on high compatibility so existing ServiceStack Customers require minimal effort to migrate existing code bases to use the new Identity Auth integration, despite Identity Auth being an entirely different Auth Provider model and implementation.

It does this by retaining a lot of the existing user-facing Authentication and Session abstractions that ServiceStack APIs use for Authorization as well as existing endpoints and Request/Response DTOs that ServiceStack Clients use to Authenticate, but replace their internal implementation to use ASP.NET Identity Auth instead.

I am confused, I can’t see how to add to the meta field.

How are you authenticating? i.e. where are you getting AuthenticateResponse from?

I have tested with the /locode dash and typescript client. The filter fires when I logout with a null DTO but not when I log in.

Please provide the full HTTP Request/Response Headers of the Authentication Request (with any confidential info scrubbed out).

General

Request URL:
https://localhost:5001/api/Authenticate

Request Method:
POST

Status Code:
200 OK

Remote Address:
[::1]:5001

Referrer Policy:
strict-origin-when-cross-origin

Response

Request URL:
https://localhost:5001/api/Authenticate

Request Method:
POST

Status Code:
200 OK

Remote Address:
[::1]:5001

Referrer Policy:
strict-origin-when-cross-origin

Request

Content-Type:
text/plain;charset=UTF-8

Referer:
http://localhost:3000/

Sec-Ch-Ua:
“Chromium”;v=“124”, “Google Chrome”;v=“124”, “Not-A.Brand”;v=“99”

Sec-Ch-Ua-Mobile:
?0

Sec-Ch-Ua-Platform:
“Windows”

User-Agent:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36

Payload

{
    "provider": "credentials",
    "userName": "admin@example.com",
    "password": "password",
    "rememberMe": true
}

Both are still getting called, the AuthResponseDecorator is for returning a different or a decorated AuthenticateResponse DTO, in your example you’re returning the entire Context which is not serializable.

Change it to return an instance of the Response DTO you want it to return, e.g:

AuthResponseDecorator = context =>
{
    context.AuthResponse.Meta ??= [];
    context.AuthResponse.Meta.Add("test", "value");
    return context.AuthResponse;
}

This will break Auth since the context isn’t serializable.

I’ve also verified RegisterTypedResponseFilter does still get called, so not clear why it’s not being called for you. Maybe you didn’t test it without the invalid AuthResponseDecorator, which changes the Response Type preventing it from being called.

appHost.RegisterTypedResponseFilter<AuthenticateResponse>((req, res, dto) =>
{
    dto.Meta ??= [];
    dto.Meta.Add("test2", "value2");
});

I’ve also tested that this being returned when authenticating in the built-in UIs:

image

It seems to happen when I add in JWT config.

Adding this stops the filter firing during login:

  options.JwtAuth(x =>
  {

  });

If I remove the JWT settings from auth config then the global filter hits correctly.

Standalone repro - GitHub - GuerrillaCoder/standalone-repro

That’s because JWT uses the AuthResponseDecorator to convert the AuthenticateResponse into a JWT Cookie, so your Global Response Filter would need to check for the decorated response, e.g:

GlobalResponseFilters.Add((req, res, dto) =>
{
    if (dto is HttpResult { Response: AuthenticateResponse authResponse })
    {
        authResponse.Meta ??= new();
        authResponse.Meta["test"] = "value";
    }
});

This is also how ServiceStack Auth JWT Provider works.

Why are you still using JWT instead of Identity Auth’s default Application cookie?