Securely Persist Local Data in .NET MAUI (Secure Storage)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
many applications have certain pieces of data that should be persisted locally in a secure way such as authentication state or other secret settings but in a.net Mallet application where do we store this data now I have this Maui application where users can log in Via Firebase authentication so we can sign in however whenever we close the application and boot the application back up our previous signed in state is lost and we have to re-authenticate so ultimately I want to persist this authentication State between sessions so what should we do here maybe we could store the authentication state in a local database but that would be a bit too heavy maybe we could write the authentication state to a local file on our machine but that might not align with Maui's cross-platform abilities and it might not work on other platforms such as mobile so alternatively let's store our authentication State and Maui's built-in easy to use Secure Storage via the Secure Storage API so first we're gonna have to set this up and as we can see here there is no additional setup required for Windows and as of now our application is really Windows only but if we were deploying our application to a different platform such as iOS or Android we would need to follow these additional setup steps which I'll link in the description now as I mentioned we are using the Firebase authentication SDK in order to authenticate users and this SDK in particular has built-in support to save authentication State we just need to tell the SDK how to save the authentication state which we once saved in Secure Storage so we're going to configure that real quick by defining a user repository and we're going to create some kind of Secure Storage user repository so let's create this we'll put it in a new file now let's implement this iuser repository interface part of Firebase auth this is the interface we must Implement in order to use this repository with our Firebase authentication SDK now as we can see by this read user method response there are two pieces of data that we need to store in Secure Storage the user info and the user's Firebase credential now Secure Storage is basically just a key value store so we're going to need keys in order to store these two values so let's add our first key for the user info and another key for the Firebase credential we could really make these Keys anything we want let's start off with saving data to Secure Storage so this data we're trying to save such as the user info and the Firebase credential it's not Primitives we're dealing with objects here so the way we want to store this is by stringifying it to Json and then just writing it to Secure Storage so the first thing we want to do is turn our user info into Json so we can get that off of this user we get passed in and we're going to use the Json serializer to serialize our user and we want to do the same thing for our Firebase credential which we can access on this credential property let's import Json serializer from system text Json and now we just have to save this Json to Secure Storage so let's take Secure Storage accessing it via Secure Storage default and we want to set a value via set async and again Secure Storage is just a key value store let's pass in our key so we're setting our user info to our user info Json and let's do the same exact thing for our Firebase credential setting the credential key to our credential Json now you might notice accessing Secure Storage is async but this interface that we're forced to implement is not async so to work around that let's just tap on a get a waiter get result in order to try and run this synchronously but ideally you should never have to do this and hopefully you're just working within an async method and you can simply await this set async method now also any of this could fail so let's wrap it in a try catch and I'm actually fine just eating the exception here if we can't save the user who cares that just means we'll have to manually re-authenticate when we reopen the application so that covers saving data to Secure Storage now what about reading data from secure storage so let's see that by trying to read the user credentials that we just saved so right off the bat let's actually wrap this in a try catch and if anything fails when we're trying to read the credentials from Secure Storage then we'll just return null for the user info and the credential so first let's grab the user info Json which we previously saved and to do that we'll take Secure Storage grab the default instance and call get async passing in our user info key which matches the key that we use to save the user info and again we're getting destroyed by the fact that read user is not async so we're gonna have to call get a waiter get result unfortunately but again hopefully you won't have to do this in your own application so first reviewed user info Json then let's read the credential Json passing in our credential key and now we're basically doing the opposite of what we did to save the user but now after reading the user Json we want to deserialize that into an actual user info object object so again taking Json serializer this time calling deserialize getting some user info and passing in our user info Json and we'll do the same exact thing for the Firebase credential and now that we have both of these values we simply just need to return them via this weird Tuple works for me so that covers reading and writing to Secure Storage but one more helpful operation to cover and that is clearing data from Secure Storage so whenever delete user gets called by the Firebase authentication SDK we want to remove the data stored in our user info key and also remove the data stored in our Firebase credential key and the remove method on Secure Storage is actually not async so we don't have to do any weird getawayter stuff and lastly I'll just show the implementation for user exists so for this we're just going to read the user so basically getting it from Secure Storage and parsing it and then just checking and making sure that both of these value values that we get from Secure Storage are not null and if they're both not null they exist then we do have a user stored and our Maui app is actually deadlocking on Startup I think that's because the Firebase auth SDK cause read user on Startup and we're doing all this funky async stuff to run all of this synchronously and there we go I was able to work around this by instead wrapping get a sync in a task.run and then extracting the result from this so as always trying to call asynchronous methods synchronously not a good idea you should not do it unless some kind of interface is forcing you to so again hopefully you're not forced to do anything like this when using Secure Storage and you can just call it asynchronously as it should be but now let's sign in and we hit our break point saving our user so let's serialize this user info there we go serialize the credential there we go and then we save each of those values to Secure Storage so now let's boot up the application again and on Startup we read the user so first we're reading the user info which we successfully get from Secure Storage we also read the credential there we go got it let's deserialize both of those values there we go both of these look good success and we successfully returned the user info and the Firebase credential so Secure Storage and dotnet Maui super easy to use the last thing I wanted to show is that instead of digging into this Secure Storage default instance everywhere you could depend on an interface so for example we could have a field up here for an i Secure Storage and we could get that injected through the Constructor and then simplify everywhere to depend on this field we have on our class now there we go very nice no longer digging into this Singleton instance from everywhere and then we can move up to our Maui program and now we can pass in our Secure Storage from up here but actually let's just dependency inject everything so we could register and I Secure Storage independency injection as our Secure Storage default instance and then we could even now register an iuser repository for our Firebase auth client to point to our Secure Storage user repository which we can now resolve down here by registering this as a callback that takes our service provider and now we can take this service provider and resolve whatever I use a repository that we have registered independency injection which is our Secure Storage user repository which is going to resolve our default Secure Storage instance so just a little monitor tip there doesn't really matter if you directly reference securestorage.default throughout your application but some people might find it helpful to depend on interface as much as possible aside from that getting back to the power of Secure Storage we can now easily and securely read data save data clear data Etc in a cross-platform supported manner for our.net Maui application so hopefully apply this to your own.net application to easily and securely persist local data [Music] [Music] foreign
Info
Channel: SingletonSean
Views: 1,073
Rating: undefined out of 5
Keywords: wpf, programming, visual, studio, xaml, custom, control, generic, system, line, display, timer, template, binding, c#, how, to, series, tutorial, easy, time, maintain, package, design, code, register, static, state, default, view, void, model, user, data, error, icon, class, clean, simple, sub, host, rule, logic, list, app, maui, type, isolation, asp, net, api, test, unit, mvvm, guard, check, return, patterns, interface, property, pattern, best, practice, extract, brittle, mock, moq, abstract, secure, storage, persist, database, file, secret, auth, access, token, refresh
Id: eeJske-Tu40
Channel Id: undefined
Length: 9min 23sec (563 seconds)
Published: Thu Jan 25 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.