Developer forum

Forum » Development » Use of UseFixedSecret gives 400 Badrequest

Use of UseFixedSecret gives 400 Badrequest

Anders Ebdrup
Reply

Hi DynamicWeb,

 

We experience that using the globalsetting: "/Globalsettings/Modules/Users/Jwt/UseFixedSecret" results in a 400 Badrequest when calling webapi methods marked with [PermissionFilter], where the Bearer-token is generated by this method: Dynamicweb.Frontend.Classic.Api.Controllers.JwtService.GetToken(Pageview.User, 3600).

Can you please try to look into that?

 

Best regards, Anders


Replies

 
Morten Bengtson Dynamicweb Employee
Morten Bengtson
Reply

Hi Anders,

A 400 bad request error would usually occur if...

1. The "Authorization" header is empty or the value cannot be parsed (scheme, parameter).
2. The user cannot be resolved from the provided token. This is done internally by calling JwtService.GetPrincipal(token) which parses the token, tries to lookup the user and then generates a claims principle from that user.
3. The user doesn't have the required permissions to the requested resource, e.g. making a GET request for something where the user doesn't have the required Read permission.

If the issue only occurs for endpoints with PermissionFilter then 3 is probably the cause.
Otherwise, try to check if the issue could be related to any of the following... 

A. It seems that you currently need to restart the application after changing the JWT configuration settings

/Globalsettings/Modules/Users/Jwt/UseFixedSecret
/Globalsettings/Modules/Users/Jwt/Secret

This is probably unintended. I'll need to get that confirmed.

Note: The secret must be exactly 32 characters long for this to work.

B. When UseFixedSecret mode is enabled the token generation and validation is different from how it works in the normal mode (default).
The normal mode will use the user id as identifier in the token, but the fixed secret mode will use the username as identifier in the token.
The identifier in the token is used for looking up the actual user in the request.
If you have multiple users with the same username then it might not work as expected.
I'm not sure why this part of the token handling is different. I'll need to ask someone else about that.

If you still can't find the cause of the issue then please provide some more details (DW version, api endpoint, request/response examples) and we can take a closer look at it.

/Morten

 
Anders Ebdrup
Reply

Dear Morten,

Thank you very much for the detailed explanation of the implementation.

Based on your description, I can deduce that the reason I am receiving a 400 Bad Request is that my user does not have a username. In our setup, we impersonate “customers” who are not allowed to log in to the solution, and therefore do not have a username associated with their account.

This leads to another question:
Why is the username used as the identifier in the JWT token, rather than—for example—the user’s UniqueId?

Best regards, Anders

 
Morten Bengtson Dynamicweb Employee
Morten Bengtson
Reply

I think the JWT token handling was implemented before UniqueId was added to users. Maybe we can change it to use the UniqueId or make the behavior configurable.
I have added a feature request to our backlog, but it hasn't been approved and planned yet.

DevOps #26546

/Morten
 

 
Nuno Aguiar Dynamicweb Employee
Nuno Aguiar
Reply

Hi Anders,

 

I've been down the path of having Impersonation of "customers" who are not allowed to log into the solution, but that came with a lot of issues (i.e. sharing of saved cards, problems getting proper statistics/tracking data, limitations in smart searches, sharing of favorites, ...)

 

There's a new approach coming that overcomes these issues that you might want to consider as well (although not all features are available in Ring 1 just yet):

  • Customers/Accounts are User Groups (of a specific type)
  • Each person will have a Login (DW user)
    • this one contains the password
  • For each Account the person can manage, it would have a Profile
    • different DW user that has the same username as the Login, no password, same Customer Number as the Account, and value "ShopID" that matches the Customer number
    • by having the same customer number, you can get addresses from the Account (User Group)
    • by having a different "ShopId", you can get multiple dw users with the same username (email)
    • by having unique DW users, we can overcome the issues I've been experiencing
  • New features in DW allow you to Switch between Profiles (users with the same username)

 

All that to say that, it justifies using JWT tokens instead of FixedSecret, because you'll tend to have multiple users with the same username. Already in R1 you have the endpoint to return the profiles. Some of the UI features (i.e. listing subgroups in a list instead of tree so we can also search) are still being finalized.

endpoint: /dwapi/docs/index.html?url=/dwapi/api.json#/User%20creation%20%26%20management%20>%20User%20information/Users_GetProfiles

 

Hope this helps,

Nuno Aguiar

 

 
Anders Ebdrup
Reply

Hi Nuno,

Thank you very much for the detailed explanation!

Your description of the new Login/Profile approach is extremely helpful. Especially the part about how separating Login users and Profile users (with shared usernames but different ShopIDs and Customer Numbers).

It makes perfect sense that this new model naturally leads toward using JWT tokens instead of a FixedSecret, since having multiple DW users with the same username would otherwise cause conflicts. I really appreciate the insight into what is already available in Ring 1 and what is still being finalized - that helps a lot in planning ahead.

One quick question: 

Do you know when the remaining features of this new approach are expected to be fully in place in DynamicWeb?
Thanks again for taking the time to explain this! It’s extremely valuable!

Best regards,
Anders

 
Nuno Aguiar Dynamicweb Employee
Nuno Aguiar
Reply

Hi Anders,

 

Short answer: I do not know. But the "remaining features" may not be important to you, but you can already play with switching profiles. 

 

Currently:

* You already have a way to switch profiles. There's an endpoint that returns you the Profiles https://doc.dynamicweb.dev/webapi/delivery/delivery-api-test.html#/User%20creation%20%26%20management%20%3E%20User%20information/Users_GetProfiles

* You'd then get back a JTW token for each profile

 

And assuming you're doing a headless implementation (if you're using JWT tokens), you can just use the appropriate JWT token (of the desired profile) to handle your requests.

 

The way we're essentially handling is our frontend application manages 2 JWT tokens. One for the Login, to do things like showing generic information and password updates and another for the "active" Profile, which is then used for almost all endpoints.

 

What's mainly missing are some UI features to view/manage the data, specially with big amounts of data (i.e. list user sub groups as a list in the main pane and having the ability to search and paginate; viewing/edting addresses on user groups - because that's where we'd import addresses tied to a customer number,...). The main thing we're waiting for though is a way to update groups (using the delivery api), because we're using a different group type for Roles. That allows us to have:

  • Each proflile can belong to different Roles
  • Because Roles are user groups, we set permissions (in the backend) on Roles
  • And some admin users will have the ability to update Roles for other users - hence the need to have it in the delivery api

 

So again, you might not need what I'm waiting for. Take profiles for a spin ;)

 

Best Regards,

Nuno

 
Anders Ebdrup
Reply

Hi Nuno,

 

Thanks for the detailed feedback.

For the Profiles concept, at least as I understand it, then users should have the same username, but that is an issue because if you have several users with the same username, then you cannot update the users in the administration as it does not allow dublicated usernames. So I think another field linking the users should be used.

And for the Account concept, then the use case that I see the most is customers linked together through the BillTo-reference in the ERP-system (or some other field e.g. a discount group), so again; can these be a custom field that can be used to link accounts instead fixing it to the CustomerNumber?

 

Besides these concerns I really love the tought of being able to work with profiles and accounts :-)

 

Best regards, Anders

 
Nuno Aguiar Dynamicweb Employee
Nuno Aguiar
Reply

Hi Anders,

 

You can have multiple usernames, as long as the field ShopId is different (odd naming though). In our case we'll be setting the customer number value in the "ShopId" field (as well as in the Customer number field) to properly allow for the "duplicate" usernames.

 

As for the Accounts concept, for now it's the Customer Number field in DW. In theory you don't need to set the actual number, meaning you can import the BillTo-reference from the ERP. There are already a number of changes in multiple apps (i.e. getting addresses by customer number instead of user id) using the Customer Number (sort of as ExternalId), so it will be hard to break away from it, at least right now.

That said, if you are looking for things like "Discount groups", what can be done is adding information to the Profiles (since they are a distinct user associated with a single account), that would help populate a segmented search, which would then populate a user group, that would then be used on discounts, payment providers, shipping providers, assortments and some other custom features (that's how we've been doing these in the past).
I know creating these groups directly from integration is not simple at times. We tried in the past to integrate creating User Groups (aka Price Groups) and have integration place them directly there, but the return on investment at the time (and overhead) was not great. And changes were harder to implement. We eventually decided to simplify and bring over data to the user record, and then have smart searches (currently known as segmented searches) to populate user groups. That removed complexity from the integration and allowed us to be more flexible in the configuration side.

 

I am also really loving the ability to standardize Accounts and Profiles. It's been a real headache for me over the years with the amount of customizations we had to build in the past, preventing/breaking some features from DW from working.

 

Nuno

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

For the UI to allow duplicate usernames, all users need a shopid.

I have just made a proposal to the architecture team to change that so you can have a user with the same username - without a shopid and one with shopid, which behaves as fallbacks right now. E.g. if a user with username "A" tries to login with shopid=shop2 - and that user does not exist - then it falls back to the user "A" with no shopid. That is not very explicit. That change would be a change of behavior. So needs discussion.

 

You must be logged in to post in the forum