Setting up Spring Authorization Server
Spring Authorization Server is a project under the umbrella of Spring Framework that provides the components you need to create an Authorization Server. In this recipe, you will deploy a very simple Authorization Server that you will use for most of the recipes in this chapter. In the following recipes, you will continue to customize this server to achieve the goals of each exercise.
The configuration of this server is just for demo purposes. The Authorization Server plays a crucial role in managing and granting access to protected resources. If you plan to use it in production, I recommend following the instructions from the project at https://docs.spring.io/spring-authorization-server/reference/overview.html. In any case, the principles that we will explain in this book have been adjusted to the OAuth2 specification and well-known practices. For this reason, you will be able to apply what you learn here to any other Authorization Server.
Getting ready
To create the Spring Authorization Server, we will use Spring Initializr. You can open this tool in your browser using https://start.spring.io/ or use it in your code editor if it’s been integrated.
I assume that you have basic knowledge of OAuth2. However, I have added some links in the See also section that can be useful if you need to go through some concepts.
How to do it…
In this recipe, we will create a Spring Authorization Server using Spring Initializr and do a very basic configuration to create an application registration. Finally, we’ll test the application registration and analyze the results. Follow these steps:
- Open https://start.spring.io, as you did in the Creating a RESTful API recipe in Chapter 1, and use the same parameters, except change the following options:
- For Artifact, type
footballauth
- For Dependencies, select OAuth2 Authorization Server:
- For Artifact, type
Figure 2.1: Spring Initializr options for Spring Authorization Server
Click on the GENERATE button to download the project, then unzip the content to your working folder.
- Now, we need to configure the authorization server. For that, we will create an
application.yml
file in theresources
folder with the following content:server: port: 9000 spring: security: oauth2: authorizationserver: client: basic-client: registration: client-id: "football" client-secret: "{noop}SuperSecret" client-authentication-methods: - "client_secret_post" authorization-grant-types: - "client_credentials" scopes: - "football:read"
We just defined an application that can be authenticated using the client credential flow.
- Now, you can execute your Authorization Server. You can retrieve the configuration of our server by making a request to http://localhost:9000/.well-known/openid-configuration. As the path indicates, this is a well-known endpoint that all OAuth2-compliant vendors implement to expose the relevant configuration for client applications. Most of the client libraries can configure themselves just from this endpoint.
- To verify that it works, we can execute the authentication of our client. You can do this by executing the following
POST
request viacurl
:curl --location 'http://localhost:9000/oauth2/token' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=client_credentials' \ --data-urlencode 'client_id=football' \ --data-urlencode 'client_secret=SuperSecret' \ --data-urlencode 'scope=football:read'
You should see a response that looks similar to this:
{"access_token":"eyJraWQiOiIyMWZkYzEyMy05NTZmLTQ5YWQtODU2 Zi1mNjAxNzc4NzAwMmQiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJiYXNp Yy1jbGllbnQiLCJhdWQiOiJiYXNpYy1jbGllbnQiL CJuYmYiOjE2OTk1NzIwNjcsInNjb3BlIjpbInByb2ZpbGUiXSwiaXNzIj oiaHR0cDovL2xvY2FsaG9zdDo5MDAwIiwiZXhwIjoxNjk5NTcyMzY3LCJ pYXQiOjE2OTk1NzIwNjd9.TavlnbirP_4zGH8WaJHrcCrNs5ZCnStqqiX Kc6pakfvQPviosGdgo9vunq4ogRZWYNjXOS5GYw0XlubSj0UDznnxSLyx 7tR7cEZJSQVHc6kffuozycJ_xl5yzw6_Kv_pJ4fP00b7pbHWO8ciZKUhmW -Pvt5TV8sMFY-uNzgsCtiN5EYdplMUfZdwHMy8yon3bUah8Py7RoAw1bIE ioGUEiK5XLDaE4yGdo8RyyBv4wj3mw6Bs8dcLspLKWXG5spXlZes6XCaSu 0ZXtLE09AgA_Gmq0kwmhWXgnpGKuCkhkXASyJXboQD9TR0y3yTn_aNeiuV MPzX4DQ7IaCKzgmaYg","scope":"profile","token_type":"Bearer","expires_in":299}
- Now, you can copy the value of the
access_token
field, open https://jwt.ms in your browser, and paste the value there. In the Decoded Token tab, you can see the token in its decoded form, while if you click on the Claims tab, you can see an explanation of each field:
Figure 2.2: JWT token decoded in jwt.ms
- Congratulations – you’ve deployed a Spring Authorization Server and successfully configured an application for authorization.
How it works…
Spring OAuth2 Authorization Server contains all the components you need to create an authorization server. With the configuration provided in application.yml
, it created an application with a client-id
value of basic-client
. Let’s look at the parameters that were used for the application and see how they work:
- The
client-id
is the identifier of the application we create d. In this case, it isfootball
. - The
client-secret
is the secret of the application. By using the{noop}
prefix in the secret, we tell Spring Security that the password is not encrypted and can be used as-is. - The
client-authentication-methods
is used to specify how this application can authenticate. By using theclient_secret_post
method, we can ensure that the client ID and secret will be sent in aPOST
request. We could configure additional methods, such asclient_secret_basic
, in which case the client ID and secret will be sent as HTTP basic schema – that is, in the URL. - With the
authorization-grant-types
, we specify what grant flows are allowed for this application. By settingclient_credentials
, we are configuring an application that won’t have a user interface, such as a background server application. If you have an application that will interact with users, you could configure other options, such asauthorization_code
. - Finally, with the
scopes
, we are configuring the scopes that are allowed for this application. In this case, it is just thefootball:read
scope.
Spring OAuth2 Authorization Server keeps this configuration in memory. As you may have guessed, this is just for demonstration and development purposes. In a production environment, you will need to persist this data. Spring OAuth2 Authorization Server provides support for JPA repositories.
We used JWT MS (https://jwt.ms) to inspect the access token that was issued by our authorization server. This tool just decodes the token and describes the standard fields. There is another popular tool named JWT IO (https://jwt.io) that also allows you to validate the token, but it doesn’t explain each field.
There’s more…
You can follow the instructions from the Spring OAuth2 Authorization Server project to implement the core services with JPA: https://docs.spring.io/spring-authorization-server/docs/current/reference/html/guides/how-to-jpa.html.
You can use any relational database supported by Spring Data JPA, such as PostgreSQL, which we used in Chapter 5.
See also
In this chapter, we’ll manage many OAuth2 concepts, something that can be difficult to understand if you don’t have previous knowledge.
For instance, it is very important to understand the different token types:
access_token
: This contains all authorization information granted by the authorization server that the resource server will verify.id_token
: This token is used for session management, normally in client applications, to customize the user interface, for example.refresh_token
: This token is used to get newaccess_tokens
andid_tokens
when they are about to expire.refresh_token
is considered a secret as its lifetime is larger than the others and can be used not only to get fresher tokens for the already authorized applications but also for new ones. It is important to protect this token accordingly.
I strongly recommend getting familiar with the basic OAuth2 flows and their main purposes:
- Client credential flow:
This is the simplest flow and was used in this recipe. It is intended for applications without user interaction – for instance, for server applications communicating with other applications. They can be authenticated in different ways, such as with a secret, as seen in this recipe, a certificate, or other more sophisticated techniques.
- Authorization code grant flow:
This is intended to authenticate web and mobile applications. This is the two-leg authentication flow, where the user authenticates and allows the application to access the requested scopes. Then, the authentication endpoint issues a short-lived piece of code that should be redeemed in the token endpoint to get an access token. After, the application (not the user) should be authenticated. There are two variants of this flow, depending on how it authenticates:
- Using a client ID and a secret. This is intended for confidential applications, such as those that can keep secrets. This includes server applications.
- Using a client ID and a challenge, also known as Proof Key Challenge Exchange (PKCE). This is intended for public applications, such as those that cannot keep a secret, such as mobile applications, or applications that just live in the browser, such as single-page applications (SPAs).
- Refresh token flow:
As its name suggests, it is used to refresh access and ID tokens when they are about to expire. For that, it uses
refresh_token
.
There are more flows, but these are the basic ones that will be used in this chapter.