Welcome back to another episode of The Rabbit Hole. Today on the show we are joined by Roberto Pedroso, and we’ll be talking about authorization and how to keep people out of our websites. Roberto is a lead engineer at JOOR and works mostly on their back end systems doing a lot of API design work. Before that, Roberto worked on backend integrations with alarm monitoring, billing and access control software for DGA Security. Inside this episode, we’ll figure out what the difference between authentication and authorization is, and hopefully by the end of it will have a better understanding of the various authorization frameworks and how to make sure that they are properly implemented and that everyone is doing their part to uphold security. For all this and more, join us as we head down the rabbit hole!
Key Points From This Episode:
Transcript for Episode 74. Authorization with Roberto
[0:00:01.9] MN: Hello and welcome to The Rabbit Hole, the definitive developer’s podcast in fantabulous Chelsey, Manhattan. I’m your host, Michael Nunez. Our co-host today.
[0:00:09.8] DA: Dave Anderson.
[0:00:10.3] MN: Today, we’ll be talking about authorization and how to keep people out of our websites, I guess, right?
[0:00:17.6] DA: Yeah, we’ll figure out also like maybe what the difference between authentication and authorization is?
[0:00:23.1]MN: Yeah, hopefully by the end, we will also talk about those things.
[0:00:29.2] DA: Yeah, we might need some help on this though.
[0:00:30.9] MN: Definitely. We have a guest! Speaking of which, we have a guest, we have Roberto Pedroso. Roberto, how’s it going?
[0:00:39.0] RP: Yeah, it’s going great, happy to be here.
[0:00:40.4] MN: Awesome, would you like to tell us a little bit about yourself before we dive into the topic of authorization?
[0:00:46.5] RP: Sure. Again, I’m Roberto, I’m a lead engineer at JOOR, I work mostly in our back end systems, I do a lot of API design work. We have a GraphQL API that exposes a lot of data and we have to be very mindful of authorization. Been at JOOR for about two years now. Before that, I was programming alarm monitoring systems. Very stressful kind of programming.
[0:01:07.2] DA: Probably need some authorization there too.
[0:01:09.0] RP: Yeah, just a little bit.
[0:01:10.8] MN: Just a tad bit, just a little.
[0:01:12.8] DA: No room for error, maybe? So I feel like the terms of like authorization, authentication get thrown out a lot and they both sound very similar. It seems like it’s easy to mix them up.
[0:01:28.2] RP: Poor choice of words. Yeah, the difference is authentication answers the question, who is the user, who is using my site, my API, my service. Authorization answer is a question, what can they do? What can they see, what can they change?
[0:01:45.5] MN: It’s a who versus what, essentially?
[0:01:48.2] RP: Yeah, it’s you know, somebody who wants to use your website but then you have to figure out what resources they’re capable of using so that you’t can trigger an alarm on somebody else’s alarm system or something like that.
[0:02:01.1] DA: Yeah, we don’t want that.
[0:02:02.5] MN: In the example as you mentioned before, someone, a user can visit their own piece of information on a website and they’re authorized to do that but an admin may be authorized to visit multiple users or all the users as well. The authentication part of it is checking, “Hey, are you that user? Got it.
[0:02:24.0] DA: Or like an example, like Facebook, like I can go to – I can log in a Facebook, that’s great but I may not be able to go to the admin panel for, you know, Stride’s Facebook page and like edit unless I’m like granted the authorization to do that.
[0:02:42.0] RP: Your authentication server says, “This person has ID 347 and they are an admin user,” and then your authorization layer says, “Oh, he’s an admin user? Great, let him change whatever he wants.”
[0:02:55.6] DA: Then I’m like, “Thanks, thanks system.” What are some examples of authentication strategies?
[0:03:01.8] RP: Yeah, there’s a few different authentication schemes, a lot of frameworks have something built in. So in an example is if you’re using Django, Django has a built in off scheme, it has a session store service that’ll will store your authentication session. It’s even got a strategy pattern built in so you can define whether that’s stored of memory, whether it’s stored in the database and some sort of volatile cash like Redis and then there’s sort of more enterprise solutions. You’ve got the OAuth2 protocol, it’s pretty common. You can be your own provider or you can allow your users to use something like Google’s OAuth provider or Facebook OAuth provider to authenticate against your service.
[0:03:41.7] DA: Or like LDAP or something like that.
[0:03:43.7] RP: Exactly, yeah.
[0:03:44.8] DA: Truly enterprise.
[0:03:46.7] RP: Yeah, single sign on a lot of organization, have to provide that serve enterprise clients. Otherwise their resource management is a nightmare.
[0:03:56.2] DA: Yeah.
[0:03:56.9] MN: What do you prefer developers use?
[0:04:00.8] RP: I think that when organizations reach a point of maturity, OAuth2 becomes the right path forward. As most services, especially if you are in the SaaS space, grow, you know, you’ll have whatever your platform is, right? But then you're going to want to expose API ‘s to users.
Maybe you’re going to have a micro service architecture or some more general service oriented architecture and you’ve got lots of services that need to interact with each other OAuth2 gives you the key abilities to define an authentication scheme that is flexible to most needs.
[0:04:33.6] DA: We even go less maybe. but I’m curious, OAuth2, is that the same scheme that’s used for Google authentication? If I’m using Google profile or a Facebook authentication? That’s all like, in the realm of OAuth?
[0:04:48.6] RP: Right. Yup, exactly. In OAuth terminology, they are providers. So they provide an authorization server, which is confusingly named.
[0:05:00.7] MN: For authorization.
[0:05:02.6] RP: It’s a little bit of both what OAuth provides for you. Yeah, you log in with your Google profile and you’re logging in, essentially you usually start your Auth flow on the service you’re using, which is not Google or Facebook or one of these providers. They will send you to google or facebook, you will log in and then google or facebook sends some meta data back to the client that you're using. That allows them to continuously authorize against your user profile, whatever information they requested.
[0:05:32.9] DA: Now that we’ve got our authentication, we’ve got our little token back, whatever it may be, what do we do with that? Like how do we know what we can do with that or be an authorized to things?
[0:05:47.5] RP: This is where the authorization tier application comes into play. Let’s take the example of a very common example of a rest API. In a rest API, I have resources, that’s the core component of a rest API. A resource user represents some object from your domain. Let’s say, users. Let’s say I have an end point that lets me list users and then get details about particular users and then you can ad users or movie users, more changed details about them.
Authorization determines what I, what of those steps I’m allowed to take, what resources can I see, what resources can I change? To go back to the admin example, right? The admin will typically have grant powers. You might have the ability to create users only be a feature of the admin if you’re running like a SaaS platform instead of a consumer driven one.
[0:06:36.7] DA: Rather than like a self-created user, like a self-served.
[0:06:40.6] RP: You know, like a Facebook where obviously you don’t want an admin to have to create over — all billion user accounts.
[0:06:46.8] MN: Please?
[0:06:49.5] DA: Yeah, I mean, I guess like the example of the users is something that you definitely don’t want to mess up because that can be – get really sensitive very quickly, especially if you have like credit card data or something like that.
[0:07:03.4] RP: Oh yeah. There is an incident actually, in the last couple of years, with Panera where Panera had — they suffered from a vulnerability called insecure, direct object references. If you imagine to get end point like /users/id, right? So I can visit my user profile at Panera.com/users/4. Well, what happens if I put five in?
[0:07:30.4] MN: Uh oh. Uh oh! I think you're a hacker if you do that.
[0:07:34.2] RP: They’re going to back trace me and call the cyber police. Yeah. That’s a type of authorization problem where you have a resource and rest lines that you did not properly check whether or not the current authenticated user has the right to see that resource and exposed all kinds of things, names, emails, addresses, private information.
[0:07:59.8] DA: Man, I guess the honor system isn’t really a good authorization?
[0:08:04.2] RP: I mean, maybe if you’re running some kind of website, right? If you go the blockchain route, right? Everything was public.
[0:08:12.4] DA: Yeah, that’s true. Although, hopefully like eventually like private information, it’s somehow like obscured or encrypted and obviously –
[0:08:22.9] RP: That’s eventually going to be a problem, right? Somebody’s going to put private information that’s not supposed to be exposed on the blockchain and then what do you do? There’s no recourse.
[0:08:30.1] MN: Then it’s there forever.
[0:08:32.2] RP: “Delete it.” “I literally can’t.” This is distributed to thousands of different computers and they all maintain those cache.
[0:08:40.3] DA: Yup, permanent graffiti.
[0:08:43.8] MN: Oh man.
[0:08:43.3] DA: She’ll be like, “Bobby is a jerk.”
[0:08:48.6] MN: In the blockchain. There you go. Forever.
[0:08:51.3] RP: That’s the term of my Ethereum contract, you have to type “Bobby’s a jerk” into those text blocks. Then I will send you $5.
[0:09:01.8] DA: Brutal. What’s a good way to establish like what those rules are for – who is going to be – how can we like, make sure that we’re following this prospective?
[0:09:15.5] RP: Yeah, lots of different framework provide some sort of built in functionality or some sort of plugin functionality. I could speak to Django specifically as an example. It has the concept of actions so these correspond pretty closely to what we think of as a restful actions.
Viewing, actually, viewing was just added today in Django 2.1 for release, they didn’t have that as an available permission before.
[0:09:37.8] DA: Oops.
[0:09:38.3] MN: Nice.
[0:09:40.0] RP: But they did manage create and edit and destroy. Django’s built in, will essentially store, you can say like, explicitly, “User one, two, three can edit, create, destroy or read these kinds of objects or this subset of this kind of object.” And then for Rails, there are similar frameworks. I remember CanCan, way back in the day, that’s –
[0:10:04.1] MN: That’s CanCan or CanCanCan.
[0:10:06.2] RP: No.
[0:10:07.8] MN: Just a derivative of CanCan? Yeah, there’s CanCanCan. CanCanCanCan. Can do that? I don’t know, I always find that hilarious. A lot of Rails applications use CanCan or –
[0:10:19.6] DA: What kind of framework does – or what kind of model does that follow? Is it pretty similar? Like create, read, update, delete?
[0:10:25.4] MN: Very similar or it’s like, can access or can read, like that kind of stuff. You can choose like the role that a person may have and what they can do, given that role.
[0:10:37.5] RP: Sometimes the framework might not cut it. One way that I think that Django solution doesn’t scale very well is that it stores when we’re on the database like per relation, right? So if I have a user and I want this user to be able to edit, like all user objects, I would rather not all user objects, some large subset of them, it will store like one row per relation there, which scales really poorly if you have a lot of data, yeah.
[0:11:03.8] DA: Wow. It’s all those line items on those orders?
[0:11:06.8] RP: Yeah.
[0:11:07.9] DA: So it’s like, “Oh, well this line item, you can definitely – and this one too, and this one.”
[0:11:14.7] RP: Yup, and see if we got a good client with the hundred thousand orders, each of which has 10 line items then you’re looking at a really, really big table with really slow reads.
[0:11:24.2] DA: Wow. Storage is cheap, just scale it on. Git box.
[0:11:30.9] RP: Poor performance though, no one’s going to like that.
[0:11:33.2] DA: Yeah, I guess there’s probably a better alternative to that.
[0:11:37.0] RP: Now you're looking at something like role based or rule base authorization instead. So instead of explicitly storing relationships of who can do what thing, you have some sort of rule that defines who can do it. Maybe you have a user ID on your order. I mean, you probably have that anyways, right? You just say, if the line item which belongs to this order is being viewed by the user with the same ID as the user who created that order, then it’s cool. In fact, they’re allowed to change that line item. Or that user’s an admin user.
[0:12:07.5] DA: I guess that can get complicated pretty quickly though.
[0:12:09.3] RP: It can, you know very well. Yes, with complications come the potential for vulnerabilities. You know, the more complicated it gets, the more likely you are to slip. One of the rules that I really like is that you should incorporate authorization directly into the layer in which you do data access. So I’ve seen systems where your domain model itself is responsible for enforcing this but I think that makes accidents too likely. If you fetch data that you don’t want exposed, then you’re at risk.
[0:12:44.3] DA: You’re already like one step away from doing a bad thing to that data.
[0:12:48.7] RP: Exactly. Don’t even read it into memory if you can avoid it.
[0:12:51.3] DA: Yeah, I guess like, a chore of what we’re doing on the client is like you know, by account, end user, who the viewing context like, you know, do you have the ability to read or update this set of data?
[0:13:09.4] RP: With texture complicated, right? Because you have considerations like where are they viewing it from, or using the mobile app, we’re using the web app?
[0:13:16.3] DA: Oh yeah, that’s true.
[0:13:18.4] RP: You know, you have a user but which account of their many accounts are they using? It can get pretty complicated pretty fast. I like the Django rules library, personally, for Django projects. It lets you encapsulate this logic in predicates that can be reused to create permissions like CanCan style, can view for a specific object but rather than doing a database call. You pass in the relevant objects and it enforces the business logic.
[0:13:46.7] DA: I’ve heard the phrase that like security is like everyone’s responsibility, is there any way that like I can help like ensure that I’m doing the right thing?
[0:13:57.7] RP: Yeah. You’ve got to bake this right into the very fabric of the organization. So there’s a couple of ways that I’ve managed this in the past. Yeah, so, you got to bake it into the very fabric of your organization, really helpful tool that I like. Slack put out their internal checklist tool that they use for their internal software development lifecycle.
Checklists are a really helpful way of making sure that certain security concerns always gets followed. So Slack’s internal checklist asks the question, “For every API you’ve changed, for every object you exposed, for every page or whatever that you added, did you make sure that only the correct users are able to access it?” By asking your developers to go through line by line to this checklist and verify that they thought about this possibility, it’s less likely that you’re going to miss something.
[0:14:49.4] DA: Yeah, then also, like double checking it when you have a review as well. Yeah, I mean, I guess if checklist are good enough for NASA to get a rocket into space, it should be good enough to make sure that you're nailing down your API.
[0:15:03.1] RP: Yeah. It’s just important to make sure that everyone in your organization is aligned on how you do security and has a defined process for how you do it. I think it’s also helpful to have special review processes for API changes in particular. This is lots of a checklist than more of a, let’s get everyone into a room to make sure we understand what the possible edge cases are, what are the ways this could be a wrong? What would be the catastrophic bad case that we know we’ve got explicitly test to avoid? Can we write automated tests to make sure that we’re not doing this?
[0:15:33.6] MN: Yeah.
[0:15:34.1] DA: Yeah, that’s a good point. I think especially with like getting new developers into the organization, if you’re trying to scale a team quickly, that can be a useful resource when it’s not always possible to have like a face to face discussion. Although maybe I should be part of the onboarding.
[0:15:49.2] RP: It’s probably part of the onboarding too. Yeah there’s nothing like a checklist to make sure that everyone’s aligned, even new developers, especially when it’s automatically applied to your pull request or the formal part of the process like Slack solution is.
[0:16:02.1] DA: Yeah, we can definitely link that in the show notes as well. It’s the Slack engineering blog, moving fast and securing things, which sounds a little bit – called to Facebook’s slogan.
[0:16:16.4] MN: Moving fast, securing things.
[0:16:20.7] RP: Got the moving fast part, right?
[0:16:24.7] DA: Yeah. Fast moving bread, straight up.
[0:16:30.1] MN: Straight out the oven.
[0:16:31.1] MN: Straight out the oven. You’re going to get burned.
[0:16:35.1] MN: With any repercussions — were there any repercussions or say like consequences that Panera had to pay a fine or like face or anything like that or is it just like, “Oh snap, we got to change those quick, before everyone gets everyone’s data.”?
[0:16:51.2] RP: Probably not. I didn’t hear about any sort of legal consequences for this leak and this is a recurring problem that eludes in the United States, we haven’t found a good way to deal with. Lots of data exposure. What was the recent one with people’s health insurance information that occurred? I forget the name of the company or one of the credit rating agencies.
[0:17:11.3] MN: Equifax? Yeah.
[0:17:15.1] RP: I think there’s going to be a consequences there? No, they reveal data like every American citizen, what are you going to do now?
[0:17:22.5] MN: Yeah, exactly. Well.
[0:17:24.9] DA: Yeah.
[0:17:25.1] RP: Yeah. That’s not the lesson to take away here that you shouldn’t care about it because –
[0:17:29.0] MN: You should.
[0:17:30.5] RP: With large organizations like that where they are mobile or people aren’t hearing the news, it might not have effect. But especially if you’re like a smaller company, you’re a SaaS platform and your growing company instead of like a large established hedge company. Now you’re at risk, right? There’s real risk that consumers will look at you mistrustfully. They won’t trust your product anymore.
[0:17:51.0] MN: Right.
[0:17:51.7] RP: Good luck getting that enterprise customer to resign after you revealed all of their personal data to the world. Especially if it’s trade secrets. It’s not going to end well.
[0:18:00.1] MN: Right, then vice versa, because your application is growing, there are more people who are looking for your vulnerabilities and try to find ways to get into your data.
[0:18:11.4] RP: Exactly. I mean, anybody who is running a web server for a while has noticed people trying to automatically connect to their SSH ports, right?
[0:18:18.8] DA: Yeah, there are some kind of funny stuff. I remember talking to some of the ops engineers at our previous client I was at and there are people trying to connect to the PHP admin portal using the default creds. But it was hosted in Rails. No way they get positive seed but there’s just some script kitty. Like you know.
[0:18:41.2] RP: You know, every domain in the planet probably gets a hit to /wp-admin.
[0:18:49.9] MN: wp-admin.
[0:18:51.7] DA: Yeah, I mean, that works too. I had a friend who had a WordPress site and it got horribly hacked, it was deeply and horribly hacked and he could not fix it. They were in there, the Russians were all the way in there.
[0:19:02.7] MN: My gosh, the Russians.
[0:19:05.1] DA: The Russians. I think they were Russians, yeah.
[0:19:11.5] RP: Yeah, if you haven’t updated your WordPress site in a week, you probably been hacked.
[0:19:20.4] DA: Oh man I think before we talk like authentication of resources or authorization of resources with rest but, you know, GraphQL is all the rage. That’s a really a different beast where it’s maybe a little more complicated.
[0:19:36.3] RP: It’s definitely a little more complicated, at least with the rest you’re dealing with just one resource at a time, right? But with GraphQL, you have nested resources. You can have these in rest too, nothing’s stopping you. But it’s the reality of every GraphQL application. The question becomes like, “Okay, how is a user getting to this particular type of object?” The way that GraphQL resolution works, you can’t depend on the contextual way that the node was resolved, right?
How did I get to a user, did I get to it through an order? Did I get to it through the user list end point? That gets tricky. That’s one of the reasons that I find moving the data access or rather putting your authorization checks into your data access process, very helpful. Because in GraphQL, you’re loading resources based on some sort of ancestor resource in a query and those connections can get very complicated if you try to implement authorization at each point where you potentially return an object type, you’re going to miss something eventually, right? I was going to open a PR and they’re going to forget.
[0:20:42.9] DA: Right, yeah, there’s many different ways you can get in there, especially if you’re implementing like the relay, a really compliant API where you can access the node directly. Then, every single object is an entry point and every single path from an object to another object is also an entry point. And yeah, you know just graphs, pickups of graphs.
[0:21:06.5] RP: We find it helpful in our data access layer to just have and this actually was inspired by Facebook’s approach. Facebook, if you look at early versions of the relay specification, it always calls for the root of your query including object called “viewer” and they ended up getting rid of it in the relay spec not because it wasn’t helpful but because it was Facebook specific and the reason it’s Facebook specific is that they always have in their data access layer the ability to accept a view as a parameter.
So whenever they fetch objects of any kind, they pass along the viewer and the data access routine uses that viewer in order to contextualize and authorize the payload that is returned by that function. So we implemented that to ours and I think it’s been helpful, a helpful pattern for making it easy to avoid authorization mishaps.
[0:21:58.0] DA: Yeah, it definitely becomes clear pretty quickly when you are looking at PR and they’re not using the request contacts and it is like, “Wait, let’s look at this deeper”.
[0:22:08.8] RP: The next step is to make it automatic so nobody could forget to make that call, that’s the dream.
[0:22:13.0] DA: The dream, but until then there’s a checklist. Yeah, so besides all of these security vulnerabilities with authorization, are there any other nightmares that I should be worried about?
[0:22:26.1] RP: Plenty of them. The best resource I know if you’re being considered about security, the OWASP website, owasp.org. They maintain their top 10 list, which is updated every year or so. It concludes their list of the most pressing, most common, most problematic security vulnerabilities. We mentioned insecure direct object references at Panera. That is an example that commonly makes their list. It includes things like SQL injection, cross site request forgery, cross site scripting. So in addition to documenting the kinds of things you should be scared of, they give you a list of techniques for how to mitigate those kinds of problems. They’re helpful.
[0:23:04.6] MN: Sanitize your data. You don’t want Bobby to drop tables.
[0:23:10.6] RP: Little Bobby tables.
[0:23:11.9] MN: Little Bobby tables dropping all over the place.
[0:23:14.9] DA: Oh man and you know I am looking at the site right now and it is actually pretty nice. There is some good examples and a couple of pictures even, you know?
[0:23:23.5] MN: Oh wow, of how it can fail?
[0:23:26.3] DA: Well you know there is this one picture where there’s these threat agents on the left and they are little stick figure dudes and then they are shooting these attack vectors, which are red lines and they are attacking your stuff and –
[0:23:43.2] MN: You’ve got to secure your stuff.
[0:23:44.9] RP: Or your base will belong to them.
[0:23:46.7] MN: Yep.
[0:23:47.2] DA: Through the vectors.
[0:23:49.2] MN: Awesome.
[0:23:50.4] DA: Cool, yeah it sounds like that’s at least 10 more podcast episodes we will have.
[0:23:55.9] RP: Any of them is its own topic but give it a read.
[0:24:00.3] DA: Cool, yeah.
[0:24:00.9] MN: Awesome, do we have any teach and learns today we want to share?
[0:24:05.7] DA: Yeah, I feel like I am humbled and learning and relearning things pretty frequently this week. So one thing I keep on forgetting is how to properly mock a class in Python. I have done it before and I just don’t have to do it often. When I do it, I forget that in order to mock something you need to be mocking the class at the place that you’re importing it not at the place it’s coming from. So if I have a service that I am mocking in my API, I am not going to mock it at “api.services.thing I don’t care about”.
I’m going to mock it at “api.schema.thing I don’t care about and I want to mock” because it’s technically in the scope of that thing that we are trying to patch it which is confusing. I wish it was better. Like there are many things about Python testing that are not friendly to the beginner.
[0:25:11.7] RP: I agree. That is one of the cases where the implementation details of your code affect how its interface works because it essentially monkey patches the module that you are mocking for at the point where the file gets or the package or function or whatever is important.
[0:25:28.9] DA: Right like once I read this caveat and I remember it then I’m like, “Oh yeah it makes sense.” But I don’t know why it doesn’t stick. So hopefully another six months I will not be having the same one.
[0:25:46.5] MN: I am constantly learning or relearning things in Java Script and like you mention with Python testing, Java Script why do I forget these things and then relearn them? Like, “Oh yeah that’s how that works.” So just dealing with what they call dump components. I realize that you can convert a lot of your dumb components to be state list components that just returns the function and it is just a fat hour and it’s really pretty in there.
[0:26:14.5] DA: You’re talking about React.
[0:26:14.8] MN: In React, excuse me. So in React, you have your dumb component and if it is just going to render something then you can have a use the fat arrow or you don’t have to extend component or anything of that nature. You just return the thing and I always seem to forget that but I learned again and I’ve learned whenever possible, just go stateless all the time and what does that mean?
[0:26:39.3] DA: Get that state out.
[0:26:40.0] MN: If you don’t, if you are not dealing with any React life cycle methods then the component can be stateless.
[0:26:46.6] DA: Yeah just get that out there, no class components if you can avoid it.
[0:26:50.5] MN: Yeah, unless you are dealing with component like component will mount, component did mount, which are actually being deprecated. That is another thing I learned and React 16 the deprecating component did mount and they’re actually renaming the function to unsafe like capital “UNSAFE”. Yeah and it’s like I think it is for the did mount — It’s like component did mount, component did unmounts. There is a list, we should put that on the show notes because it is pretty interesting and they are actually adding new life cycle functions too, which is pretty cool.
[0:27:26.8] DA: Yeah, I mean the functional component just looks really nice, which is like a narrow function and a thing. It looks really cool but it doesn’t really do anything very different from the class component yet but I think that they are eventually going to add some kind of optimization for being pure component where it will hopefully be faster but we’ll see.
[0:27:47.7] MN: That’s the dream.
[0:27:49.5] DA: We’ll just wait for Dan [inaudible] to let us know what’s up.
[0:27:52.9] MN: The dream right there. Roberto, is there anything you want to plug before we wrap this up?
[0:27:57.7] RP: Yeah, if you like hearing about the GraphQL portion of our talk and you are a Python or Django developer and just want to know more on August 14th, JOOR is going to be hosting the Django-NYC Meetup and I will be giving a talk on getting started with GraphQL and Django. Come, it will be great. It will be fun, we can talk afterwards if you have any questions about that or authorization, I am happy to talk about those things whenever.
[0:28:21.6] DA: Cool.
[0:28:22.1] MN: Sounds good.
[0:28:23.1] DA: I am excited for that.
[0:28:24.1] MN: Follow us now on Twitter @radiofreerabbit so we can keep the conversation going. Like what you hear? Give us a five star review and help developers like you find their way into The Rabbit Hole and never miss an episode, subscribe now however you listen to your favorite podcast. On behalf of our producer extraordinaire, William Jeffries and my amazing co-host, Dave Anderson and me, your host, Michael Nunez, thanks for listening to The Rabbit Hole.
Links and Resources: