Angular and NgRX authentication
Building token authentication into an NgRx application can be overwhelming and confusing. Authentication is already a big, scary subject and so is NgRx. When you put them together, things get confusing fast. In this talk, we’ll do a comparison of how authentication in a vanilla Angular app differs from auth in an NgRx app. We’ll then see how the central nervous system of authentication shifts from a service in regular Angular to Effects in NgRx.
This talk will be practical and code-driven, leaving you equipped to tackle adding this feature to your NgRx application at work on Monday. You’ll learn how Effects can handle loading authentication state, navigate users to protected routes, and process tokens received from an identity provider. By the end, you’ll feel way better about tackling auth in NgRx!
Watch all the ng-conf: Hardwired presentations/videos at https://videos.ng-conf.org
ng-conf: Hardwired is brought to you by: - https://thinkster.io/ - https://herodevs.com/ - https://xlts.dev/
Follow us on twitter https://twitter.com/ngconf Official Website: https://www.ng-conf.org/
All right, before I begin, I want to give a quick shout out to my friend Kim Maita. We were originally going to be doing a joint talk at this conference and she had some some issues come up. And so I just want to give her a quick shout out. I hope she's doing well and I hope my slides live up to her expectations. So we're going to be talking about the role of effects in indirects authentication. I love to teach and I love anger in general, it's one of my favorite technologies right now and I love teaching about it. I think it's because it's complex abstract concepts. And so I love breaking that down and making it understandable to newcomers and junior developers. But what a lot of us have found in the entire ecosystem is that effects are one of the hardest parts of learning. And I know it was for me and I think part of that is because, well, on the one hand, effects are really powerful and can do a lot of things. They're really abstract. They're not as concrete as actions or reducers. There's something about actions just dispatching a payload to the reducer to update state that I think people get a lot faster than getting effects. So in addition to loving indirects and teaching about anger, I also love Oth, which makes sense given that I work for an identity company. And over the last year I've been giving this talk on demystifying token authentication and consistently I've found that it turns out that effects are really the cornerstone of the whole auth process in Congress. So it doesn't take a rocket scientist to put that together. Right. The that effects are the hardest part of learning indirects, but they're also the biggest part of the process in indirects. And that combination is enough to induce a mild panic attack. So in this talk, my goal is to turn you from mild panic attack to sigh of relief as I teach you some ways to overcome some common struggles with effects and anger and especially in authentication. So what we're going to do in this talk, we're going to cover some general concepts about effects and how they're the DJ of Enger X. We're going to talk about common struggles people have with effects, and then we're going to look at effects in the log-in flow and how you can overcome those struggles that everyone faces there. So Frosti mentioned I'm Sam Julene, I am a developer advocate for Zero Whereat Identity and Access Management Company for developers. I'm also a Google developer, expert and angular collaborator. I created the course of creating angular JS Dotcom, and I'm an instructor for both Inkster and Egghead. So let's start by just talking about effects in general, and we'll do a quick architecture review to get that started in. So in Vanilla Angular, we typically have services and components and they interact with each other in both directions, but in ingress, we don't really do that right. Instead, instead of having services and components that are interacting with each other directly, we break apart our architecture so that our app state is updated by dispatching actions to reducers and then components. Read that state through selectors. Effects also listen for actions and handle side effects, effects do a lot of things, and I think what most people think of is what that affects, decide when to call services and they communicate with APIs. That tends to be where people start to get affects. They start to realize, oh, I need to call an API. So I must use an effect here. But if I can do one more thing, which is handle control, flow logic, and this is where I think people start to get tripped up, what do I mean by handling control flow logic? That's kind of a a jargon jargony phrase there. Well, what that means is that affects function as a task runner. Effects are the brain of Mike and Brandon say that effects are the meat of the lasagna. I like to say that effects are the D.J. of the angry dance floor. They make sure everything everyone's having a good time and the music is playing in the right order and everything's going well. But working with the facts isn't always a bowl of cherries. And there are a few things that people really tend to struggle with. Three in particular. The first is actions that only trigger effects. Now, what do I mean by that? This is actions that don't touch the reduce or to modify state. The second is non despatching effects, these are effects that don't return an action. And then the third one is complex effects, so complex effects, this is when you run into a scenario where you're trying to handle multiple side effects at once. It turns out when you're implementing off an angry ex, you come across all of these problems. We have actions that only trigger effects and we sure do. How about non despatching effects? Yep. And what about complex effects? Yep, we got some of those, too. So let's look at effects in the log-in flow and we'll see how we can overcome each of these struggles before we get to off energy. Let's just look at OTH in general just to get an idea of the flow that we're working with. What we're going to talk about here is just the basic login process. So you kick off the log in by usually clicking a button or something. You get sent over to some sort of identity provider where you log in and then that provider sends you back to the application. The application then needs to handle that redirect. Usually you've got some sort of SDK or something that goes out and exchanges a code for a token and brings back a successor error message. Inside of that success is where we'll usually have our user and token and then we'll get some sort of you are usually we need to send out our user to another part of the app that's protected. Now, in Vanilla Angular, what we typically do here is we throw everything into an office service, so this all service does a bunch of stuff right? It stores the token and user in memory. It interacts with the office and it handles all of the redirect logic for us. And then that service interacts directly with the components and also interacts with data services. Usually we need to add the token to an outgoing request so that we can hit like a protected API or something. But this isn't how we do it in anger. Instead of having an off service with data services and components interacting together, we have this distributed architecture right where our service becomes this thin layer around our SDK alongside of our effects. And the rest of those responsibilities get spread out between effects, selectors and reducers. So now what I want to do is look at that flow again from the standpoint of Congress and I have a little bit of a challenge here for you when we go through this. Again, I want you to think about which parts of the flow directly change state. So we kick off our log-in process. We get sent over to the provider, we get sent back to the app to handle the redirect, and then we process the successor error and we pull out our user and our token and then send the user on their merry way. Now, which parts of that actually update state in the application? Well, it's actually only this part where we get the user and the token. These are the only things. I mean, you may store more than this, but these are the only this is the only part that we're going to actually put in our store in our state. Everything else in this process is a side effect, which means that everything else needs affects. So let's break this into two pieces. First, let's zoom in on the just starting the login process and getting sent over to the provider. We have probably an instinct to go ahead and create an action because we know somehow we've got to kick off this process, so we create a log in action and then you're probably thinking, OK, I know I need to call the service to log in, so I must need an effect for that. So that's a good instinct. So we create a log in effect and that log, in effect, listens for the login action that we've created. And then we're going to use the tap operator. That's just the operator that's used for side effects in our jobs. And we're going to call the office services log in function. Now, this login function on the service, lets just zoom in on this and see what it's doing. So in the service, this log in function is just wrapping the auth clients log in function, whatever SDK you're using, you'll just sort of use this as a pass through. So then we could go back to the effect. And after we call the Log-in, we're not going to dispatch a new action here because we're just going to be sent off to somewhere else. So we need to pass this dispatch set to false options object. So right away, you can see here just just in our first step here, we've already encountered two of people's common struggles with effects. We've already come across actions that only trigger effects and non despatching effects. So what can we do to help us understand this a little bit better? Well, this is where it really comes in handy to remember that effects are a task runner for energy drinks. They are the D.J. of the angry dance floor. But what do I mean by that? Well, so if you tell your deejay to play your favorite song, unless the DJ just immediately starts serenading you on the spot, nothing happens right away, right? The deejay has to do things like go grab a record, put it on the record player and then play the song. So everything until the song actually starts playing is just a task that needs to happen. It's just a side effect. And we can look at our app and logging into our app the same way. So what do we need to do in order to get our user in our Tolkin? Well, we need to call the service to log in. We need to handle this redirect flow and then we need to update the store with the user and the token. Everything until we do that, though, is just a side effect. It's a task that needs to happen, and that's where indirects can help us. So let's look at the second half of this process, so we get sent back to the app and we have to handle the redirect, we got to interact with our SDK and then we need to process the success to get the user into action and send the user to wherever we need to send them. So there's a lot happening here. We know that we do need to do some sort of action to kick off this part of the process when we get sent back to the app by the provider. So we create an action here and then we know that we're going to need to interact with the SDK and do a whole bunch of other stuff. So hopefully your instinct is starting to think that you need, in effect here. So we create a handle, redirect effects and we listen for the handle, redirect action. But then we've got our exhaust map here to help us with whatever we need to do. But what do we actually put inside of it? Well, let's take a stab at it. Well, so we know we need to call this all services handle redirect function. This is just an observable that works with the SDK to go get your token and your user and whatever. Redirect your URL you need. But then after that, what do we need to do when we know we need to have some sort of success that we dispatch and we need to have some sort of failure that we dispatch if there's an error? But what about all this stuff in the middle? Somehow we need to go set the user and token somewhere and somehow we need to navigate to the redirect you, Earl. But do we do that here or do we do that elsewhere? Seems like a lot. And then we need to dispatch a success action. But is that supposed to have a payload? What do we need to do? So this is where things start to get really confusing and people start to get tripped up. I know it was tripping me up when I first started this. It turns out here that we've run into a complex effects scenario where we're trying to do too many things in one effect. So usually that I found in this situation, if I start to feel like I'm getting confused about what to put in my in fact, I missed something or taken something for granted. So I need to go back back up and try to find the hidden side effect that I've missed along the way. Somehow I've taken something for granted. So I go back and I look at this flow again and I realize that calling the service to handle the redirect is already a side effect. And then we go and grab the token and everything and proceed with the process. So. We need to know how to work through this, so what I like to do is break a complex effect into smaller pieces and that way we can just let one effect handle one side effect. When I was chatting with Mike Ryan about this talk a week ago as I was building it, he said that if if you ever gives a talk on good effect hygene, this will be one of the tenets. Let one effect handle one side effect. Another thing that really helps me is to write out the flow. So just like we did with our and our login process, we can write this part out. So what do we need to do here? We need to call the off service to process everything. We need to update the store and we need to redirect the user. So only one of these is actually impacting state. Right? So the first and the third, our side effects and updating the store is changing the state. So when we go back to our effect, we know we need to handle the redirect where we're calling the service. And this is already a side effect that we're dealing with. So instead of trying to do everything here, let's refactor this and we'll dispatch a success action and this time will pass along the payload and the redirect your URL. This lets us do is go back to the reducer and we can add a case for handle redirect success and here we can just go ahead and update the token and the user profile. And that lets us create a new effect, a second effect for Handal, redirect success. We'll listen for that handle, redirect success action, and then we'll use that tap operator again to navigate the user to the redirect. Yoro, now, notice again here, we're not dispatching a new action, so we need to set dispatch to force for this effect. So now we've successfully tackled all three of these actions that only trigger effects, non despatching effects and writing complex effects. So I've hit you with a lot. Let's do a really quick review. So, like we said, effects are one of the hardest parts of learning Andrex, and it's also a huge part of implementing off in ingress, in vanilla angular. We tend to have one giant auto service that interacts with our components and our data services. But in engineering, we have this different architecture where our service just becomes this thin wrapper around the SDK and the reducers and selectors and effects are sort of distributing that responsibility. Most people think about effects when it comes to calling services and APIs, and that's where people the light bulb starts to go on. It starts to click that they need an effect, but people tend to forget, including me, that affects also handle your control flow. Logic effects are the DJ of the entire dance floor. I promise if there's one thing you remember from this talk, that's going to be it. So we looked at, though, there are three major things that people struggle with here, and it turns out that all of them show up when you're implementing off in an app. So we first we found the first two. Just when we try to log into the app, just clicking the login button actually has a lot of complexity behind it. So to break this down and to overcome this, what you want to do is remember that affects function as a task runner and try to identify where the side effects are and where the store is being updated. And then we found that the complex effect at the second part of this process of handling the redirect, getting the user in token and sending them to a new place. So this was a complex effect. And when you run into complex effects, there are a few things you can do to make your life a little bit easier. First, you want to back up, find the hidden side effect. What have you taken for granted? Maybe it's a call that's being run that doesn't actually return anything, but it has to get run anyway. So break apart the complex, the complex effects into smaller pieces so that you can only let one effect handle one side effects. Again, it helps to write this out and just figure out what things are, just tasks and side effects and what is actually needing to be updated by the reducer in the store. And now, hopefully, in addition to just figuring this out in order, when you come across these problems with effects in your application, you'll go from a mild panic attack to a sigh of relief. One last thing before I let you go, Angie is planning a conference in November and I have a discount code for it. I'll be there, Kim will be there, Mike will be there. A lot of people will be there. And I hope to see you there in November. You can find that link as well as all of my slides are at Sam JDAM and Hardwired. Well, they will be in about four minutes when I finish uploading them. And yeah, that's all I got you.