Keycloak Angular Integration Guide | OAuth 2 + Express Server

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
by end of this video I'm going to show you how to integrate the keylocks login screen in your angular application so we are going to create this awesome looking Netflix clone website which basically shows movies and uh we are going to integrate a login screen of key loock in our angular application and uh not just that I'm also going to show you how you can protect your backend apis using the Au zero concept so we are going to implement additional layer of security for our backend API so that whenever any backend call happens any HTTP request happens to backend all are all the request should have the authorization header in it has the better token and that will utilize in our pend application to check whether the request is coming from the valid client or not so this video basically covers both the front end part where we are going to protect the front end login screen of key clock and uh at the backend side we are going to have the express server running which will be Bally protect all our API routes and don't worry if you don't know how to set up the KY loock because in this video I'm also going to show you how to install and set up the key clock instance on your Local Host 8080 port and that is via Docker image so I'm going to tell you all the steps from the scratch and additionally I'm also going to touch a topic of external identity access management provider which is Google in this case so you can add a sign in with Google or sign in with GitHub or external identity provider button so I'm going to touch that topic Al I'm going to show you how you can do that in a key clock using a key clock before we start coding I want to uh request you if you have not subscribed to my Channel Please Subscribe because seeing that support from you it motivates me and if you like this video then you can watch another videos on my channel I make the videos about the software engineering and also uh make some videos about how to prepare for the job how to look for the job abroad how to prepare so you can look for for the relevant videos on my channel and if you really like the content subscribing to my channel is a really good way to show a support so let's start with the step number one we need to set up a ky lock so we can install a kyck lock in uh two ways one is the native installation where you download the K loock binaries and the installation file and you set it up on your operating system another one and which I also recommend you to you guys and the one I'm going to do in this tutorial which is the installation via Docker so you just have to go to the keylock org and get getting started with a Docker so what we are going to do is we are going to run the key loock image in a Docker container and uh that is basically most safe way to run the docker uh to run the key clock and you don't have to do the installation by any of by yourself so for that for for this method you need to have a Docker running in your operating system so if you are using Linux you can install that using uh command lines using few commands that you'll find on the docker site if you're using a Mac or windows then you can install the docker desktop application like me and that will basically install all the necessary runtime environments required for your Docker images to run so once you have a Docker desktop setup uh you can just come to the keylock website and copy this command so I'm going to open my terminal and I'm going to put this command in my terminal so it basically pulls that image from the internet as you can uh see over here it basically pulls the image and we have given the uh server URL for that image which is this one QA y.i key clock it is pulling that image it basically pulls that image and put that in our local Docker container and then it basically uh at the end will show you that running the server in the development development mode so then you can just simply go to your Docker desktop and now if it's running successfully then you can see that there is a uh key clocking image running over here and if you have to verify whether the key clock image is running correctly or not then you can simply go to Local Host 8080 and then you will see your key clock interface like this over here I'll just minimize this thing here over here and then you go to Administration console and by default the username the password that you have to provide is the admin admin uh so then you log into your uh key clock and here you can see the interface for the key clock now before we go to our uh angular application and to our back end uh we have to set up few things in our key clock so we have to set up the client we have to create at least one user we have to create a role group and uh there are a few configuration that uh you have to do in your key clock uh so you can create a real from here so U real is basically like an environment which contains the clients inside it uh so for the sake of this tutorial I'm just going to stick with a master real and uh I'm going to create a client under master real but if you have a much complicated scenario uh then you can create a multiple real or create a custom real and add the clients under that so I'm going to Simply hit the create client and I'm going to name this as a tny Netflix uh as my client ID and uh name and the description are the optional fields then I'll just simply click on next and remember you have to turn this off client authorization because it basically means uh you can allow this uh client to be authorized from some external website then you go to the login settings and here you have to provide the root URL on which you are going to use your you're going to use this kick loocks login screen so I'm providing my Local Host 4200 over here and the valid redirect uis are basically Uris to which once the login has happened it should redirect to so I'm going to 4200 SL star because there can be multiple routes under my Ang application I'm also giving the URL of my backend Services which is going to be 090 I'm going to run my Express server on the local 90 server that's why and again I can put slash star something like this and uh yeah web Origins if you just hold it can show that allow course or to permit all the valid origin so I don't want to get a cuse error that's why I will simply put a plus over here uh but if you are running it in a production then I don't recommend doing this you can put the specific URL of your domain and that will basically uh prevent the Cs eror from happening so with that I will just save that and then uh you will have the standard flow and the direct access Grant uh enable by default then you can choose the login theme so I'll go with the key clock over here here and um and just save it then I will create one sample user so I will cck create add user in a key clock if you have to prompt user to verify their email or configure OTP or change their password you can choose the action from from here but in my case I don't want to do this so I will just put a name like this then the email address of my user uh email verified I'll put it yes because I'm just showing this for the demo but if you want your user to verify their email address then I recommend you do that so that after first login your user will be asked to change their password to something and then join group uh so I don't have any group created now till now that's why because I just have fresh instance of K loock that's why I cannot join any group but I'll simply create a user and then I'll I'll go to the credential and we'll set a password for this user so I'm going to set a password as admin and we confirm this save it and this is not a temporary password because I don't want this time user to prompt to change a password because yeah this just for the example again then if you go to the groups you see like there is no group assigned to this user a so we'll go to the groups and we'll create a new group let's call this tny Netflix user group and this will be a group for my application users and I can now add my user to that group so I go to the group join group simply check on this over here and join okay so now I have a user I have group so last thing that I have to do is I'll create a role so uh I'll create a role as a t my Netflix users role and I'll assign this role to the group so that I can specify the uh accesses for the role so in the key clock mainly you create a role you assign the accesses to the role and then you assign that role to user or the group this is how things ideally happen so you can go to the groups and simply click on that group and if you just go to the role mapping assign role and you choose the role that we created and with that you have Ro assigned to this group so in a brief what we did we created a new client with our application name we specified the root URL and the redirect URL that we are going to use uh then we created a group uh we added a user into that group and we also assign a role to that group so that's all configuration we need in the key loock now we are going to now we are going to go to our V code and going to create our web applications so let's create a new directory called front end over here and uh let's create another one for the back end so yeah and for the back end so I'll go I'll start with the front end stuff first and then we'll go to the back end so I'll go to my front end and I'm going to create a new angular project using NG new and I'm calling this as a tnyy Netflix uh and this will basically create a new Ang application I'm using Anglo 17 which is the latest version so I'm going to use fuel uh latest concept of angular the latest features of the angular 17 version so I'll just go with the CSS uh do I need a server side rendering and static generation not really in this case so I'll just put n and it will install the packages and we will set up a project in few seconds so it has completed that so I'll open another CSH terminal and uh this time I'll go to a backend and we'll initialize a new uh backend project so just to npm any tyon y this will create me a backend package.json and uh this is basically my project over here and uh for now I'm just going to create a single file which will be my Express server I'm going to use my I'm going to use the express Library expressjs I'm going to use the express library expressjs for this that's why I'm calling it express server um and I'm also going to need one middleware that I will explain you in a later part of this video what is the purpose of this middleware just to get rid of typo yeah and in my angular application I will get rid of boiler plate code that usually angular generates when you create a new site so I'll remove everything from my app component HTML except the router Outlet so I can simply get rid of everything over here like this and the CSS also and I have app config and the appts so I'm going to create a new component in my uh Ang project so I'll just create a photo for the component then maybe another for the services because I'm going to use some Services I'm also going to need one Au guard so I'll create a guard also and then I also need one um model to show my movie status so I'll create models also here uh so yeah let's start with the component I will use my generate component extension and we'll create a component called homepage uh this is the component on which I'm going to show the movies so homepage is my component and uh it will be there um and I think I'll need to put the route entry and I'm going to put some route configuration so I just have home component so let me rename this to homepage component and I have one o guard that I'm going to create in my guard folder over here so in the guard folder let's create op. guard. TS and uh let's write some code over here so let me add the necessary Imports and uh this will be provided in my route this is the oard which extend the key clock oard so remember this we are going to install one uh Library which is basically key clock angular library and as you can see that it is coming from Key clock angular we have to extend this key clock oard and don't worry about the code that I'm showing if you feel that I'm going too fast or if you're not able to catch up I have all the code and the link of the repositor is down in the description you can go to the description and check the kup repository you can clone the repository and uh you can run the code and you can run the code in your local so don't worry about the code uh so in the odard I'm going to create a Constructor which has the router and the key clock service instance and uh then we have one method which is is access allowed or not so this is going to be our method which basically decides whether a user has access or not to a particular route and this is basically can activate type of Route sorry can activate type of the card that we have going to use in our app route so these all are the um logical this so this piece of code is basically for deciding whether the user has access and if it has a role or not and uh yeah that's it you need here in this file and uh I need to import the O card from my card in my app route so somehow my intellisense is not working and to get rid of this error simply import the O card and uh I guess I have a typo in the name of my file so I can simply rename this to card so I'm going to uh create the services now so uh let's create a service called movie service the purpose of this service will be to get a data of the movies from the back end to make the HTTP calls and there will be a key clock service which basically handle the key clock related things like perform the log in log out get the user information get user profile all that and uh I'm also going to create one more folder called init and uh inside that init folder I'm going to write the initialization method for my key clock so let's create a key clock. init factory. DS so uh in the kick lock in it let's import the kick loock service from the kick loock angular don't worry about this eror because we have not installed this npm package it when we'll do npm install this error will disappear so we are going to write a function which is initialized key lock and this basically contains the configuration of the key clock like your url of the key clock what is the rearm that you're using what is the client ID and uh yeah and you need to provide your enable beer Interceptor beer prefix because we are going to use the uh beer token in our authorization and you can also provide option like the check SSO this is basically for the reason if you want to use uh uh external identity provider a single sign on then for that reason you need this option check SSO on load which basically checks if there is already sign in state or not in the session and in a key clock service I will have a method for each logged in this is basically coming from the key clock Library it's just checking if user is logged in or not so key loock library has bunch of methods you can perform a log out you can get the user profile also then and in my movie service I have a backend URL defined which is Local Host 9090 on the express server and I have two API calls get all movies and get a single movie by ID and I'm basically just making a HTTP call to my backend and I don't have a model created over here so I'll simply create a model uh namely movie dos like this and let's define the properties of movie inside this model so this is how my movie object is going to look like I have ID titled L gener and the image URL uh that I'm using in my movie service now we need to do few configurations in our app config TS since I'm using a stand alone uh mode of the application that's why you can see I don't have any app module at my root level uh instead of that I have app config TS uh so if you are using a standalone mode like me then you have to provide some dependencies of your keylock library in your providers array in your app config uh so provider route for a route and the animation ass sync if you're using the animation per if you're using animation things which I'm using in my application uh then uh important thing and you have to provide this key clock service dependency and that will come from the key clock angular uh then you have to provide the app initializer because when we are initializing our application we want to provide the configuration of the key clock and that's where you go to the landing page of your app that's where you go to the first starting point of your application and it takes you to the login screen then we need a HTTP Interceptor I'll talk about it in a brief and uh then you need to provide the HTTP client also and I will simply import the necessary things over here so I'll take a minute to explain like what we did in the in this app config so we basically initialize the key clock client in our angular application and uh we have HTTP Interceptor the role of HTTP Interceptor here is whenever you you make any API calls to your back end we want to tap into that request and we want to perform some custom action in between so that's where we want to make any backend call we want to add a beer token authorization token to our request and that's what a key clock libr is helping us to do that's why we added the HTTP Interceptor dependency in our providers array and we also want to uh enable that with the provide HTP client so it basically means that if you're using HTTP client in your application to make a backend request then intercept it and use the uh HTTP Interceptor from the key clock add the authorization header to it add the better token into it and pass it to your back end okay now finally we are going to install this Library which is basically key clock angular so I'll do npm install key clock angular and uh this should install the G loock library and I should get rid of this error for now so yeah the error is on as you can see here now we will uh build the template for our application how it should look so let's go to the homepage and add a few code over here so in my homepage uh let's add the container and I'm going to have a header and in a header I'm going to have a search box I'm going to have my logo on the left and I'm going to provide one simple button for the log out if user click on that log out button he will be logged out from the KY loog session and we are going to use a ky clogs function for performing a clean log out so this is my logo search and this search text log out button and then I'm going to have a list of movies that I'm showing in a card so each card has a movie image title all its detail like that generate release here all that and uh that's it over here in my HTML that's it here in my HTML file in the homepage component let's add the import so I'm going to use the Matt snag bar module and forms module because I'm using using the NG model toway binding uh then I have a Constructor inside that I have my movie service and the key clock service a snack bar instance and in my NG on in it on the initialization I'm going to get list of all the movies and that I want to show in the cards in my HTML so uh I'm just invoking the key clock service get user profile that is basically for getting the user profile uh because I also want to get the details of the users just to show you and then one method for the log out then get all movies basically invoking get all movies and just subscribing to it and assigning the value to the local variable over here which is namely movies and then on movie ID on movie ID change so this is if you want to get a specific movie by ID then you can use this and then I have the handle error method for my if there is no proper response from the back end this is the handle error method that is taking care of it and let me quickly add the angular material since I'm using using a snag bar I need to add a angular material so I'll do NG add angular material oops I run this and the so now it will work and this will basically install the angular material just put yes the angular material installation is complete and I don't see a import error to the mat snack by module now so let's run this and see like how it is looking so NG ser and uh I'll go to my local host 4200 and uh there is some problem it seems which is the 880 open ID is not able to use it it says that 403 Forbidden uh because the client ID that I provided is I think wrong so if I go to my code in my innate the name of a client ID that I have put here and the one that I created in my key clock that has to match so I have a client IDE as tny Netflix it has to match with this one so I'll simply remove the front end from here and ideally it should work now so yeah there we go you can see this time it has navigated me to the login screen and I can use the user that I created in my key clock setup uh I can put the email ID or just the username whatever you want and then we'll simply give the password that I set at that time and now you can see I have been successfully logged in and navigated to my page where I have my uh homepage component and uh this is looking ugly so I'll add some CSS to this so I added some CSS and let's see how it looks after adding the CSS so uh this is how it is looking I have my logo I have my search box and the log out and uh it should also have fetch the user details so I have just console loged them in the uh table form or here so I can see that the information about the user like the name last name email ID email verified or not and there are few attributes so you can customize your custom attributes also in a key clock like you can specify the image of your user or anything basically any user data that you want to maintain you can uh put that in the custom attributes and from where it is coming so this is the code which basically giving us the user profile so I have a user profile which I'm basically getting from the load user profile so if you go to the load user profile you can see like it has uh the promise return which basically Returns the entire object of the user so there are few other method that you can see available in this Library like the login log out register is user in the role if you want to check if user has a particular role assigned or not or get user roles what are the different roles assigned to a one user then you can use that there are other method like perform your clearing a token getting the username add token header um and yeah a few others so you can explore them and the keylock is basically a full stack solution for your identity access management you can store the user information also and you can use it for any use case that you are going to have for the authorization and authentication related need that's why I like it and key clock is completely open open source so now I have my user data over here but I don't have any movies data here that's because I have not done anything related to a backend 8 so uh let's start to implement our back end now so I already created the express server TS and the middleware uh so we'll install few packages in our backend application so we are going to install this packages we'll need Express Express session course to avoid the course error TS not Dev because I'm WR writing my code in the typescript and uh I need a key clock connect which is basically a interface library for making the use of the key clogs uh authentication better token validation in your backend application and the body passer so I'll just hit enter and uh wait for a minute to get this packages installed and I think it was fast so I should have my packages in my pack end now I can start to use this packages in my Express server and in the middleware uh before that I want to put my custom command over here in the scripts so I want to put a start command for the TS node Dev because I want to run my back end in the dev mode when I do uh uh npm start and if I have to just build it then I will do just npm build so yeah now I have the required packages let's come to the express server and this is completely blank let's write a server from the scratch so I'm doing a con app Express and I want to rent on the port number 9090 I have interface for the movie and that has to match with the interface that I'm using in my frontend um and I'll simply uh assign the movies data so I'm going to create a database folder over here so I'll create that database so movies data is basically a list of movies that I'm getting from my database movies and which I have over here created so I'll simply rename this to movies. TS and in my movies. ts I'll put some data of the movies so it's basically a array of Jason opposite that you can see over here that is exported and I'm using it as a my data here in my server file so you need to have these two things over here which is calls and the body pass. Json calls is required because in our case we are our front end is also on the local host and back end is also on the local host and if you try to access the resources from the same domain then it gives you error that it has been a it has been a blocked so to get of that error we are basically using a cuse origin true here body pass. Json you need because you get a request data in the Json format and then we have the route endpoint for the get all movies and if you want to get a particular movie by ID we are simply using the find method on the movies AR and finding that movie and simply returning that then finally we are listening it on the port of 1990 and I think uh we have enough things and at this point I think if I do yarn start or npm start whatever you can use I like to use as a package manager our backage should run so I think it's running and if we go to our front end ideally it should fetch the list of movies to us uh which it is not doing there is something wrong it seems in our front end cannot read the properties of f reading code if I go there and I think that was happening because I forgot to add the key loock angular module and the HTP client module in the Imports of my app component uh since app comput is a root component over here we need to provide that as Imports because since we are not using any module uh this is stand alone application you need to provide the necessary dependencies in the Imports are of your app component so ideally now I should see the list of movies so it is fetching me the list of movies from my back end it should have a better token added so this is the main thing this is what we were trying to achieve till now every request that goes to back and should have authorization header and it has the token attached here along with it so if you just copy this token and I want to show you like what exactly is there if you copy this token and go to the JWT IO and if you just decode this you can see that inside this token you have the information about your client client ID you have the information about your user also the user that has logged in email first name last name the client all that details are basically present in this token so that means we can use this token as a identity for particular user who is using your application who is the current user logged in with this session and this information is passed to the back end and if you see the flow of this API calls you can see like there is a init client which was basically initializing your client and it made a request to your key clock server and then it return a token and that token basically has this information uh it has the session expiry set here also I want to show you from where you can set this session so if you go to your key clock Administration UI there you have uh your client and inside the settings you can go to the uh uh access settings or you can sorry you can in in your clients you can go to the advance and there you have option to set the expiry for your token so so you have uh access token lifespan 1 minute and uh client offline session idle 30 dayses so you can specify like how long your bar token should leave from this advanced settings from your key clock then you have another HTTP call happen to then you have also Account Details which is coming from your KY lock so it basically rains the user profile details like the email ID first name last name email verified so everything about the uh user details you can get from this endpoint and this is what we are using when I console log this user profile I'm using it internally get all movies and uh now we have the bar token here uh we want to utilize this here in our backend code so we'll go to the backend code again and uh in the backend code we had our Express server setup and uh uh these routes what we have they are completely open what I mean by open like they are not protect ected it uh and we are getting the authorization token from the client so we have to make the use of that token to validate that this request is coming is it from the correct client or not so now what is happening in this flow is we have the access token which is coming from our front end but we are not making use of that at our back end so we want to use that uh token to validate that whether this request coming from is it from the legitimate client or not and that's where we are going to add that to add that validation flow in our back end and we are going to protect the back end apis so uh let's import the key clock from the middleware and uh we are going to define the protected routes and that will basically key clock. protect because we want to protect all the routes by default but if you don't want to do something like this you can put the protect routes in the individual routes over here each of the route like this this will protect only that particular route that particular API but here in my case I want to protect every route that I have present in my app in my Express server that's why I put it as a uh protected routes and I want to just pass that here in my app.use so that every route that I have in my Express server will be protected let's come to the middleware and this is a part where we have to define the configuration of our key clocks so we going to have a key clock config object where I have my client ID and uh I'm going to specify the beer only as a true I'm going to give the server URL of my key clock and the real that name of the real that I'm using and this is the real public key now this is the important part because there are two aspects in the security uh so this is the important part because there are two aspects in the security yes we are using the we are using a bar token that front end is passing to a back end but there has to be also a validation for the back end which means that uh how a key clock will verify the back end is legit or not so there's another key called public key which basically backend uses and if the key is correct then only a back end is going to expose a data uh if the key is not correct then the back end will not be up so we have the two level of security if back end has a correct public key from the key clock then it's going to expose it apis and uh if front end has sent a correct better token then front end will be able to consume that API so we have two level of security and that's a beauty of key clock so you have this uh real public key and from where you get it so you can find that in your key clock if you go to the real settings you can just go to the Keys Tab and there you have a different algorithm you can choose whichever you want so for example I choose the RSA 256 I can copy this public key and simply grab that and I have to just paste that over here in my KY CL configuration in the middleware and uh with this basically uh it is a mechanism for keylock to understand that whether this back end what you have is it a correct whether it is a legitimate backend service to perform the validation of the bar token that is coming from the client so it's not just you know authentication from the client like usually we talk like usually we talk the client need to have a proper keys and the tokens then only they can access the backend URLs but also back end need to have the currect key so that it can can be identified a legitimate back endend and it can provide the data the additional so this is a really good feature of the KY lock and additional level of security we are incorporating here so I provided that key and in my Xpress server I'm already utilizing that so now if we go to our application and see and now if I just do a refresh I still see the list of movies and uh this time I'm making the use of the uh public key that I got from my uh key clock so just to tell you like this is working if I give something wrong over here I just change one letter then you can see in my front end if I do a refresh I will no longer will be able to get that data and uh it will fail there because now my back end don't have a right public key with it so with that key clocks access is dened for this back end so this is really a smart approach because when you don't have a right key a back end at first place doesn't expose any data so there is no chance for the frontend to basically consume the apis because our apis are never exposed in the first place itself because back end didn't have a right key back end had access in that error and uh if you just change that to correct one and do a refresh then you can see that it has the data being properly fetched and we have our beer token in our authorization header and I already showed show you that you have the details of the user profile over here and you can perform the sign out also so if you click on the log out then it will log you out uh now seeing this screen you may have a question like we have this theme specific to a Ki lock so how you can change it so if you have to change the key clock theme then you have to make use of your Docker command shell or you can just simply use the terminal so you can use the docker command to go to the uh file directory structure of your key loock image and you can change the login. CSS so I'll show you like how that is done so if I go to the sources over here and uh if I or just I'll use the inspect and we'll find out the CSS for this so I'll go to a login CSS and here you have the uh CSS code for your image if I simply remove that then it's gone or if you want to change the back end image whatever you can simply do that by tocking the CSS or I can do something like changing a background color to gray so you can customize your login screen as you want and that you can do by tweaking with a login CSS of course I'm doing it in the browser so this is the temporary way and if you have to do it permanently as I was saying you log into your doer shell and from there you basically alter the theme of your uh key clock login page you just have to change this login. CSS file as I change here in my browser and it will basically reflect so you can change it to whatever you want um now I want to come to the external in provider so as I was so so clock also provides your feasibility that you can add external identity provider and there's a list of external ident Prov like the beat bucket Facebook GitHub gitlab Microsoft LinkedIn Instagram open shift stack Overflow PayPal Twitter you can use any of this and if you just enable that uh you will have the sign in with that particular external IM appering on your login screen so for example example if I just put a Google's here I will provide some dummy data and just add it and now if I go to my page and just do a refresh I should see a sign in with Google button here and there's support for a bunch of other I am providers and what you need to do is you just need to get a client ID and the client secret for example in case of the Google I had another video in which I explain how to do a sign in with Google and uh there I got the client I declar secret from the Google developer console you can put them here and it will be ready to use so this was my movie application which uses the key clock authentication keylocks login screen and it also protects my backend apis using OD zero concept so through this video I'm trying to spread the awareness about the key clock Tool uh this is really good tool and uh it has all the features that you need for your authentication uh like the API protection o better token all that and over all of those it is totally free it's 100% free as it is open source and by days and by day by day it is keeping on evolving so I that's why I really like this tool and thought to make a tutorial uh if you guys have any question specifically if you want to know how to add external IM providers like the stack Overflow GitHub gitlab B bucket along with a key lock in your application then uh do let me know them in a comment and I'll be more than happy to make a detail tutorial on that topic if you like this video do uh consider subscribing to my channel it's totally free for you but you doing that it really supports me and motivate me for doing this videos uh with that thank you for watching this video and uh Happy coding Journey bye-bye
Info
Channel: Brogrammers
Views: 1,433
Rating: undefined out of 5
Keywords: keycloak, angular, authentication, keycloak tutorial, how to use keycloak, keycloak authentication flow, keycloak docker, keycloak docker setup, keycloak angular login, keycloak angular, keycloak nodejs example, keycloak nodejs, openid connect explained, oauth2 authorization code flow, oauth2 explained, how to integrate keycloak with angular, keycloak login page customization, keycloak login page, configure keycloak for production, single sign on, angular sso login
Id: E5-rkGf5DGA
Channel Id: undefined
Length: 40min 42sec (2442 seconds)
Published: Tue Feb 27 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.