28-Jun-2022 05:00 - edited 30-Jun-2022 09:39
Implementing basic OAuth with F5 BIG-IP APM
BIG-IP APM can work in various OAuth roles including OAuth client, OAuth Authorization Server, and OAuth Resource Server. In this demo, we will configure one BIG-IP APM as an OAuth Authorization Server and the other BIG-IP APM as an OAuth Resource Server. We will cover a basic implementation using Postman and BIG-IP APM in this demo rather than a detailed access control process. I will cover the more detailed access control implementation using BIG-IP APM and NGINX Plus in the upcoming articles. The purpose of this demo is to show a basic implementation and how Postman S/W(OAuth client) is able to obtain a valid OAuth access token from the BIG-IP APM(OAuth Authorization Server).
An OAuth ‘scope’ is a set of access privileges that are used at an OAuth Resource Server. Scopes are defined with strings and the values can be combined as a set using a space-separated list in the OAuth requests and responses. As a result, the scope value should not include the space character as a value. There is no defined structure of scope in the standard RFC of an OAuth. For example, Google uses URI format as their OAuth scope values like ‘https://www.googleapis.com/auth/cloud-platform.read-only’ and Dropbox uses a period-separated format like ‘account_info.read’. (Note. While Google uses URI format as their scope values, it is not reachable URIs.) While the scope values can be different in each OAuth implementation of an enterprise, its purpose is the same, ‘Enforcing the right access control to each API endpoints based on the scope value’. Because of this reason, OAuth scope is a critical and essential part of an entire OAuth framework.
Designing OAuth scope values is essentially a required step before an organization actually builds its own OAuth systems. OAuth scopes are the most important mechanism in an overall OAuth flow because an OAuth resource server actually can limit the access of a client based on issued scope values. In an OAuth flow, an organization can enforce its access control policy based on OAuth scope values. OAuth scope values should be synched between OAuth AS(Authorization Server) and OAuth RS(Resource Server). That means OAuth AS should assign the correct scope values to the client who has the correct privilege for protected resources. The OAuth RS, on the other hand, should be able to understand the scope structure and can enforce the access control actions based on the policy. OAuth configuration is just an operational step, but designing OAuth token policies and scope values are more complex and critical steps for organizations when they build their own OAuth-based access control. I will explain more details about designing parts in my next article. For now, we use two OAuth scope values here – ‘read’ and ‘write’.
1) Create scope values in the OAuth AS(BIG-IP APM#2)
BIG-IP UI >> Access >> Federation >> OAuth Authorization Server >> Scope >> Create
2) Register the OAuth client application in the OAuth AS(BIG-IP APM#2)
In the normal OAuth configuration steps, the client application should be registered in the OAuth AS manually. Although there is a separate process for supporting the dynamic registration of OAuth clients, it is not covered in this article. You can create an OAuth client instance in the OAuth AS UI with the below steps.
BIG-IP UI >> Access >> Federation >> OAuth Authorization Server >> Client Application >> Create
Since we’re going to use the ‘Authorization Code Grant’ type to obtain the access_token in the POSTMAN software, we need to select the ‘Authorization Code / Hybrid’ menu here. The ‘Redirect URI’ indicates the address of the client application, and the OAuth Authorization Server uses this ‘Redirect URL’ to send the generated one-time ‘authorization code’ to the OAuth client application. In our example, we need to configure the ‘Redirected URI’ value to the default value of the POSTMAN software. Finally, we attach the configured scope values to this client software. In this case, we want to allow POSTMAN to perform both ‘read’ and ‘write’ actions for the API endpoints. Once you finish all required configurations here, click the ‘Finished’ button. If you click the ‘created client’ application in the menu, you can find the ‘Client ID’ and ‘Secret’ values. The values will be used by the OAuth client(POSTMAN) to obtain the ‘access token’, so the values must be stored separately.
3) Register the OAuth Resource Server in the OAuth AS(BIG-IP APM#2)
The next step is to create and register an ‘OAuth Resource Server’. The role of an ‘OAuth Resource Server’ is to validate the ‘access token’ that is attached to the ‘API request’ from the OAuth client and to enforce required access policies based on the scope values inside of the token.
BIG-IP UI >> Access >> Federation >> OAuth Authorization Server >> Resource Server >> Create
The ‘Secret’ value is not shown when you create ‘Resource Server’ the first time. It will be displayed once you finish your creation process.
4) Create the OAuth Profile in the OAuth AS(BIG-IP APM#2)
Now, we need an ‘OAuth Profile’ to combine previously configured ‘OAuth Client’ and ‘OAuth Resource Server’ in the same policy.
BIG-IP UI >> Access >> Federation >> OAuth Authorization Server >> OAuth Profile >> Create
You must select the client application and resource server that you created in the previous steps. There are 4 different URL values in the profile, ‘Authorization Endpoint’, ‘Token Issuance Endpoint’, ‘Token Revocation Endpoint’, and ‘Token Introspection Endpoint’. These values are accessed by the OAuth client and the OAuth resource server, so we need to store these URLs at the moment.
5) Create the Local User Database in the OAuth AS(BIG-IP APM#2)
The next step is to create a ‘Local User Database’ in the BIG-IP APM(OAuth AS). We're going to use the ‘Local DB’ of APM as an IdP in this demo for simplicity. However, you can use other IdP in your own environment such as MS Active Directory.
BIG-IP UI >> Access >> Authentication >> Local User DB >> Instances >> Create New Instance
BIG-IP UI >> Access >> Authentication >> Local User DB >> Users >> Create New User
6) Create an access profile in the OAuth AS(BIG-IP APM#2)
Now, the final step in the OAuth AS is to create the access profile.
BIG-IP UI >> Access >> Profiles / Policies >> Access Profiles (Per-Session Policies) >> Create
You have to attach the ‘OAuth Profile’ that you created in the previous step.
After you create the access profile, you need to edit the ‘VPE(Visual Policy Editor)’.
BIG-IP UI >> Access >> Profiles / Policies >> Access Profiles (Per-Session Policies)
a. Click the ‘Edit’ of the access profile that we created in the previous step.
b. Click the (+) icon next to ‘Start’ and go to ‘Logon’. Select ‘Logon Page’ option and click the ‘Add Item’ button. Then configure like the below and click the ‘Save’ once the configuration is done.
c. Click the (+) icon next to the logon page we created before. Go to ‘Authentication’ tab and select ‘LocalDB Auth’ option and click the ‘Add Item’ button. Then configure like the below and click the ‘Save’ once the configuration is done.
d. Click the (+) icon next to the ‘LocalDB Auth’ item we created before. Go to ‘Authentication’ tab and select ‘OAuth Authorization’ option and click the ‘Add Item’ button. Then configure like the below and click the ‘Save’ once the configuration is done.
e. Click the ‘Successful’ branch of the ‘OAuth Authorization’ and change the ‘Deny’ value to the ‘Allow’. Then your VPE of the access profile should be like the below.
7) Create a standard virtual server in the OAuth AS(BIG-IP APM#2)
The final step is to create the virtual server and attach the access profile to the virtual server. This virtual server will be used as the address of the ‘OAuth AS’.
8)Configure an OAuth Provider in the OAuth RS(BIG-IP APM#1)
BIG-IP UI >> Access >> Federation >> OAuth Client/Resource Server >> Provider >> Create
9) Configure an OAuth Server in the OAuth RS(BIG-IP APM#1)
BIG-IP UI >> Access >> Federation >> OAuth Client/Resource Server >> OAuth Server >> Create
a. You need to paste the ‘Resource Server ID’ and ‘Secret’ values that you obtained from OAuth AS configuration.
10) Create a per-session access profile in the OAuth RS(BIG-IP APM#1)
BIG-IP UI >> Access >> Profiles / Policies >> Access Profiles (Per-Session Policies) >> Create
a. The profile of this ‘Per-Session Policy’ should be set to ‘OAuth-Resource Server’.
b. Click the ‘Edit’ of the access profile that we created the above.
c. Click the ending ‘Deny’ and change it to ‘Allow’.
11) Create a per-request policy in the OAuth RS(BIG-IP APM#1)
BIG-IP UI >> Access >> Profiles / Policies >> Per-Request Policies >> Create
The ultimate goal of the OAuth resource server is to enforce the required access policies based on the scope values of the ‘access token’. Following this, OAuth RS needs to validate all the requests from the OAuth Client and enforce the access control. Because of this, we need to include PRP(Per-Request Policy) in the BIG-IP APM.
a. Click the ‘Edit’ of the access profile that we created the above.
b. Click the ‘Add New Subroutine’ and type the unique name of the subroutine.
c. Click the ‘Edit Terminals’ and change the name and the order like the below.
d. Click the (+) icon next to the ‘In’ item in the newly created subroutine and select the ‘OAuth Scope’ and click the ‘Add Item’.
e. ‘Token Validation Mode’ menu indicates the type of the token. If it is set to the ‘External’, it indicates the ‘Opaque Token’ while the ‘Internal’ means the ‘JWT’.
f. Click the (+) icon next to the ‘Start’ item in the main PRP and select the newly created subroutine policy under the ‘Subroutines’ tab.
g. Then, the final PRP should be similar to the below.
12) Create a virtual server in the OAuth RS(BIG-IP APM#1)
The final step is to create the virtual server and attach the access profile and the per-request policy to the virtual server. The virtual server needs to connect your API endpoints through the Pool setting.
Verifying the result
We’re going to test the API request without the OAuth token, and will see our OAuth resource server correctly block this unauthorized request.
In the POSTMAN configuration, go to the ‘Authorization’ tab and select the ‘No Auth’ as an authorization type. Type your API endpoint URI and select the ‘GET’ as an HTTP method. (This URI should indicate the virtual server address of the OAuth resource server, and in our case, it is the ’10.1.10.50’ from APM#1.)
Since the API request doesn’t contain the correct OAuth token in the authorization header, OAuth Resource Server(BIG-IP APM#1) blocks the request and returns the ‘400 Bad request’ error message like the below.
We’re going to obtain the valid OAuth token from the OAuth AS(BIG-IP APM#2) this time and try again the API call. First, select the ‘OAuth 2.0’ as an authorization type in the POSTMAN setting, and then you need to type the correct OAuth values in the right panel. All these values can be found in the configuration of the OAuth AS. Regarding the scope values, you can type one of two values from ‘read’ and ‘write’ scopes, but you also can type both with space-separated. Once you finish the configuration of the OAuth values, click the ‘Get New Access Token’ button at the bottom.
Type the username and password that you configured in the OAuth AS with Local DB.
Click the ‘Authorize’ button.
Click the ‘Use Token’ button.
Try again the API request, then you will see the successful API request call.
We have successfully completed the configuration steps of OAuth using two BIG-IP APM devices, one for the OAuth Authorization Server and the other for the OAuth Resource Server. However, this demo only covered a very basic implementation. In other words, this demo didn’t cover how to apply the required access control policy to the OAuth Resource Server and how the admin can revoke the OAuth token effectively. In the next article, I’ll show you how users can configure the access control policies in the BIG-IP APM when it works as an OAuth Resource Server, and you will learn how an admin can revoke the access token in the OAuth Authorization Server.
Do you know if the F5 APM has support for RFC 8705 ?
-> RFC8705 = OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens
If yes how can this be configured?
Thank you for this great article.