C
C#•2w ago
NotAGenuisGuy

Refresh token on Browser reload

I am trying to implement jwt authentication with refresh token logic for my school project. Refresh tokens are stored in browser HTTP cookies with CORs enabled. They are also stored in Mssql db (I'm thinking to change to redis) in server. My frontend is blazor WASM and my backend is Web API with FastEndpoints. Right now, I can't refresh the refresh token on browser reload. I have implement a refresh token refresh in frontend program.cs in the picture attached. But, that code is not being run everytime the browser refreshes. I have also attached the Jwt Authentication State Provider. Any suggestions are welcome as I am still learning on improving my code 🙂
No description
No description
25 Replies
NotAGenuisGuy
NotAGenuisGuyOP•2w ago
These are the refresh token logic in Backend.
No description
No description
Kuurama
Kuurama•2w ago
At least use Nullable properly with '?', You can enforce thing by treating warning as errors in the csproj. Nullable is nothing to really ignore, it's a pain to get used to writting the code properly and use null when it makes sence, knowing your way around it and the keywords to use (You can also initialize with = null!; to make it shut when you know it won't be null because it's gonna be injected. You can also just use the required keyword most of the time).
Kuurama
Kuurama•2w ago
I also believe FastEndpoints have different overrides where you can return directly the Response instead of writing it yourself. That way you can prevent some logic errors, and I assume it might also make a future OpenApi doc you might generate better. https://fast-endpoints.com/docs/get-started#union-type-returning-handler
FastEndpoints
FastEndpoints
FastEndpoints is a developer friendly alternative to Minimal APIs & MVC for rapid REST API development.
Kuurama
Kuurama•2w ago
Another tips: Don't use DateTime.UtcNow, why? Because how do you test it? (And it depends on a state you don't have control on, its not pure) The proper way is to inject a time provider, there are many techniques, but the default way is injecting the TimeProvider From System.Runtime, and use it that way:
timeprovider.GetUtcNow();
timeprovider.GetUtcNow();
When testing it, simply inject TimeProvider.System if you need the default behavior (It's a static property). overwise just make your own time provider by making one that inherit it (its an abstract class). Some directly inject a Func<DateTimeOffset>, but I don't think that its a good thing to start with, nor something that is very common. It's just to show off that there are many ways you can inject Time, TimeProvider is the default microsoft recommended way to do it. As for the naming, what is the purpose of ending the request record with 'DTO'. As far as I'm aware, you only have the DTO variant, since it is the response dto. DTO naming is therefore useless, it's just boilerplate. You can find them by just searching for "Response" already, if that's your concerns. I would say always put a space after a Early return statement. Which you condenced too much under LoginWithRefreshTokenAsync. No one likes that, might look cool in your head that it's condensed, in fact, its ungly and hard to look to. Try to organize the code in parts, like one where you prepare the variables like the generate token thingy, then you put a space because you are about to run some IO, it's clearly another step that is not totally related to the things prior. Therefore you can clearly distinguish when you save the db from all teh previous things, and then another space so you return. Less space doesn't mean better, too much is also bad. But there is a nice in between you will find. Nothing hard to do, its just natural after a while. Not a fan, but At least put the readonly keyword to the NonAuthenticatedState declaration, I don´t think you wanna modify this by mistake. Of course, you might think its unlikely, but it doesn't excuse that you don't code with intend in mind. The type system is something to look after when making production grade code. You might not work alone later, so better prevent one colleage doing a funny, by just getting used to this kind of things. Always make sure you can do as much as you are allowed to do with your types. I also don't think the State management Should be accepting null Listen to the compiler. You are setting null to something right? It means you kinda wish to have that other state. What does that state describe in your app? That the user is Not Authenticated correct? And what do you have? oohhh, a Static readonly NonAuthenticatedState;, how convenient? Stop using null on it, just set the private state to NonAuthenticatedState. It doesn't make much sence having 3 states with 2 describing the same thing. I really really mean it when I say, listen to the compiler, don't set nulls things when you didn't declare them as nullable, Billion dollar mistake here remember. Either question why the fuck you try to do this (in this case, it was non needed and a mistake), and if you need, always please the compiler with proper nullable declaration, try to shut it the least amount of possible. @NotAGenuisGuy When you are done with the changes, send another pick, ping me and I will take a look.
NotAGenuisGuy
NotAGenuisGuyOP•2w ago
I have not finished implmenting time provider but I did the following changes
NotAGenuisGuy
NotAGenuisGuyOP•2w ago
I removed null for Auth State, so rn the authenticationstate is going to return either Authenticated or NotAuthenticated
No description
NotAGenuisGuy
NotAGenuisGuyOP•2w ago
I did not really fully understand how to implement this for the rest of my code, but I did what I understand, for the RevokeRefreshTokenEndpoint
NotAGenuisGuy
NotAGenuisGuyOP•2w ago
No description
NotAGenuisGuy
NotAGenuisGuyOP•2w ago
No description
NotAGenuisGuy
NotAGenuisGuyOP•2w ago
I also changed the names for DTOs I understand putting the DTOs in SharedKernel where both frontend and backend can access is a bad idea, I will seperate them in the future
NotAGenuisGuy
NotAGenuisGuyOP•2w ago
No description
NotAGenuisGuy
NotAGenuisGuyOP•2w ago
Did thereadability changes
NotAGenuisGuy
NotAGenuisGuyOP•2w ago
This is the logic to refresh RefreshTokens
No description
NotAGenuisGuy
NotAGenuisGuyOP•2w ago
I also understand injecting HttpClient directly is not a great idea for testability, so I will be making a service class for it Right now the biggest problem I still can't solve after many hours is refreshing the refreshtokens on browser reload Oh and btw, if possible can you please give me some feedback and tips on jwt standalone auth? I'm really new to jwts so there might be some rookie mistakes that I made Thanks
Kuurama
Kuurama•2w ago
you can early return false here to avoid nesting, you then put a space after the return false;
Kuurama
Kuurama•2w ago
maybe this would be better with the union return type override https://fast-endpoints.com/docs/get-started#union-type-returning-handler
FastEndpoints
FastEndpoints
FastEndpoints is a developer friendly alternative to Minimal APIs & MVC for rapid REST API development.
Kuurama
Kuurama•2w ago
But yeah, I'm not the one that will help you with your current problem. I never done blazor stuffs sorry. Since you said you would still like feedbacks, that's what I'm providing haha. Assuming having front end be a C# thing, to follow why they also make some typescript backend, it does make sence to share the request/responses dto between front and back One tips would be actually watching content relative to the theory behind jwt and refresh tokens I like to draw the flow on a whiteboard before hand. How funny to use such an opinionamed lib for a school project as fast endpoints It hides quite some things. I would say it would have been better learning the basics with minimal api. Organizing them isn't a given, you have to find ways. I personally organize them just like fast endpoint anyway lol. But yeah, native validation + blazor included deeply nested validation and all only got included in .net 10
NotAGenuisGuy
NotAGenuisGuyOP•2w ago
I chose it mainly due to its organisation and structure I felt like organising minimal apis is a bit tricky Not that it’s impossible but I like how endpoints are in fast endpoints and ofc a lot of things it brings like validation and stuff Can you please elaborate more on 5ag *that .net 10
Kuurama
Kuurama•7d ago
dotnet
YouTube
Blazor Community Standup - Blazor validation improvements
The new validation support in .NET 10 aren't just for Minimal APIs - they're for Blazor too! Join us to check out the new validation improvements for Blazor ...
Kuurama
Kuurama•7d ago
As for **organizing minimal apis••, just copy this: https://github.com/GuildSaber/GuildSaber/blob/main/src%2FGuildSaber.Api%2FExtensions%2FEndpointsExtensions.cs It is something very commonly see, even sume paid courses uses this exact approach. To then register it in your app, do: builder.AddEndpoints<Program>(builder.Configuration); then when it's built: app.MapEndpoints<Program>();
GitHub
GuildSaber/src/GuildSaber.Api/Extensions/EndpointsExtensions.cs at ...
Contribute to GuildSaber/GuildSaber development by creating an account on GitHub.
Kuurama
Kuurama•7d ago
GitHub
GuildSaber/src/GuildSaber.Api/Features/Guilds/Members/MemberEndpoin...
Contribute to GuildSaber/GuildSaber development by creating an account on GitHub.
Kuurama
Kuurama•7d ago
Of course, you can check the overall structure I use. however, this is not blazor. Axd I don't think you should check the logic too much, I use a library that gives me a Result and Maybe monad, it's quite an advanced way of pipelining code. Not something you are ready to peek into yet. But basically I kinda think that a project at this scale can benefit from a vertical slice feature based architecture: Features/ |-> Auth/ |---> AuthEndpoints |---> AuthService |---> AuthMappers |---> AuthResponses |---> AuthEndpoints |---> AuthRequests (if needed) |-> Users/ |---> UserEndpoints And so on. You can obviously break it appart weth subfolders for specific features. Like huum, Auth/RevokeRefreshToken/ But that might be overkill sometime. But you cas do just that if you prefer! But given the logic is often small. And that the default way of writting apis was with controllers where your features are within 1 class. This is alrealy good enough. Since you use blazor, you might have sligtly different organization needs. But that's exactly where even the default non opinionated minimal api can shine, you can just structure it as you like. Of course you enforces structure in a big project, i still find sad that microsoft doesn't show a small structured way like i showed you as an example haha. They just go: yeah organize as you wesh indeed, it's not meant to stay in one file. Too many devs believes it's only good fov small stuffs, I hate it. They just don't know the tech lmao. Does that make sence? @NotAGenuisGuy Not saying you should throw fastendpoints in the bin. It's just that it's third party and opinionated (opinionated can be good), some entreprise just refuses to work with code Microsoft or themselves don't control entirely. (since fastendpoints uses many different third party package too) And licensing rules and stuff, I forgot if fastendpoint uses fluent validation. Now that comes at a cost depending on how much your entreprise makes money or something. But since .net 10, validation just works on minimal. You could install the .net 10 Rc1 release and bam. It's official build is due to november, but it mostly just works out of the box. I don't think it wouldn't work out fov your school project. You can use it. In my project, there are some things in a Transformer folder, that is for OpenAPI documentation stuffs. (I use the official microsoft.openapi package, and it lacks features I'm adding via their way of hooking with the generation process, quite cool do to.
NotAGenuisGuy
NotAGenuisGuyOP•6d ago
May I ask one question So I found out about hybrid caching I’m a bit lost on where to implement that cache. i.e API layer or front end layer Giving another think about it, you are definitely correct on minimal apis If only I had known about .net 10 minimal api validation in advance and if only my project isn’t due before .net 10 official release
Kuurama
Kuurama•6d ago
If your teacher doesn't care about the realease candidate status, that might be fine ngl. You can still ask them if they are okay with a release candidate version It's an easy to install as the normal version anyway @NotAGenuisGuy Caching only really make sense when you face the need to cache anything really If, lets say, you see there is a hot path in an endpoint and the users are pretty much spamming it and most requests are redundent, that is when you want caching. I don´t really know how caching would work but it's only beneficial when going through the cache is faster than directly executing the request. Which is not always the case if the cache is also a database and if the request is simple. Here, an in memory cache could still work in the case that the latency between the db and the server is the bottleneck.

Did you find this page helpful?