 We are deprecating hooks by November 2024, so let me show you how to migrate your out-zero hooks to out-zero actions. Hello everyone, my name is Carla and I'm a senior developer advocate here at Out-zero by OCTA. We recently announced the deprecation of out-zero hooks and rules because we're focusing our attention on actions. But don't despair, this won't happen until November 2024, so you'll have plenty of time to migrate your rules and hooks to out-zero actions. Now we already posted a video on how to migrate your rules into actions, so in this video we're going to focus exclusively on out-zero hooks. Out-zero hooks enable you to customize the out-zero behavior to some extensibility points, such as the pre and post user registration, password changed, and so much more. Now you have out-zero actions. Out-zero actions provides you with a unified development environment to provide you with the same functionality and customization options that you had already with rules and hooks. Actions provide you with an integration version control system. You can modify an action without affecting the one that is already in production. You can create new versions and even go back to previous ones. The actions editor support code hints, npm packages, and even isolated secrets management. You can also take advantage of a growing number of no-code actions from the out-zero marketplace, which solve common identity use cases like consent management, progressive profiling, and user verification. Now keep in mind that while rules and hooks are still available, they can live together with actions. Just remember that both rules and hooks execute before actions. So let's discuss some of the conversion guidelines that you should follow in order to migrate your out-zero hooks into out-zero actions. Now I'm going to assume that if you're watching this video, it means that you already have some sort of understanding about hooks and actions, but if you don't, I highly recommend that you take a look to the documentation that I'm going to leave in the description below. So I'm already here in the out-serial dashboard. I'm looking at some of the hooks that I have created already. As you can see, I have one client credential exchange, one post change password, and one pre-user registration hook. And if you remember, there are five different types of hooks. We have client credentials exchange, post change password, post user registration, pre-user registration, and send phone message. And so the first thing you need to do is to map the hook type with the action trigger. Now generally speaking, both the action trigger and the hook type are pretty much the same except for the client credential exchange, which is called M2M slash client exchange in the action trigger. So let's go ahead and try to migrate one of our hooks into an action. I think I'm going to start with the pre-user registration one. If we take a look at this hook quickly. Quickly. Thank you. So what this is doing is adding information to the user metadata. Here what we're doing is if the user has a phone number, then we're going to say their favorite color is green. And if not, we just simply cannot update the user's favorite color. And that has a lot of sense. So that's what we're going to do. So the first thing we're going to do, we're going to go to actions library. And we're going to build a custom. So that one we said is add users info to metadata. And now we're going to remember the trigger. So in the hook, we were talking about the pre-user registration. And as I mentioned before, the name is the same in this case. So we're going to select that trigger and we're going to click on create. Now when you select the trigger and you'll see you'll get an empty named export in the actions editor. The name of this export depends on the type of action that we're using. In this case, it's going to be the pre-user registration. But if we were talking about post-user registration, the name will be pretty much the same except for this little part here, which would be post instead of pre. The same principle applies about the namings of the hook type and triggers. The only different one is the client exchange, which on actions will be on execute credentials exchange. So I want to go and copy the content of my hook. And we're going to start the migration. So we were said we were going to do the pre-user registration. And we're going to copy just the body of this function. And we're going to move that to our recently created action in here. And now as you see, we have a few things marked with red. Some things might not make sense at all, like the CB doesn't exist in this action. So let's talk a little bit about how to map the parameters from a hook to an action. Now hook functions receive contextual data about the user, the client, the request, etc. And this could be multiple arguments depending on the hook type. In the pre-user registration hook, we only have three attributes. And that is the user, the context and CB, which refers to the callback. So let's go ahead and write that over here. So we don't forget because I will forget. In hooks, we have three parameters, which is the user, the context, and CB, also known as callback. And if we take a look in actions, we only have two parameters. And that's going to be the event and API as we can see in line 10. Now, as I mentioned before, hooks can have different parameters. Most of them have the user context and callback, but some of them can have even more depending on the type. And we'll see an example about that later in this video. Now, as a general rule, all the read-only properties of the user and the context are going to be found in the event object. While any interaction with the running environment, like adding information to the user's metadata, can be done using the API object. Now, let me write that down before I forget it. So read-only props of user and context can be found in the event. And as we said, any interaction with running environment, running environment, if I know how to type, can be found in the API. Now, let's talk a little bit about the callback. So in Hux, you were using callbacks to either end the execution of that hook or to show an error. Now, in actions, the machine-to-machine client exchange and pre-user registration both have the API parameter as a second argument, which you can use eventually, for example, to prevent user registration by calling API.access.deny. So let's write that down more or less as a general rule. If there's a failure and you want to show a message or simply deny access to the user, you can use API.access.deny in actions. And as I said, this works in pre-registration and machine-to-machine client exchange triggers. Now, if there's a success and you simply want to end the execution, you can do nothing and just let the execution end normally. Or you can just write return and the function will end. Now, something important to notice here is depending on the trigger that you're using, in this case, we're using the pre-user registration, both the event and the API objects can change. I'm going to leave a link in the description so you can take a look that depending on the different trigger, how these objects look like. For the sake of the video, if you want to know how they look like, for example, if you want to take a look of how the event object looked like, you can click on test. And this is pretty much a test JSON object that you can use to test your action. And so you can see the structure of the JSON object already. Now, since we're already looking at the outactions editor, we can take a look at the sidebar that we have here. The one I clicked on, like I said, is the test, let's call it tab. And this one over here that looks like a box is the dependencies one. Now, with hooks, you could include dependencies from thousands of NPM packages. But if you need to use a package that was not listed there, you would need to request directly to outzero to include it. This is not the case with actions because you can add dependencies that are available in the NPM registry, making a million of dependencies available for you. Now, another thing about dependencies is that when you were using hooks, you had to specify the version of that dependency you were using. With actions, you can simply click on add dependency, specify the name. For example, let's say I want to use Axios. And if I don't specify the version, it will just pull the latest one. And just like that, you can import it and use it in your code. Another thing that you can take a look is secrets. Now, similarly to hooks, you can have secrets in your actions by clicking on the add secret button. And this will ask you for a key and a value. And that way you can secure your secrets in there. Now the accessing of the secrets, it's a little bit different. And we'll cover that in just a minute with another example. All right, so now that we've seen how the actions editor looks like and what these three options do for us, let's try to change this action code in order to make it work because right now we have some errors here. And so the first thing, as we mentioned before, anything that is read only from the user in the context will be in the event. So we will have a phone number in there so let's go ahead and make some changes. So the user will be in the event.user and the phone number spelling is not really correct. We can even use the auto completion from the editor. That's good. And now we need to update the user metadata. And if you think about it, this is a way for us to interact with the environment. So that is a hint to use the API. So what we're going to do here is instead of this, let's comment this out so we remember what it was doing. Instead of this, what we're going to do is api.user. This will be the current user. Set up not app metadata. This always happens to me. User metadata. And we're going to set the favorite color to green. All right. And this is if the users provide a phone number. So lines 21 to 23 are doing exactly the same as 24 as line 24, but in the context of action. So we're going to get rid of that. And then what's happening here is we are doing a callback, an empty callback with the response. And if you remember, if this is a success, we don't need to do anything. So we can simply leave it empty in the else. So if the user doesn't have a phone number, we want to show an error message, or basically we don't want the user to be able to register. So what it's happening here is using the callback to show an error message. And what we're going to do is we're going to comment this so we don't forget what to do. And because we're interacting again with the running environment, we're going to use the API. I'm going to return an error from that. So the first thing we're going to do is to return. And we're going to use API.access.deny. And if we pick here, we're going to take a look to what the deny function receives in this context. And the reason I'm doing this is, like I mentioned, depending on the trigger that we're using, the object can change. So in the previous registration, we see that we actually have to return to the strings. One is an internal reason. And the other is a user message that can be used for the interface, or it's more like user facing. So let's write our internal reason like error. User is weird. And then the external message is going to be the same one we had in our hook. So that way it will be completely transparent to your users. So we'll get rid of this. And just like that, we actually, I missed this, but we actually don't even need this response anymore. So we can get rid of that. And the good thing is this is like a lot more simplified. We can even try this out. So in this case, this user has a phone number, which is 1231231234. So if we try this out, then the user media data will now include the color green. So let's run that. See if it works. And there it is. There's a key for every color. And now it's green. If we, on the contrary, remove this phone number from here and run it, then we should get a message saying that the user is weird and the phone number is mandatory. Now, please don't take this user is weird. Personally, this is just me making up strings as I record. So yeah. So just like that, we have our first hook completely migrated into actions. Now let's go back to our hooks and see what else we can do. So what do we have here? We can take a look to the add custom claim to a token. Let's start with that one. Let's take a look. This one's interesting because unlike the previous registration, this hook has a lot more parameters. And if you want to learn more about those, you can either read this or our documentation. But we're not going to focus on that right now because what we want to do is to migrate this into actions. So let's copy that. And we're going to go to our actions and create a new one. So we're going to build a custom action. And let's remember the hook type. In this case, this was client exchange. So we're going to select M2M client credentials. I'm going to create that. And as you can see, the name of this export is now on execute credentials exchange. We have the event and the API. And we're going to put this content here. So let's take a look at how we can migrate this function. Okay, so we're creating a constant here. I'm not sure if we're going to use that. So let's leave that for a second. We have a namespace, which is this my app.example.com. And you see we're already assigning things that we don't really have anymore. So what is going on here is we're trying to use the scope parameter, which is no longer available. And then we're trying to add the favorite color claim as green to the access token. Now the access token, as well as part of the running environment, which mean is going to be available somewhere in the API. And because you can use the editor, you can see it's available here in the access token. And then let's see what we can do with that set custom plane. That's exactly what we're going to do. We can take a look here at what we need to do. So we have a key and a value. That's the name of the claim and the value. Pretty self-explanatory, right? So right here, the name of the claim is going to be this. We're going to use the same exact name without this thing. And we're going to set it to green. And just like that, we can get rid of this because we're not longer using that anymore. We can also get rid of this line because we already did that in line 11. And now we are using the context, which is from hooks, but we are returning null and an access token. And because we don't really want to do anything else with this function, and there's no error message, we're just going to do nothing and finish the execution. So we can also get rid of this initial constant that we defined. We don't need that anymore. That way, this is how our action is going to look like. Now let's see if we can test this out quickly. If we go to the test section, you'll see that there's a few different things in the event object that could be because this is a different trigger. So we're going to run that. And what we should see is a response saying that in this namespace, we set a custom plane with the value green. So this is working. There were no errors. So that's pretty cool. Now last but not least, let's go take a look to the last hook I have created here. And I think this is going to be the most complex one, even though it's not really that complex, but hopefully it will show you how to do a few things. So the one that we're going to do now is a post change password hook. And what we want is to send a notification email after a user has successfully updated their password. So let's take a quick look at this hook. So what's going on here, we're using the request dependency here. We have a secret and two, because we will be using sacred for this. And we are making a post request using the sacred API, just telling the user that, you know, your password was changed. And if there's any kind of error, then we'll show an error message. And yeah, that's pretty much it. So once again, let's copy this code and take that to our actions. So we're going to click on build custom. And this one was to send email after password. The trigger here should be the post change password. And we're going to create that. All right. So we're going to put our code here and start making some changes. Now, there's a few things here in this function that we haven't really migrated yet, but we did talk about them briefly at the beginning of the video. So one of them is the secrets and dependencies. So in the case of requests, we don't need to add that asset dependency, but in the case of the secret, we do need to add the sacred API key. So let's do that first and create a new secret. So we're going to create a new secret. And it's going to be sacred API key. And in the value, I already have it copied in my clipboard. So I'm going to create that. And a second look at what else do we need to change? I will have to change this email in a bit, but I'll do that when we're going to test this. So let's leave it as is for now. So the first thing we need to change is the way we access secrets. So we're going to comment this out. And we're going to create this constant sacred API key. And I need to learn how to spell. And the way we access secret is through the event object dot secrets dot. And then we'll have a list of all of our secret keys. Then we don't really need these symbols here. We're passing our API key as a bearer token. And we are sending this to this email, which is going to be available in the event dot user dot email field. Like I said, we're going to change this email in a minute. And we do have to change a few things here. So we want to talk about the connection name thing, saying something like the password for your account blah was recently changed. So as we know, the read only properties of the context are in the event. And we don't really have to change much there. Same for the user email as we saw. And the last part we need to check is so here we're saying if there's an error or the response was not successful, we're going to return this error or throw this other error. So instead of using the callback for that, what we're going to do is we're going to throw the error or we're going to use this new error body message from the sacred response. Oops, response just like that. All right. Lastly, we no longer have a callback. And since we want this execution to finish, we're not going to do anything. So just recap and what we did. We change how we access the secrets. We change it, how we access the connection and the user email as well. And finally, we change the way we throw errors. So let's go ahead and test this out. I actually have a test email here that I'm going to use. So I'm going to write that email here. And I'm going to change the recipients email. All right. So if I type everything correctly, we should be able to test this out. So let's run it and see what happens. So we're running this and there's no errors. So if everything went well, we should have an email. Let's take a look. And I do have it indeed the password for your username password indication, because this is my connection name. This account was recently changed. So just like that, we were able to migrate this hook as an action as well. When converting hooks to action, there's a little bit more to think about than just executing the conversion. You also need to plan your migration strategy in order to avoid issues in your production environment. You should set up a staging environment in out zero where you can test the actions that you just migrated from hooks. This will help you guarantee that the actions code that you have is running without errors and also won't affect the code you have in production. Now, keep in mind that you can have both hooks and actions running in your tenant. You should always remember that hooks will run before actions. So you can migrate a hook by activating the respective action and then deactivating the hook. This will help you minimize the risk of breaking your production environment, although there are some caveats that you should keep in mind. For that, I highly recommend that you check the documentation I'm going to have in the description below. So in this video, you learned about how to migrate your out zero hooks to actions. We also talked a little bit about the benefits of using actions. We went through the conversion guidelines that you should generally follow when doing the migration. We covered a few common use cases that will hopefully help you while doing your own migration. And finally, we talked a little bit about how to plan your strategy and generally how to move forward and continue using out zero. Thank you so much for watching. I hope you really enjoyed this video. And if you have any comments or questions, make sure to leave it below. Hit subscribe and give us a like. Thanks!