spring-spring-security

Source Webpage
Source Code

Chapter 00 - Introduction

Lecture 001 - Welcome

Introduction
  • Security frameworks provide us with valuable and required feature sets with little effort.
  • In the Java world, the premier framework of choice for security tasks is Spring Security.
  • It is often one of the most overlooked, because often, when someone figures out a pattern for your company, everyone just copies that pattern and moves on.
  • This course aim to provide you with the information you need to understand how the Spring Security framework works to solve authentication and authorization concerns
  • Look at some of the most common extension points, like LDAP, active directory, and Oauth2.
  • Also focus on showing you how to use Spring Security to set up your own Oauth servers for securing your applications and services.
  • This course will be fast-paced but will aim to provide you with enough material and knowledge to discern how Spring Security works, how to make it work for you, and how to extend it to maximize your value.

Lecture 002 - What you need to know

Language
Web template
Tools used
  • Also use a command line utility, called HTTPie, in order to make web traffic easier in the command line
  • Have a plugin in there called JSONView

Lecture 003 - Working with exercise files

Chapter 01 - Spring Security Concepts

Lecture 001 - Introduction to Spring Security

Security layers
What is spring security
  • Spring Security is a project that provides amazing abstractions in the J2EE, now called Jakarta EE, application space.
  • These abstractions help solve the various issues of traditional Java enterprise security like portability and vendor lock-in.
  • By abstracting these topics, we are providing a clean and efficient way to provide security services.

Lecture 002 - Authentication vs authorization

Authentication
Authentication support by spring
Authorization
Authorization support by spring
  • Most common and the one we'll dig into exclusively in this course is Web request based authentications
  • You can leverage Spring Security to provide domain object instance access control, which can be very powerful in highly sensitive areas like PII, financial and health care information

Lecture 003 - Spring Security projects

Overview
  • In java, It's finding the classes that you need that is hard.
  • The spring framework is broken up into many different projects.
  • This level of granularity is nice, but it requires some pretty detailed knowledge of the projects to get around.
  • Spring data, for instance, has projects for each technology that it works with, like Mongo or JPA.
  • All of this granularity allows you to only bring onto the class path what you need to do your work instead of a lot of bloat that frameworks often bring.
Most common projects
  • The spring-security-core project contains all of the classes needed for core authentications and authorizations.
  • In addition to the core class, any custom configurations using XML or Java config requires the spring-security-config project.
  • Once you move into servelet API for web based applications, you need spring-security-web.
  • The final core project that you will use as often as the core project itself, hopefully anyway, is spring-security-test, which provides the apparatus needed to adequately test applications that are using spring security.
Specific projects
  • Spring-security-ldap, which as you might imagine, provides the ldap authentication, as well as active directory support.
  • Spring-security-oauth2-core provides the classes needed for oauth2 as well as openiv1.0 operations as a client, resource server or authorization server.
  • The spring security two client project provides client operations for oauth2 log in and oauth client support.
  • Spring-security-openid provides support for authenticating to an openid server.
  • Now the final projects in the mix are less used in my experience, but you may have a specific use case that requires them.
Less common projects
  • The spring-security-oauth2-Jose project provides support for javascript objects signing and encryption specifications, such as JOT, J-W-S, J-W-K and J-W-E.
  • Spring-security-remoting is used for securing remote client invocation operations using spring framework remoting.
  • Spring-security-cas provides support for authentication with cas, single sign on server.
  • Spring-security-acl provides domain object-based security operations.
  • Now that we've quickly gone through all of the projects, let's actually dig into some code and start leveraging spring security to secure a web application.

Chapter 02 - Securing Web Applications with Spring

Lecture 001 - Implementing basic authentication

About the project
  • This project has no security, let secure it
Adding dependency
  • We're gonna use the spring boot starter security.
  • Now you may notice here that I've got dev tools listed on the web application itself.
  • And, indeed, I could leverage dev tools if I was making a change to a class within my application.
  • But because I am actually adding to the class loader, I need to go ahead and re-start my application.
Open the page
  • And you'll see that immediately I now have forms-based authentication, and I haven't done anything.
  • And that's because the default behavior for spring security, once it's added to your project, is to enable forms-based authentication for the entire application.
  • Now you may notice, well there's a user name and a password, where does that come from?
  • The user name, by default, is user.
The password
  • And the password, if we go back to the console for our application, you will see that I have this user-generated security password.
  • And there's a nice UUID listed here.
Authenticated
  • Use the account above log in to system, home page appear
  • We don't use default forms-based authentication, let use another mechanism
Config security at gateway project
  • We permit all static resource and home page
  • We restrict authenticated for the rest
Test
  • And from Chrome, I'm gonna navigate, once again, to local host 8080.
  • Now you will see I have full access to this page, because I told http basic to allow this page to any request.
  • But if I click on view guests, you will see that I get the http basic authentication window that is default for my web browser.
  • That's all there is for http basic authentication in a spring application.

Lecture 002 - In-memory authentication

Warning
Implementing in-memory authentication
  • We add some users
Test the app
  • Note that in the console, we don't see the generated password any more because we didn't user default UserService
  • We can free access to home page
  • Click on View Guests, system require authentication
  • Input account, then we can go to the page View Guests

Lecture 003 - JDBC authentication

Adding dependency
  • Add spring-boot-starter-data-jpa
  • Add h2
Create entity User
Disable auto generate ddl
  • We will use sql files to create schema
Create repository class
Create user principal class
  • Spring security relies on principles, not users, so we need a way to build and translate the two.
  • So let's create another class called Landon user principle that will implement the user details interface.
  • Class extended from UserDetails
  • We add a grantedAuthority "USER"
  • Password and username got from user
Create user principal class 2
  • Return true for all last 4 methods
  • Ideally, if we were building this out for production, we would have these values in our database so that we can lock accounts and things like that.
  • But for the purpose of this demo, we'll just return true on all of those.
Implement service class
  • It extended from UserDetailsService
  • We need override loadUserByUsername(), which return a principal
Configure
  • We create needed classes, now going to configure
  • Inject UserDetailsService
  • Create bean DaoAuthencitationProvider which uses UserDetailsService
  • For demo we configure store password in plain text (line 31)
  • Override a method to specify authenticationProvider
Access to app
  • To to home page, click on the link, enter credential, system navigate to Guests page
The account data in db

Lecture 004 - Leveraging bcrypt for hashing

Password rules
  • There's really no valid reason that I can ever imagine that encrypting a password is a good idea.
  • Today, the best option that I can use is bcrypt.
  • And the bcrypt libraries are built in to Spring Security, which makes them super easy for you to implement in order to make your code work, and protect your customer's data.
Data contains password is bcrypt hashed
Specify bcrypt for the provider
  • And we are very simply gonna replace our NoOpPasswordEncoder with a new bcrypt password encoder.
  • Now, the constructor takes a value.
  • The default, or if you don't provide a value, is 10, and it's gonna run bcrypt 10 times.
  • Here we use 11.
Test the app
  • The app run as expected
  • Now, you may have noticed that there was a little bit of a delay there from what we saw previously, and that's actually expected.
  • In fact, that's one of the features of bcrypt.
  • Because you actually don't want your hashing algorithm on an authentication routine to go too fast, because it allows your site to be brute-forced much easier.
  • That little bit of delay, actually will slow down a bot dramatically.
  • So, that's actually a feature of bcrypt.

Lecture 005 - Authorization

The schema
  • We have auth_user_group table
Data in db
Create entity
Create corresponding repository class
Modify the user-principal class
  • Inject list of AuthGroup to build list of grantedAuthority
Modify the service class
  • We get groups from the repository then pass them to user-principal object
Secure the apis
  • We user @PreAuthorize at line 38 and 46 and 52
Configure spring
  • We're going to set enable global method security.
  • Pre-post enabled is going to be set to true.
  • This will actually turn on our method level security
  • So you may remember that we set our methods to role underscore user, or role underscore admin, but in our database file we only have the roles of user and admin. So we need to go ahead and map those two. (method authoritiesMapper())
  • To specify mapper, we set it to the provider at line 37
Access the Guests page with jdoe user
Jdoe can access the Guests page
  • Let click on Add New Guest
System shows the error page
  • Because jdoe doesn't have Admin permission
Login with user has admin permission
  • We can access "add new user" page
  • And that's essentially all the steps that you need to implement not only authentication, but authorizations using basic auth with spring security.
  • Now we're going to enhance this a little bit and get a little bit better login view.

Lecture 006 - Form-based authentication

Limitation of basic authentication
Forms-based-authentication
Steps to implement

Lecture 007 - The login page

Adding the dependency
  • Thymeleaf-extras-springsecurity4
  • Now, you may ask why we're using four and not five.
  • And the answers actually very simple.
  • Five is not quite ready yet.
  • And four is completely backwards compatible for everything that we're gonna use it for.
Import thymeleaf tags
  • Brought in an XML namespace, for security.
  • And it is bringing in the org.thymeleaf, Thymeleaf extras spring security namespace.
  • Now this gives us access to a couple specialized tags that we can use throughout our application itself.
Layout.html
  • And in that sec authorize, if it's anonymous on line 25, you'll see that on line 26, we're gonna show the word login with an anchor.
  • However, if the user is authenticated, we won't validate on line 25, but instead we'll validate on line 28 and we'll get a link to go to the logout page.
  • And that's essentially something that we've now added to every single page within our application through this layout.
Login.html
  • So, our login page starts on line 11, with an error section.
  • If we come to this page, and we have a parameter of error, then we're going to assume that there's an invalid user name and password.
  • And as such, we will show that with an alert.
  • Otherwise, the rest of the page is really just a traditional login form.
  • Define get-mapping for login page
  • From line 37 to 40
  • We're not gonna use the "model" (parameter) for our example, but it's a good habit to have it just in case you do need to use it.

Lecture 008 - The logout page

Logout.html
  • We have a simple landing page and on line 11, you'll see that we just print out a message that says, "You have been successfully logged out." That's really all there is to our logout landing page.
  • Spring Security actually handles all of the actions of the logout itself, so we just need a place to go.
  • Now, because this is a template, we need to have a way to serve this template.
Mapping logout in controller
Error.html
  • If you create a template as I have done here called error.html and put it into your templates directory, it will handle all error conditions through this.
  • Now Spring MVC also provides a way for you to build custom error pages for each message as opposed to flexing through one page.
  • Now, that's beyond the scope of this course, but know that you can do that as well, if you choose to.
Error.html
  • You'll see that I'm actually pulling the error as a status and that will give us that this is forbidden or not found, or bad request and then below, I'm actually gonna go ahead and return the status code.
  • And I'm doing this using some Bootstrap list group decorations to give the text a red background to sort of make it stand out when we're in this error case.
  • Now, because Spring MVC handles all of the error flow, we don't actually need to build a controller for this, so that's all we need to do to have our error page, and next up, we're gonna wire all of this together.

Lecture 009 - Putting it all together

Configure
  • Line 62, where we're specifying basic auth.
  • We're going to replace httpBasic with, as you might expect, formLogin.
  • Now we've got several elements that we need to add to formLogin.
  • So the first thing that we need to tell it is what is our loginPage.
  • And in this case, it's at /login, where we put that controller.
  • And we want to have it permitAll to that, which should make sense, because everybody needs to get to the login page if they're not logged in.
  • And we're go ahead and put an and in here.
  • And now we're gonna specify our logout.
  • And during logout, we wanna go ahead and invalidate our session, and we want to clear our authentication, and then we're gonna do a logoutRequestMatcher, and in here we're gonna do a new AntPathRequestMatcher, and we're gonna do a path of logout.
  • Now the last element that we need to put in here is we need to tell it, where to go to after a successful logout, so the logout success URL.
  • And here's where we're gonna do /logout-success and we need to permitAll to that page, because of course you've actually logged out.
  • Now that's all there is to it.
Test - no authenticated
  • App show "Login" link
  • Click on Login, app shows login page
Test - was authenticated
  • Input credential, app shows "Logout" link
Test - error page
  • Let access unknown url /foobar
  • App shows error page
Test - logout page
  • Click on the logout link, app shows logout page
Test - forbidden
  • Let access webpage with jdoe, who has only USER permission
  • Access to /guest/add, app shows Forbidden page

Chapter 03 - LDAP Authentication

Lecture 001 - LDAP for authentication

Why LDAP
  • LDAP, or Lightweight Directory Access Protocol, is a lightweight user authentication directory structure.
  • It's built in natively into many operating systems and of course, there's stand-alone implementations as well.
  • One of the biggest benefits of LDAP is the fact that it's interoperable among many different operating systems and components.
Spring security LDAP
  • Spring Security LDAP is not a very hard project to learn.
  • It offers full support for all native LDAP operations that you would need outside of authentication, as well as in authentication, and while we're gonna focus primarily on the authentication routines, it is good to keep in mind that you have other accesses to LDAP outside of authentication.
  • Spring Security also provides adequate support for password hashing that most LDAP implementations also support.
  • Now, the paradigm that we're gonna use is going to be very similar to what we saw with basic and forms-based authentication.
  • LDAP authentication still leverages the AuthenticationManagerBuilder that we have been configuring in our security configuration class.
Paradigm
Internal
  • We're gonna use the embedded LDAP server that's part of the Spring Dependency Management Structure.
  • You don't have to use the embedded LDAP server if you don't want to.
  • You can use something like OpenLDAP, and if you've got a Mac, it's built-in and ready to go.
  • You may be asking yourself, well I've got access to Active Directory, can I just use it for the purposed of this demo?
  • The short answer is you can.
  • It's a little bit different, and we're gonna talk about some of those differences.
  • However, it's important to note that Active Directory is not LDAP, but it can use LDAP for authentication routines.
  • Both of them are based on a directory structure, and it's very similar, but they are not the same, and we should be really clear on that.

Lecture 002 - Configuring a sample LDAP server

Adding dependency
  • Spring-security-ldap
  • Unboundid-ldapsdk
Adding some LDAP properties
Ldif
  • We start with a base DN of Frank Moley com.
  • You'll see on line eight, that we had an organizational unit of people, and then on 13 we had another organizational unit of groups.
  • Then, on line 18 we add a user, fpmoles.
Ldif
  • You'll see that we also add a user on line 30 of jdoe.
  • And then as we go down here to 39, we build an admin group of unique names, and in this case, the unique name is fpmoles for our admin group.
  • And then we go down to line 45, and this is our user group.
  • We've got fpmoles and jdoe in our user group.
  • This is much the same structure that we had in the database, but now it's contained within an ldif file.
Check the log
  • You can see right before the live reload server, that it talks about a user DN.
  • This lets us know that our actual LDAP server has come up.
  • If you, on your machine, have an LDAP system, you can query against this at 8389 on the local host.

Lecture 003 - Implementing LDAP for authentication

Configuration
  • So we're gonna start with an auth object and then we're gonna do a .ldapAuthentication and a .userDnPatterns.
  • Now, here we're gonna specify that the uid is the value that we're using as a login routine, and that that exists in the ou of people and if you remember how our LDIF file looked, that's exactly the structure that we are going to be using.
  • So now we're gonna set up our .groupSearchBase and our .groupSearchBase is an ou of groups.
  • Now, we're gonna set our .authoritiesMapper so that we can get that role_groupname for our actual roles and we'll go ahead and use that bean for the authoritiesMapper that we created above.
  • And now we're gonna set our .contextSource, and on our .contextSource we're gonna set a .url and the url that we're going to use is ldap://localhost:8389 which is the port that we specified and then we're gonna do a /dc=frankmoley,dc=com and again that maps what we put in our properties file.
  • So, now we're gonna do an .and on that and we're gonna now tell it to do a .passwordCompare and for the .passwordCompare we wanna use an encoder.
  • Now, we've encoded our passwords with the SHA hash algorithm, so we're gonna go ahead and choose that.
  • You'll notice that it's deprecated and that's okay because it's just a demo.
  • In reality, just like with the JDBC based authentication, we would want to use a bcrypt hash or something significantly similar to that.
  • Now, the last thing that we need to do is we need to tell it which value in our structure is the password and in this case it's userPassword camel cased.
Test
  • If use fpmoles user, we can access any where
  • If use jdoe, we access somewhere
  • So, the app run well

Lecture 004 - Spring LDAP outside of authentication

Not only security
  • So to a casual person in technology, when you hear LDAP you may only consider authentication.
  • While that is an important use case, it isn't the only one.
  • In fact, there are several valid use cases that you may encounter where LDAP can be a viable solution.
  • The project for working with LDAP outside of the security sense is spring-ldap-core, and I have professionally used this project a few times for some really big projects.
  • The uses, in fact, were so critical to HR that I feel that it's worth this entire video on this topic so that you know it exists.
LDAP operations
  • Many of these use cases are not even security focused, they are simply in my experience employee-related tasks.
  • One of the beautiful aspects of the way the Spring team works is the cohesion of the framework itself and LDAP operations are no exception.
  • The first and most common for many people is search.
  • There is also support for building distinguished names in a very simple LDAP name builder, mostly associated with the JDBC template and often you use one to serve the other.
  • Back to the template support, you also get binding support, which is the creation of nodes and associated with that you get updates and deletes.
  • Finally, there is full support for the repository patterns within LDAP.
Use cases
  • One really powerful use is an employee onboarding system where the user is added to the directory dynamically based on conditions being met, like signatures being fulfilled and things like that.
  • Another valid use case is the various HR management systems, especially for those targeting communication.
  • By leveraging groups that may not be visible to the entire company, communication channels or email lists can be generated while obscuring those from the view of those not in the group.
  • It can also be a very useful tool when building HR or physical security directory tooling or search programs.
  • I've also seen it used for alerting systems, for weather, and other warnings within an enterprise.
  • Finally, I think it's important to admit that there are other pieces of data that you can store in LDAP other than users.
  • And those use cases can get huge wins by leveraging spring-ldap-core.

Lecture 005 - AD vs LDAP for authentication

AD is not LDAP
  • Using Active Directory from Microsoft for authentication in a Spring Boot application.
  • Now, it's important to note, that Active Directory is not LDAP.
  • And that sometimes really gets confused in the industry, because people deal with LDAP, and quite often they are connecting to LDAP URLs, but really they are hitting Active Directory.
  • It's important to note this because Active Directory implements an LDAP API, but Active Directory is much more than LDAP.
  • Now, the LDAP interface is really what is exposed, and it's exposed to the AD Lightweight Directory Services, and that's contained within the structure of Active Directory itself.
  • Now, again, Active Directory isn't LDAP, because Active Directory provides many, many, many more services.
  • And if you look at the port requirements of a Domain Controller, you get a real feel for the weight of Active Directory, versus a very small, lightweight LDAP implementation like OpenLDAP.
  • But that being said, Active Directory is, by far, one of the most popular enterprise solutions, for managing Directory Services among other things.
  • And as such as a Spring Developer it as critical that you not only understand the differences, but understand how to leverage your knowledge of LDAP to intergrade with your Enterprise Active Directory.
Authentication with AD
  • Now, authentication with an Active Directory can be standard, but there's also some non-standard methods.
  • We're not gonna deal with those from the perspective of Spring Security, but just know that there are some differences.
  • Now, configuration in an Active Directory situation is very, very similar to what we've previously looked at in LDAP.
  • But I do wanna give you a little word of caution.
  • Now, one catch with Active Directory is all too often we build Nested Group structures.
  • In fact, that's considered a feature of Active Directory, to build groups within groups within groups.
  • That way you can cascade permissions down across your organization.
  • But in the Spring Security world, Nested Groups don't natively work out of the box.
  • And there's actually a Spring Security ticket SEC-1823, that talks about this.
  • And there's some conversation there, actually between Rob Winch and myself, where we're talking about the fact, that this support, in my minds eye, seems natural, but it would be a non-passive change in Spring Security.
  • So Rob has provided a very clear implementation step, and it's one that I've implemented and I highly recommend you go take a look at that ticket, if you're dealing with Nested Groups within your structure.
Authentication provider
  • There's an authentication provider, and instead of an LDAP Authentication Provider, it's an Active Directory LDAP Authentication Provider.
  • And just like we did before, in your configure method that has an Authentication Provider Builder, you are going to utilize this LDAP provider.
  • And you're gonna do that in your Web-Security Configurer Adapter class.
  • Again, mostly it's gonna be the exact same.
  • Where you're gonna have some play is in the group to role matching, and you're gonna have to do some extra work on that.
  • That's just because the nature of the Nested Groups that we get all too often in Active Directory.

Chapter 04 - Leveraging OAuth 2 with Spring Security

Lecture 001 - OAuth 2

What is OAuth 2
  • So OAuth 2 is a protocol as well as a framework for providing access to HTTP services.
  • Now those services can be traditional web services as well as web applications.
  • It's often used for third-party access, so if you use social media and you grant an application access to your Facebook profile, for instance, that's done through OAuth 2.
  • Google provides the same sort of structure with its frameworks.
  • It's so common that you may not even realize you're doing it, but OAuth 2 really is all over the place.
  • It also can be used for system-to-system communications in standalone mode or on behalf of another user.
  • And from my perspective, this is actually the most common use case that I use because we actually secure all of our web services calls with OAuth 2 between client and server on purpose in order to make sure that we're protecting the data as needed.
Parts of oauth 2
  • The first is the resource owner, and that's the data that actually is being protected.
  • So for instance, my profile data in Google would be the resource and I'm the owner of that data because it's about me.
  • Now the client is the application that, for instance, I am using or a service that is being used on my behalf that is requesting access to the resource.
  • The resource server, in my previous use case would be Google's profile system itself.
  • So it is the system that hosts the protected data and the accounts that we're requesting access to.
  • And the authorization server is the service that grants tokens on behalf of me to the data that the resource server itself holds.
Token types
  • There's a couple token types, and we need to know about these tokens as we're interacting with OAuth at a systemic level.
  • The first is the access token, and this is the secret token that is used to identify the user.
  • Often, it is very short-lived, and that's on purpose because that token uniquely identifies me and whatever permissions I've associated with it.
  • As such, we don't really want it to live for a long time because if it gets leaked, the security breaks down.
  • Now, the refresh token is a little bit longer-lived token.
  • It is used to renew an access token when that access token expires.
  • So you may have an access token that lasts for a day, and you may have a refresh token that lasts for a week.
  • So what that means is, if I log in today, I use my access token.
  • IF I come back tomorrow, I would use the refresh token to renew my access token.
  • However, if I don't come back for another 14 days after that my refresh token and my access token will have expired and I will have to go through the process of granting access once again.
  • Now, scopes are provided on the access tokens, and it's essentially the rights that are associated with that token.
  • So, for instance, in a server-side component, let's say we have a service that serves customer data.
  • We could grant access to another system that says you can access customer data while not providing that same scope to a different access token.
Grants
  • Now I kind of alluded to it here, but there's a couple different types of grants.
  • And those grants impact flow throughout the system.
  • Now the authorization code grant is the most common, and that's what you would see on something like Facebook or Google, where you're granting access to someone else on your behalf.
  • Now, an implicit grant is very common in web apps and mobile apps where the security of that access token cannot be maintained.
  • Often, these don't come with refresh tokens, and they're very specific to the function of the application being granted access.
  • Now, the one that I use the most often, and as I alluded to previously, is the concept of a client credential.
  • Each system gets a client ID in secret that it uses to get an access token to then do its work within the system based on the scopes that we previously defined.

Lecture 002 - Spring and OAuth 2

Oauth 2 provider
  • Spring has full integration for this protocol.
  • One of the first classes you may interact with is the common OAuth2 provider.
  • And this is used to connect to such systems as Okta or Facebook.
  • And we'll look a little bit more at this later on.
  • But as I said, it provides native support for things like Okta, Google, Facebook, GitHub, and several other OAuth providers.
  • It's property-based configuration if you're in a Spring Boot.
  • And that's most often how you're going to use this class.
  • By using the property-based configuration, you actually get native support in the Spring Boot app, with very little work.
  • It provides client-side OAuth integration.
  • It allows you to provide 3rd party support for the log in operations so you don't have to keep that information in your site, which is very attractive to a lot of companies that don't want to manage the overhead of bringing user authentication in, because after all, when user authentication leaks, that's what makes the news.
Authorization server
  • And we're going to spend some detailed time working with an authorization server.
  • This is what provides authorization and authentication services to the system as a whole.
  • Many companies, mine included, choose to have our own internal authorization server, to provide that utility to not only our mobile applications but also internal services.
  • Creating the authorization service really is as simple as using an annotation @EnableAuthorizationServer.
  • And as we'll see, there's a lot more configuration than often you're going to want to do, and we're going to do that.
  • You use an AuthorizationServerConfigurerAdapter to configure that authorization server when you're going to use it.
  • And again, this is the pattern that we're going to follow as we go through the rest of this chapter.
  • One of the beautiful parts of configuring your OAuth this way, is you actually have support for multiple grant types.
  • Now we're going to use just one in our example, but the point is, is that you can support various grant types, many times with the exact same configuration for those same grant types.
Resource server
  • Now the resource sever provides the resources that are being protected.
  • And often this is a person system, but it doesn't always have to be.
  • Configuring the resource server literally is as simple as doing an @EnableResourceServer.
  • Now you can go further than that if you choose to, and often when you're separating your authorization server from your resource server, you will need to provide a lot more configuration.
  • In our examples we're no going to do that.
Client
  • Now the OAuth2 client allows you to have full client side support for OAuth systems, often when you're not using things like Facebook or GitHub.
  • To enable the client, you use annotation @EnableOAuth2Client, and then you provide yourself the ability to create a rest template.
  • But it's a specific rest template.
  • It's an OAuth2 rest template that's actually going to manage all of the tokens, manipulation, and injecting them into headers, that you would normally have to do if you were manually configuring this system and consuming it.
  • So by using the OAuth2 rest template, we get a lot of that scaffolding for free, much as your might expect from the Spring framework.

Lecture 003 - Creating an OAuth authorization service

Adding dependency in gateway
  • Spring-security-oauth2
AuthorizationServerConfig at microservice project
  • The first is "EnableAuthorizationServer" and the second is "@Configuration".
  • Extend the authorization server configure adaptor.
  • Overide is the configure method that takes the authorization server security config.
  • And we're now going to add a security item .passwordEncoder, and we're going to set it to a NoOpPasswordEncoder.getInstance.
  • And then we're going to do a .checkTokenAccess.
  • And we're gonna set that to in quotes, "permit all Camel cased" as a method call.
  • And then we're gonna do on tokenKeyAccess the same thing.
  • Now the purpose of these is to allow these two endpoints access to users that are authenticated, but regardless of which role they have.
AuthorizationServerConfig at microservice project
  • Configure method that takes the client detail service configurer.
  • And we will do endpoints.tokenStore.
  • And the token store that we are going to use is an in memory token store.
  • Now again, in production you're not gonna do this in memory but for the purpose of this demo that's all we need.

Lecture 004 - Creating an OAuth resource service

Enable resource server
  • So, now that we've configured the authorization service, let's go ahead and make our same service become a resource service as well so that we can start consuming our service APIs using OAuth security.
  • Let's open up the GuestServicesApplication class.
  • Now, to this class we're gonna add a very simple annotation called EnableResourceServer. And that is it. That's all it takes to make this resource server OAuth enabled.
Test - get the base64 value
  • Use this website to convert text to base64 format, which will be used in HTTPie
Test - using HTTPie
  • So, I've made a post to the API and I've gotten an access token.
  • You'll see I'm also getting all of the scopes with that, and that's very important because that's what we're actually gonna use to secure our application.
Test - check token
  • And now you'll see when I make that request, I get the authorities as well as the scopes of the client ID that I just passed that token for.
  • So, both of these APIs together give you the whole picture of what you're actually authenticating against, therefore giving you all the information that you will need to make decisions in your services as to whether allow or block these calls.
Test - convert to base64
Test - with api_audit client
  • And you'll see now we have a different bearer token, and we had a different set of scopes, which is exactly what we would expect based on the way that we configured our application.
  • So, now that we've got our web services protected, we need to move into the client because we can no longer make our web service calls now.

Lecture 005 - Client-side implementations of OAuth 2

Client side implementation
  • So now that we've protected our services with OAuth, we now need to go implement our client to actually log in through OAuth to consume the services.
  • Let log in with user fpmoles, and get an internal service error
  • Now the reason I'm getting the internal server error as opposed to a 401 is because I've actually not handled the error out of my client when we actually implemented that code.
  • So the internal server error is kinda hiding the fact that underneath, OAuth is saying nope, you're not authorized.
Adding dependency in gateway
  • Spring-security-oauth2
Modify Guests service in gateway
  • Inject restTemplate
  • Ide signals error that there is no bean restTemplate, let define this bean
Define restTemplate bean
  • Open up our guest application, and we'll fix that.
  • We are going to make this an OAuth client by adding the EnableOAuth2Client annotation.
  • Now in addition to that, I'm gonna do a private static final String for AUTH_TOKEN _URL, and that is going to be /oauth/token.
  • So now let's add in a private String called serviceURL, and we're gonna inject this the same way that we did before in the service class.
  • We're gonna use an @Value annotation, and we are going to do landon.guest.service.url.
  • Now we're gonna do an @Bean annotation, and we're gonna make a public OAuth2RestTemplate, and we will simply call this restTemplate.
  • Now, this OAuth2RestTemplate extends restTemplate, so we're gonna get all the same functionality, but we're also gonna get the ability to tie into an OAuth, and it's gonna manage all of our tokens.
  • So the first thing we wanna do, is we wanna set up a client credentials resource.
  • The reason we're using this one is because we're using the client credentials flow.
  • There's a similar path for all of the various flows that you might use.
  • So go ahead and set that equal to a new instance of that object, and we're gonna set a few values.
  • So the first thing we need to do is, we need to tell it where is it gonna get its access token, and the access token URI is going to come from our serviceURL, plus, our AUTH_TOKEN_URL.
  • We need to set our client, and the client ID that we are going to be using for this, as you might imagine, is guest_app, because that is the purpose of that client.
  • We're also gonna go ahead and set our client secret, and it was that uber secret value of secret.
  • And now we need to confirm that the grant type is indeed client_credentials.
  • Now we're gonna tell it which scopes we wanna get back, and in this case we're going to get our scopes as an array list.
  • So we need a little lambda functionality here, so we're gonna call add, and the first one that we're gonna pass it is READ_ALL_GUESTS.
  • And then we're gonna call add again, and we're gonna use WRITE_GUEST.
  • And then one more time we will call add, and this time it's going to be UPDATE_GUEST.
  • Now you don't always have to type in all the scopes, however, it is good practice to type the scopes in order to make sure that you're only getting those things that you need with that token, because if that token gets compromised, we don't want it abused.
  • So there's just a couple more things here that we need to do.
  • We need to set our authentication scheme, and we're gonna set the authentication scheme to be form based.
  • Now we're gonna create an AccessTokenRequest called request = new, and we're gonna use the DefaultAccessTokenRequest, and finally we can return a new OAuth2RestTemplate, and that rest template is gonna take our resource, and then it's gonna take a new DefaultOAuth2ClientContext, that takes our request value.
Test
  • Go to view guests.
  • Type in fpmoles, password, sign in, and low and behold, we have all of our guests as we would expect.
  • So as you can see, consuming OAuth is actually relatively easy from the client side.
  • Now you can take this much farther than this example, this is very simplistic, but it gets you a feel for what you have to do to implement OAuth in a Spring application.

Lecture 006 - OAuth 2 with third parties

Why
  • Sometimes, you just need authentication, and you do not want to manage username and password in your system, which is perfectly valid when there are very well-designed and well-tested systems that provide all of that behavior, and provide you a hook in which to use their service in your site.
  • On the same lines, sometimes you don't wanna manage any of that.
  • Even if you can, you just don't wanna manage it.
  • Also, many of those times we want more than just authentication from those sites.
  • We want the rich integration that comes with those social platforms.
  • And speaking of social, those social aspects tend to bleed into our site, such as likes, and shares, or code commits, things like that that really add value based on who is consuming our site.
So many ways
  • OAuth 2 is all over this place in Spring, especially third-party login.
  • There's Spring Social, and there's OAuth 2, and then there's the new modern Spring Security OAuth.
  • And while this is a problem, Spring Security and the Spring team in general is working on unifying all of this under one common umbrella, and that is the Spring Security umbrella.
  • Now this video is gonna be based on the details of using Spring Security OAuth 2 client, which should be considered the model to follow going forward.
Basic flow
  • You go to the third party, and you register your application with them, you authorize your application to be used in that third-party app.
  • Now a lot of times to do that, you're gonna need a developer account, and usually that's a very straightforward and free process in order to do that.
  • Now once you've authorized your application, one of the things that they're gonna ask you to do is set up a redirect URL, and what is essentially gonna gonna happen is, is you're gonna ask them to do authorization, they are then gonna redirect back to your site at the redirect URL that you provide.
  • Then you're gonna need to go into your application and configure it to consume everything that is necessary from the third party.
  • Most of those revolve around client ID and client secret, although some of the APIs do have additional values you need to add.
  • And finally, once that's done, you simply run your application, and you will be integrated in that third-party OAuth flow.
Example config
  • Essentially, it comes down to the point where it says registration, which is the fifth line.
  • At that point is where it diverges, so there's a GitHub flow, and a Facebook flow, and a Google flow, and an Octa flow, and you pick which one of those flows that you want.
  • But but both of them rely on having a client ID and secret at the bare minimum, and that's what your application is gonna use in order to register with the third party, and to have that back and forth communication.

Chapter 05 - WebFlux Security

Lecture 001 - Introduction to WebFlux security

WebFlux
  • Any modern development in Spring these days requires a reference to WebFlux.
  • WebFlux is the way to do reactive Spring since Spring Boot 2.0.
  • With Spring security there's full support for WebFlux.
Enable web flux security
  • The basic annotation that you're gonna use is the @EnableWebFluxSecurity.
  • This gives you the control for basic configuration mapping, and the basic config puts everything as secured.
  • You also have a handle to a SecurityWebFilterChain as you might remember everything in Spring security is based on filters and Reactive Spring is no different.
  • This filter chain provides much more fine-grained control much the way we've seen before in the authentication managers.
  • You also have a MapReactiveUserDetailsService that allows you to handle the traditional UserDetailsService much the same way we have before.
  • As we get into our example, we're gonna go back to that InMemoryUserDetailService.
Principal
  • Often times in Spring we want to have a handle to the principal, and in traditional Spring security that was never a problem.
  • With WebFlux it still isn't a problem.
  • You still have a model based on the principal itself, but instead of injecting straight principal into your method, you now inject a mono with a principal template into your method where you want to handle it.
  • You still get all the same core functionality, but now it's just wrapped with mono.

Lecture 002 - WebFlux basic security

The problem
  • HTTPie application to call localhost:8080/hello and you'll see I get a nice response back.
  • And I'm gonna do the same thing at /roll.
  • And the response I get is the roll of two six-sided dice.
  • So that's fine and dandy, but we really don't want somebody just rolling our dice without permission.
  • So let's go ahead and add some security to this scenario.
Adding dependency
  • Spring-boot-stater-security
Configure
  • The first thing we're gonna do in our application class is @EnableWebFluxSecurity.
  • And this is the reactive security model that we're gonna base everything off of.
  • Now we need to go create a couple beans.
  • The first bean that we are going to create is a MapReactiveUserDetailsService.
  • And we'll simply call it userDetailsService.
  • Now in order to do this I'm gonna add a couple users.
  • Return a new MapReactiveUserDetailsService, passing it that list of userDetails.
Configure
  • Now we're gonna do on any other exchange what's in the system, we wanna make sure that we have a role of "ADMIN".
  • And we're simply going to use basic auth.
  • And then we will return http.build.
  • Excellent, so let's go ahead and restart our application, let the compilation continue and the restart happen.
Test with anonymous user
  • And indeed, we still get a response which is exactly what we expect because we said that any request to the hello should still happen.
  • But let's go to roll.
  • And you'll see now we get a 401 because we haven't authenticated.
  • Now, previously I went to a website to get the basic auth.
Test with admin user
  • And we get a dice roll because this user is an admin user.
Test with none admin user
  • Let's do a dice roll again, but this time we'll do jdoe and fubar.
  • And we get a 403 which is what we would expect because now we've been blocked.
  • So what we've seen here is that we've got WebFlux turned on, we've got security on it, we've got one API that's open and we've got another API that requires you to login or else you get a 401 and it requires you to be an admin user or else you'll get a 403, which is exactly what we would expect in our web service.

Chapter 06 - Conclusion

Lecture 001 - Next steps

Get involved
  • There's plenty more information out there, so get reading and stay involved.