Allow support of Grant Type "Client Credentials"

Problem this snippet solves:

The OAuth 2.0 framework specifies several grant types for different use cases (for more information about grant type: https://oauth.net/2/grant-types/).

The "Client Credentials" grant type is used by clients to obtain an access token outside of the context of a user. This is typically used by clients to access resources about themselves rather than to access a user's resources.

Typically the service will allow either additional request parameters client_id and client_secret, or accept the client ID and secret in the HTTP Basic auth header. The POST request that the application makes looks like the example below:

POST /f5-oauth2/v1/token HTTP/1.1
Host: as.mydomain.com

grant_type=client_credentials
client_id=ds87as7f5dasdsa890dfd0fdsd7685dsfd98d9f8s98fs
client_secret=vfv998dsa7697fd900d96fd876d765a54a7s5dsfd798d

however as you can noticed F5 does not provide this grant_types (Client Credentials) for client application.

How to use this snippet:

s explaind above, F5 does not provide "Client Credentials" but provide "Resource Owner Password Credentials".

Resource Owner Password Credentials is used by first-party clients to exchange a user's credentials for an access token. the user's username and password are exchanged directly for an access token. the application presents a traditional username and password login form to collect the user’s credentials and makes a POST request to the server to exchange the password for an access token. The POST request that the application makes looks like the example below:

POST /f5-oauth2/v1/token HTTP/1.1
Host: as.mydomain.com

grant_type=password
username=user
password=mypwd
client_id=ds87as7f5dasdsa890dfd0fdsd7685dsfd98d9f8s98fs
client_secret=vfv998dsa7697fd900d96fd876d765a54a7s5dsfd798d

So as you can noticed, "Client Credentials" and "Resource Owner Password Credentials" Request are substantially similar. the only difference is that we add the parameter username and password in addition. And grant_type name is different (password / client_credentials).

So If Client imposes "Client Credentials" grant type, follow this procedure to achieve your need.

in your client application settings checked "Resource Owner Password Credentials"

Access ›› Federation : OAuth Authorization Server : Client Application

As you can notided below in the irule, we retwrite only request done by the client:

Code :

when HTTP_REQUEST {

set grant_type null

if { ( [string tolower [HTTP::uri]] equals "/f5-oauth2/v1/token" ) and ( [HTTP::method] equals "POST" ) } {
set grant_type "client_credentials"
    HTTP::collect [HTTP::header Content-Length]
}

}

when HTTP_REQUEST_DATA {

if {$grant_type contains "client_credentials" } {
set payload [HTTP::payload]

if { [HTTP::payload] contains "grant_type=client_credentials" } {
# log local0. "Old Payload: [HTTP::payload]"
HTTP::payload replace 0 0 [string map {"grant_type=client_credentials" "grant_type=password&username=test&password=jhgkhlkjhkjhkj"} $payload]
# log local0. "New Payload: [HTTP::payload]"
HTTP::release 
}
}
}

# For information (both request):
#grant_type=password&username=test&password=jhgkhlkjhkjhkj&scope=username&client_id=ds87as7f5dasdsa890dfd0fdsd7685dsfd98d9f8s98fs&client_secret=vfv998dsa7697fd900d96fd876d765a54a7s5dsfd798d
#grant_type=client_credentials&scope=username&client_id=ds87as7f5dasdsa890dfd0fdsd7685dsfd98d9f8s98fs&client_secret=vfv998dsa7697fd900d96fd876d765a54a7s5dsfd798d

Tested this on version:

13.0
Updated Jun 06, 2023
Version 2.0

Was this article helpful?

2 Comments

  • I think there is a mistake with this part of the irule:

     

    HTTP::payload replace 0 0 [string map {"grant_type=client_credentials" "grant_type=password&username=test&password=jhgkhlkjhkjhkj"} $payload]

     

    It should actually be something like this:

     

    HTTP::payload replace 0 [HTTP::payload length] [string map {"grant_type=client_credentials" "grant_type=password&username=test&password=jhgkhlkjhkjhkj"} $payload]

     

    This is important because if grant_type isn't the first argument in the call, it simply won't work.

     

  • Instead of adding these tweaks and twists on our iRules, I'm just wondering why BigIP will not add support of the Client Credentials Grant Type since it is pretty useful in term of securing external APIs