 So now we're going to talk a little bit about security, which similar performance is very important for DHS2 applications to keep in mind. It's important for a number of reasons, but one of them, I mean, obviously for its own sake, security is important, but it's also important for all the applications in DHS2 to take security seriously, because if one application is being used in the DHS2 instance and has a security vulnerability, it could compromise the entire system and all the other applications as well. So it's important to be a conscientious member of the DHS2 community by creating secure applications. We're going to talk about some specific steps that you can take to secure certain parts of DHS2 apps. This is not going to cover everything. There's a lot of additional details that we'll need to get into in the future as well. So for some best practices, we will be creating a dedicated security guide soon on the developer portal, but for now there is a good kind of baseline guide available in the app hub guidelines. There's a security section in this guide, which gives you a number of concrete recommendations to use in your applications, when specifically for these are things that we will look for when reviewing DHS2 apps that are submitted to the app hub, but if they're good guidelines to follow in any case. So let's start with data store security. We talked about using the data store yesterday. We talked about the app service data store. We used that in the example that I went over this morning, but there are a few security considerations to keep in mind when you are using the data store to store information. The first and most simple is that you can reserve a namespace in the data store for your app, which prevents other applications from reserving that namespace. And it allows only users that have access to your application to see the reserved data store namespace. And that applies to both the data store and the user data store. And if you're using a data store namespace, except for certain situations where you expect to share that information in that namespace with other applications or other users that don't have access to your app, you should always add a reserved namespace to your manifest file or your d2.config.js file as we saw in the example earlier this morning. You should also make sure that the namespace you choose is unique to only your application. And so you don't want to choose something that another developer will also choose and then you'll have conflicts. So one of your applications won't be able to be installed and the other one maybe if they are, maybe one of them is not reserved, then you'll have conflicts with the two apps trying to use the same data source. This is how you reserve a namespace in d2.config.js and a d2.config.js application in a platform app use d2.config.js and set the data store namespace key to the name that you want to reserve and then manifest that web app for non-platform applications it's in the activities djs2 object space. And second, once you have reserved a namespace or if you're using a namespace that you don't want to reserve because you want to give access to other users and you can set sharing permissions on the specific keys that you're using in the data store. And this is for the global data store rather than the user data store and basically you can set sharing just like you can with any other metadata in djs2 things like an indicator or program, a visualization, a dashboard all of those use the same sharing system under the hood. By default, when you create a new key in the data store it can be read and written by all djs2 users. So if you're creating a new data store key use it carefully and then you can use the sharing endpoint to set the sharing settings on djs2. You can, or on the data store key. I didn't include a link here, but I'm going to add it. You can find information about how to do this in the developer documentation. This is the API docs where you can find everything that has to do with the djs2 API in the data store section. It will tell you how to get keys and namespaces from the data store, how to create new values, how to update values, how to delete values and then also how to share data store keys. So this will allow you to set the sharing settings with an object like this for a particular key in the data store. I'm going to go ahead and include that in this slide now as well. So when we share that, you will have access to it. There you are. Okay, this is something that we will be adding to the app service data store in the near future but it doesn't exist today. So if you want to use the global data store and you want to share your saved objects or your settings key with other users, you're going to have to use a manual HTTP request or a data query in order to do that today. But in the near future, we hope to add sharing to that library as well. Talking a little bit more generally about credentials, it's recommended never to store credentials in the data store. This means that if you're allowing your user to, for instance, enter DHS2 credentials that then another user can use with basic authentication or something like that, that's not a good idea. I would say that you should never store DHS2 credentials in the data store because then you're kind of defeating the purpose of the fact those credentials exist because you're storing the credentials in the thing that you need credentials to access. In some cases, it can make sense to save credentials for external systems into the data store. I'll get into a little bit more of some recommendations of how to do this more securely, but in some cases that can make sense. And in those cases, you should always, if possible, store those credentials in the user data store. So they're specific to a particular DHS2 user. And if you're using the global data store, you wanna make sure to set the sharing permissions very narrowly. So you want to at least make it so that no one can, no one else can write those credentials without having certain privileges. And probably in most cases, you want to also restrict who can read those credentials because they should be considered very sensitive. And then the third thing that you can do to help secure credentials when they're stored in the data store is to set the encrypt equals true flag. This, it's again, I'm gonna go back to this documentation here. It talks about the encryption. You can pass encrypt equals true when getting or setting a key in the data store. And that will basically let you encrypt and decrypt data at rest in the DHS2 database. And so if you're storing credentials, which again is not recommended generally, you should use this encrypt equals true flag. There is a flag that was recently added to the data store provider for the app service data store to enable this encryption, which you can use, but it is very, very nascent, very new. So make sure that you're kind if there are issues and feel free to contribute back to that library as well. That's again, something along with sharing that we'll be pushing forward in that library as we move it into a more formally supported library as part of the app runtime, rather than as a separate proof of concepts library. So that should be coming soon as well. This kind of goes without saying, as we mentioned, but I've seen it in a few applications that try to do this, but you should never have DHS2 credentials used in the browser that are not the session cookie that the user already has. So in your application, the user that's logged in already has a session that's authenticated with cookies. In some cases, it might be tempting to say, like save somebody else's credentials into the data store and then use those credentials from the browser with basic authentication to talk to DHS2, but that is a pretty glaring security hole and you should not do that. And there, as far as I know, there aren't legitimate use cases to do that for the DHS2 server that you're talking to. So be very careful if you're going down that path and think about it quite a lot. That goes along with the user authentication model. So in our authorization model, in DHS2, you have users. You have user roles that those users can be assigned to and you also have authorities. So an authority is assigned to a user and it gives the users with that role some permissions. That might be the ability to write a particular indicator to update it. It might be the ability to create new dashboards. It might be the ability to view data at a certain level in the argument hierarchy. It's recommended or required that your application should use that data model, use that authorization model and shouldn't allow users to kind of step outside of that and have more permissions than their user gives them, DHS2 gives them as a user. That's why you shouldn't be impersonating other users. It means that you should use that system whenever you're interacting with the API. Similarly, every installed DHS2 application is granted its own authority. So when you install a new app into your DHS2 instance, you will see in the user's app a new authority that you can assign to users that gives them access to that application. I can quickly demonstrate that. Okay, so we're gonna go to the app management app which gives us a number of applications that have been installed here. I'm gonna look at relationship tracing, first of all. So this is an app that has been installed that we can look at. Recommend that everyone, maybe take a look at this application as an example of some good things that you can do in a custom app. This has some interesting, I don't have the right permissions on this one, more if I'm in the right case. Anyway, I need to think about how to build this visualization for particular relationships between different, different objects. Probably need to do this. Nope, okay. Anyway, I'm not gonna dig into that too much, but this is an application that's installed into DHS2. And I can then go to the user's application, go to a user role. Let's say I wanted this to be available to everyone with the Child Health Program Manager role for instance. So in this list of apps, we'll see that there is a relationship tracing app down here at the bottom. And that uses the short name of your application. There's also the query playground app and some other applications as well, Scorecard is another installed application. So if I wanted to grant access to this application for this user, which also would give them access to the reserved namespace for this application, I would select that and then click save. I'm not gonna do that here on the server, but actually I can, it's fine. So then any user with the Child Health Program Manager role now has access to that relationship tracing application. So every app has its own authority which grants access to the app, but also grants access to the namespace that has been reserved by that application. And in addition to that, in your DHS2 app, you can create custom authorities which will show up in that user management application. If we go back to this here, there will be additional authorities that are created. For instance, these are authorities that were created by the bottleneck analysis application for certain things like adding interventions, adding root causes, and these can be assigned, these fine grained permissions can be assigned to specific users or user roles so that they can perform certain actions within the application, but not others. It's important to note, however, that these do not provide any real security out of the box. Basically, they just give you a way to assign a role to users, but because they're not enforced on the server, they don't provide any real security benefits out of the box. You can use them to increase security significantly by using a custom backend service to basically check that the user that's making a request has a certain role before performing some operation on the backend, but because they are custom, the DHS2 core itself doesn't know what to allow and what to decline for those authorities, so it's used more often to show and hide different parts of the user interface of your application to different user groups. Another security guideline around communication with external servers. When you're communicating with an external server, for instance, DHS2 to DHS2 metadata sync or DHS2 to GoData sync or any other kind of synchronization from DHS2 to something else, I would always recommend that you perform that synchronization server side. This means that credentials can be saved and encrypted so that the user can't read them again in the browser, which is much more secure than transferring it over the network all the time. It's much more performant also because the server is going to be online, it's gonna have access to the two other servers, it's more secure because it's behind potentially a firewall and it don't need to send all of the information through the browser from one server and then out to another server again, which can be quite slow and prone to network troubles as well. So I would always recommend that you do synchronization with a server side component. You can use an application to configure that component if you'd like. I know that that does significantly increase the burden for development, but also for system administrators to set up an additional server component, but it's much more secure and it's never secure to transfer and store credentials in plain text. So when you find yourself doing that, just be wary that that might not be a good thing to do. In the near future, we're hoping to have better tooling for setting up and hosting these server side components and maybe even in a kind of Next.js style through an application that can define its own backend services. In the meantime, cloud hosted services are an option in some cases as an easier way for implementations to spin up and scale integration and server side componentry that maybe they don't want to manage or maintain on their own service. Finally, I want to talk quickly about cross-site scripting. If you're not familiar with cross-site scripting, you can look it up online. It's a fairly well-known attack for websites or web applications. And the basic concept of it is that if a user can enter some information and then the website puts that information directly into the content of the site, then there's a chance that that user could enter something malicious like a script tag that runs some JavaScript and does something bad and you don't want to allow them to do that. So whenever you're displaying anything that a user has entered, even if that user is an admin user that entered it a long time ago in the DHSU database and you're requesting it through the API, you should always sanitize that information before rendering it to the DOM. That means that if you shouldn't just say element.innerhtml equals the result of this API request because that will basically replace the innerhtml which could include a script tag. So you need to escape the contents of that script tag, et cetera, et cetera. Luckily React does this for you in most cases. So unless you use dangerously set innerhtml which I wouldn't recommend that you do, React will automatically sanitize anything that it renders to the DOM in most cases so that you should be mostly safe if you're using React in a normal way. If you're not using React or if you're using React in a very kind of advanced way just be careful that you're not rendering anything from the API or from user input into the DOM of the page itself. If there is a cross-site security vulnerability, it could mean that someone could steal all the data from DHSU and that that could happen without the user knowing. So this gets back to the first point that I made which is that if there's one insecure application in the DHSU implementation then it means the entire DHSU implementation is insecure and there are big problems potentially for data and user security. That's a quick, very, very high-level, quick overview of security for DHSU web apps will now open it up for questions. If anyone has any questions for me about security we can talk about those now. And if not, that's okay too. If everyone is lost, that's okay too. I didn't see any question coming in. Okay, no questions coming up yet. Okay, do you have a checklist or template? Abumai is asking. So the guidelines for the app hub submission are a good kind of checklist that you should go through when you're looking at your application to check for some common security issues. Like I said, we will be adding a guide for specifically around security. But for now, the best place to look is that app hub submission guidelines which I can show again somewhere. You go to guides, app hub, app hub submission guidelines and then scroll down to the security section. So there's quite a few kind of best practices here and we'll be adding more to an additional guide. Good question though, thank you. Okay, with that I think I need to upload the example that we're going to work on as for the exercise. It's not gonna be a long one. It's gonna be a little bit open-ended but hopefully we'll get some good feedback and some good kind of exploration of an application. What I'm going to do is I'm going to upload an app to the Academy repository. It's an open-ended exercise where you should find and fix as many performance and security vulnerabilities as you can within this application. It's a fairly simple app and I'll upload it in just a few minutes. And then we can go ahead and do that. There are quite a few that are very obvious and maybe a few that are more subtle performance and security issues in this application that you can take a look at. So with that I think, so I can have a minute to upload this, why don't we come back in three minutes, take a quick break and we'll be back right at half past the hour here in Central European time for the exercise for this session and then we'll be done for today.