 Hello and welcome, my name is Micah Silverman and today I'm going to be talking to you about centralizing authentication and authorization with Kong and Okta. Quick little bit about me, here's some background. I am staff security hacker at Okta. I co-authored mastering enterprise Java beans just in time for that technology to become relevant. I contribute to a number of open source projects including the Java JSON web token project and I contribute regularly to Okta's blog, including this reference here on an OpenID Connect primer in case you are interested. Now just to be clear, where I'm not an expert is in Docker, Kong, Lua and Security. We're going to be talking about all of those today. Where I am expert is in Java, Spring Boot, Breaking Shit in general, especially around API's networking protocols and security and expert in security. And if you notice that security is there twice, security is a very broad field and there are some things that I'm pretty good at and some things I know nothing about so I put those in both categories. So let's talk a little bit about Kong. Kong is all about having a centralized API gateway and it provides services on top of it for things like logging and authentication, rate limiting and routing and it's a very modern way to manage your RESTful API. It also is open source and they have an enterprise addition as well but you can get started with Kong totally free forever because it's open source. Now why would you even want Kong well? Let's take a look at our first network diagram here. I'm focusing on modern authentication for web applications and for API, APIs that's often using OpenID Connect. Now deep dive into OpenID Connect is a little bit outside the scope of this talk but suffice it to say that OpenID Connect allows you to securely identify yourself to a website or a service without having to give your credentials to that service. So you have a centralized what's called authorization server and that's over here, that's Okta and then you have one or more services or web applications that are clients to that service provider and you've probably experienced this most frequently with Google or with Apple where you say you go to Gmail and you go to log in, you're redirected over to Google centralized authorization server that's where you provide your credentials and then you're redirected back to say Gmail or one of Google's other authorization or one of Google's other services. The nice thing about that architecture is that the Gmail team at Google doesn't have to deal with credentials and storing them safely, they just have to deal with Gmail and Google's authorization team manages all of the credentials and you get a good separation of concerns. So here's kind of what you might experience with a normal architecture. Let's say you have a microservices architecture or even a single website but one that you want to replicate across a high availability zone and so maybe you have multiple instances of that and then you'll have some sort of a load balance or a gateway in front of it all. So you can see here we have a request coming into AllTheThings.com and you may be routed and redirected through any of these different services and then you're going to be sent over to the authorization server to go and identify yourself. This is fine. This is a good architecture. The challenge here is that each one of these services or each one of these websites has to have an entire OpenID Connect client stack set up with them and if things change or need to be updated you have to do it in a lot of places. If you need to add more services you need to make sure that the OpenID Connect stack is there for all those services. What having a centralized Kong gateway allows us to do is then it's Kong that's interacting only Kong that's interacting with our OpenID Connect provider which is Akta in this case and then Kong sends through an assertion on the X user info header to each of the services or inside websites and that allows these stacks to be a lot leaner. Now your stack only needs to know how to interpret and process an X user info header and then it will be able to identify who the authenticated user is and be able to manage an identity going forward that way so you can have a much leaner stack you only have one entity that's interacting with a service provider at any given time. Now there's a couple of things that we need to tend to in this architecture in the Kong centralized gateway architecture. One is that inside services should only ever accept connections from the API gateway so we don't want our interior services able to accept connections from the public internet because anybody could then spoof an X user info header and then that would eliminate the security that we have in place. So inside services must only accept connections from the API gateway and inside services must use the custom header the X user info header as a security assertion. So as far as these services are concerned or individual websites if the X user info is present and formatted in an expected way that's equivalent to a user having identified themselves securely. Now let's talk a little bit about Docker as I said I'm not an expert but I know enough to get myself into trouble and the example that we're going to go through in a little bit takes advantage of Docker in a couple of important ways. One is that you can have an internal network set up in Docker and you can configure very precisely what can get through that network and what cannot. This helps us to manage rule one here. So our inside service which is going to be a spring boot app we'll see that in just a little bit will only accept connections from our Kong API gateway. So the Kong API gateway is going to allow connections from the outside world and we manage all of that through this internal network. It also makes it because there are some moving parts to this infrastructure. We have our spring boot and spring security app. We have Kong we have a database that Kong relies on using Docker allows us to keep things very manageable and I'm going to run this entire infrastructure on my laptop that I'm presenting from and I can set up and tear this whole thing down very quickly. So here's what our Docker infrastructure is going to look like for the purpose of this example. First of all if you notice port 8080 which is what our spring security spring boot application runs on that's going to be blocked from the outside world I can't get there directly. However port 8000 that's the default port that Kong is going to listen on. We can get there from the outside world internally we have this octa con bridge network and all of these different players all of these different entities can can communicate with each other across this network but it does not have access from the outside world direct access. So the con gateway is going to be able to speak to our spring boot app and it's also going to be able to speak to the Cassandra database to manage its internal state and other things that it requires. So here the con gateway is then going to be able to connect to spring boot on port 8080 and pass along that security assertion. X user info is the the header that's going to come across. All right so let's take a look at this in action and then we'll go through a little bit of the code and talk about how all these moving parts work together. All right the first thing I'm going to do is fire up our con gateway and there's a lot going on in this command so let's take a look at it. Now prior to this presentation I built an image called octa con OIDC that image can be built completely from the GitHub repo that I'm going to share with you at the end of this presentation so that you can run this locally if you want. So I've taken a few shortcuts I've already built the images now we're just going to run the containers and this is some Docker speak if you're not familiar with it. Docker is this kind of big container ship we build images that can be used and then we create containers from those images which are running kind of virtual machines. I also already created the octa con bridge that I spoke about earlier so you can see right here we're referencing that octa con bridge that's the network that it's going to be using. We're also calling out the open ID connect plug-in which this image contains and this is going to activate it once we fire up this container. It's going to use the Cassandra database and then we have a couple of other environment variables for Kong. This one is important here Kong has an admin API that listens on port 8001 and ordinarily we would not expose this to the outside world because it's the the an API that controls Kong's admin but for purpose of demonstration I am going to expose it to the outside world and I do that by telling it to listen on port 8001 and by exposing port 8001 with this command. Finally this is the image that I'm referencing on octa con OIDC so let's kick that off So now this is running and I ran it in an interactive mode so that we can just see the output and what's happening there and if we take a look this is my I don't know if I can make this bigger doesn't look like I can but this is the Kong or rather the Docker interface on Mac and you can see that I have this Kong database running that's a running container and now I have the octa con OIDC container running. So we've got some of the parts of our infrastructure here that we just discussed right so right now we have the con gateway and we have Cassandra the last piece we're going to run here is our spring boot application and that also is an image that I created and we're going to run it inside a container. We could just run it locally we could run all of this locally but having it run in a container keeps everything nice and neat. It also sets up the networking in a way that that we want to. So here I'm running this thing called the header origin example I'm using the same octa con bridge and I already have the header origin example image and if you're familiar with spring boot you may recognize this splash screen so it's running the spring boot application and we can see here that it's listening on port 8080. Okay so now let's just take a look and see what we have running here. We can see in Docker I have three containers that are running I have the spring boot app I have octa con or I have this image this container called octa con that's our con server. It also shows us open ports so here's 8000 to 8001 and I also have the con database which is our Cassandra database that was previously set up as well. Alright the next thing we're going to do now is to establish some services and routes so right now we have these three pieces we have the con gateway Cassandra and spring boot and con and spring boot are not connected in any way right now so an incoming request to the con gateway doesn't know where to go right now so we're going to establish that using some con API commands and I'm also going to use some some shortcuts here so I'll show you exactly what's going on. First thing I'm going to do is set this thing I'm calling service ID now what it's doing is it's submitting a form to the services endpoint and it's giving it a URL and so this is the URL to our header origin on port 8080 and it's giving this service a name octa secure and then I'm piping the output through a little tool called jq which is a JSON parser the result of this call is JSON I'm pulling out this unique ID for the service and I'm assigning it to the service ID environment variable this is a little shortcut because for the next command we've defined the service now I'm going to call the con admin API and add a route and I'm basically saying for all paths that is slash I want to take advantage of this service and route it to the service so all paths starting with slash are going to be routed to the the spring boot example let me do that that will also be a JSON response and we can see that this has its own unique ID as well and we can see that it's covering all of these paths now it's worth taking a step back here for the purposes of example I've put together a spring boot web app now Kong we think of is a centralized API gateway so for purposes of demonstration I just set this up as a simple website but this approach would work just as well for a cluster of disparate microservices that were sitting behind the API gateway alright so now we've set up our route anything coming into Kong at port 8000 will be sent over to the the spring boot application the internal spring boot application on port 8080 let's take a look at this a little bit here let's just see what we have right now I'm going to bring up an incognito window first I'm going to go to local host 8080 and we can see that nothing that is accessible to me is listening on port 8080 well let's check out port 8000 we know that's going to send me over to the spring boot application and now you can see that I'm getting this 403 error because Kong is sending me over to the spring boot app but I have not been authenticated in any way and so therefore the app just rejects me it's forbidden well in order to fix that situation we need to activate the open ID connect plugin with some specific information so let me paste this command and we'll break this down just like we did the other one so now I'm submitting a form using Kong's admin facility admin service to the plugins endpoint and the plugin I'm interested in configuring is OIDC I need to give it a client ID and a client secret which I previously set up and I need to give it this thing called a discovery URL and I'm going to pipe the output into jq and I'm going to remove the client secret that's with this DEL I'm going to remove the client secret from the output because I don't want you all to see the client secret but we can see that this is now configured with a client ID and the discovery is an octa URL because octa supports open ID connect and so now we've configured this open ID connect plugin for Kong and any incoming connections to Kong are going to require that we've been properly set up with open ID connect let's see what that looks like so I'm going to go back to localhost 8000 I'm going to go in one more time now I'm directed to octa to authenticate so far so good now before we continue and actually well let's do this let's see it in action and then we'll talk about some of the mechanism of what's going on here behind the scenes so let me go ahead and authenticate I'm going to make this little bigger I'm going to log in as this user called Joe user and assign in notice up top here I'm over here in octa world I'm going to sign in then I'm going to get redirected back to the app and now the app recognizes that I am in an authenticated state so it's addressing me by name and now I have these other buttons users only and admins only I click on users only and it shows me a list of the groups I belong to and now notice if I click on admins only I get this unauthorized page because I am not an admin so Kong and and my spring boot app are aware of not only my authentication but also my authorization that is the roles the groups that that I belong to look at one other quick one here let's jump back to port 8000 this time I'm going to log in as Sally admin okay now it's again it's recognizing me by name if I go to users now I can see these are the groups that I belong to and now if I go to admins only I can get in there because I am a member of the admins group so this kind of proves that everything is now working everything is hanging together I can't get to the app directly I can get to it via the Kong API gateway that's where the open ID connect dance is happening and then it's passing along this internal assertion and we can even see some of that in action if we jump back here to our output I scroll back just a little bit notice here Kong is saying that it it knows who I am and and it's parsed this thing called an ID token that's an open ID connect asset that you get back and it recognizes who I am and it has a list of groups and it's going to pass that list of groups along and we can even see in the spring boot output looks like we got an error here but somewhere in the spring boot output so notice spring security detected this X user info header with a base 64 URL encoded value it decoded that base 64 value to this JSON and now the application recognizes who I am because this assertion came in and it was able to to recognize it all right so let's take a look now at some of the code that backs all of this to to see what's going on here first let's take a look at at the octa configuration because that's kind of what makes all this hang together and work so here we go all right so now in octa I can go and see that I have this application I have a number of applications defined but I have an application called Kong API gateway it has a client ID and secret which I configured Kong with and it also has assignments so I have these users Joe user and Sally admin and I have these groups called users and admins and I've assigned those groups to this application so anybody who belongs to these groups can access this application I also have an authorization server definition and here's where things get interesting and some of the power that that octa gives you I have added some custom claims now we haven't talked about the details of open ID connect and we're not going to get too far into the weeds here but open ID connect sends back a token called an ID token that identifies who the authenticated user is and here I'm defining some additional information that I'm going to add to that ID token most importantly I'm adding a list of the groups that the authenticated user belongs to and then I'm adding some individual details like a full name and the user's email so that comes back in the ID token and we saw that in the output here from Kong let's see if it didn't scroll away too far so we saw that here that the ID token that's coming back in addition to whatever else it might ordinarily include it also includes this user full name it includes user email and it includes an array of the groups that the user belongs to so this is the glue that makes everything hang together this definition in octa and the only thing I need to give to Kong is this this issuer information and over here in the application I had to give it the client ID and the client secret now Kong knows how to speak to octa because we're dealing with standards here so it's not that Kong specifically knows how to speak to octa it's that Kong and octa both speak open ID connect let's take a quick look at the code to round out our tour here and this is very Java specific but you could manage this sort of architecture with any language and framework but the important bit here is that I've defined for spring security I've defined this custom filter and the filter attempts to get a user from this class that I created called request context user if it's able to find the user then it sets the spring security context to say that hey there's an authenticated user so we're hooking into the natural capabilities of spring security to indicate that an authenticated user this app is now aware of an authenticated user because it was able to find the user now here's where the magic happens with finding the user and that is we have access to the HTTP request and I have this header that it's looking for x user info and so if that header is not null then it's going to come here and it's going to base 64 decode the x user info header and then it's going to use the built-in Jackson mapper to take that JSON string and marshal it up into this user object so between the request context user and the filter we're able to find a user if one exists and then in our spring security security configuration I simply add this filter into the stack of filters that are used to determine whether or not there's an authenticated user so that's what makes it all hang together from the perspective of spring security last thing to look at here is by default all paths are secured meaning you can't just get to there we saw that before I had enabled the open id connect configuration in kong we saw that that was the case if we look at this secure controller we can see these endpoints we have slash users and admins and they all require authentication but for users and admins it's actually making use of or it's adding the user it's automatically injecting the found user into this method in the controller and now we can add that user to our model we're in the world of model view controller here and so then these resulting pages can show us information about that authenticated user we'll take a very quick look at that if we look at the roles template if we look at the roles template you'll notice that it's taking a look it's iterating over the list of groups that the user belongs to and it's showing us each of those each of the groups that the user belongs to let me find my place here so that has been a brief whirlwind tour of using kong and octa together to centralize auth that's both authentication and authorization for your your spring boot apps so I have a qr code here you can get this presentation deck you can get access to this video and to blog posts that I've done about it you can always tweet me at a fit nerd or tweet the whole developer advocacy team at octa at octa dev and I hope this has been instructive and we'll see you soon