Configuring the UI Login screen

I have a problem with the UI (hosted at /ui) that I cannot immediately figure out.

Problem

We are using the AuthFeature, with a bunch of providers, as such:

appHost.Plugins.Add(new AuthFeature(() => new AuthUserSession(),
                new IAuthProvider[]
                {
                    AuthenticationProviders.CreateJwtProviderForSigningAndValidation(settings),
                    AuthenticationProviders.CreateApiKeyProviderForValidation(
                        container.LazyResolve<IApiKeyApplication>()),
                    AuthenticationProviders.CreateHmacProviderForValidation(settings),
                                        AuthenticationProviders.CreateCredentialsProviderForAuthentication(
                        container.LazyResolve<IUserCredentialsApplication>())
                })
            {
                SaveUserNamesInLowerCase = true,
                ValidateUniqueUserNames = true,
                ValidateUniqueEmails = true,
                IsValidUsernameFn = username => Validations.EmailAddress.Matches(username),
                IncludeRolesInAuthenticateResponse = true,
                IncludeAssignRoleServices = false,
                IncludeRegistrationService = false,
                IncludeDefaultLogin = false
            });

and thus we get the built in “Login UI”, (at /ui) which is great.

Now, if a developer selects the “Credentials” tab and fills out the form, the login attempt does succeed,
image

The format of those roles (in green) is how we define them

but, if we try to use any of the APIs from the left pane, they are called without including our JWT bearer token in the request. (Fiddler confirms that)

Workaround

However, we can make the whole thing work if we use the Authenticate request (at /ui/Authenticate).

Then get a JSON response containing a bearerToken that we can then copy and paste into the “JWT” tab of the “Login UI” on the “JWT” tab (at /ui).

Then calling any APIs from the left pane now includes the JWT in the request. (Fiddler confirms this).

Question

Is there something I can do to make it work through the “Credentials” tab (at /ui)? or what other options do I have? the workaround is not obvious and a PITA to get working for the user.

I’m struggling to follow this to find out what the actual issue is.

Is it after you sign in, you’re not actually authenticated so attempting to call a protected API will fail?
If you refresh the page is Authentication lost and you have to sign in again?

Yes, that is the case - if I use the “Credentials” form of the “Login UI”. at /ui

So then your Authenticate API isn’t returning authenticated cookies? What cookies is it returning? Are you using a Custom CredentialsAuthProvider?

I’m assuming your JwtAuthProvider is configured to not use Cookies, i.e. UseTokenCookie = false?

That is correct.

  • For the JwtAuthProvider, UseTokenCookie = false.
  • Yes, we are using a custom CredentialsAuthProvider.

(This is an API service, so no cookies)

Perhaps there is some way to configure the javascript of that /ui “Login Form” to extract the bearer token from the Authenticate JSON response and store it in the same place as the JWT is being stored for future requests?

What’s the rationale here for not using cookies? Do you have any browser clients that need to authenticate with this API?

You can try the latest v6.8.1 on MyGet to see if it resolves this.

No we specifically do not want to support browser apps connecting to this API. We have one and it is using ss_tok and ss_reftok cookies, but connecting to the APIs through a reverse proxy. We only want cookies on the web apps, not on the APIs.

Thanks for the spike, I will check it out

Thansk @mythz

Looking at your last commit that fixed this,
Is it possible in our version (6.1.0) to put in place those changed files, by configuring the UiFeature somehow.
I do see abunch of options in there for modules, but not sure if its possible to inject that new code into them?

This would be good to fix the problem (with the raw changed files) until we can upgrade to vnext.

No all UIs have been completely rewritten since v6.1 from PetiteVue to Vue 3, otherwise a lot of the files could’ve been replaced

Is there a version after 6.1.0 that I can upgrade to and replace these modules to tie me over until v.next?

Any advice/samples in how would I do that from my code?

You should be able to create local modified copies of of stores.js and add them to your projects local /wwwroot/modules folder with an updated login() that sets the bearerToken properties:

if (this.api.succeeded) {
    if (this.api.response.bearerToken) {
        bearerToken = client.bearerToken = this.api.response.bearerToken
    }
}

Thanks, do you mean I can do this on v6.1.0?

Should be able to, but not tested.

Brilliant, thanks @mythz,
that workaround works in v6.1.0.
Ill upgrade to vnext when it comes out

1 Like