Configuring Avi Vantage for JSON Web Tokens (JWT) Validation

Overview

Starting with Avi Vantage release 20.1.3, Avi Vantage supports JWT Validation as the authorization method for secure communication through Avi Vantage.

Avi Vantage supports the following JWT validation methods:

  • ​Manual upload of the JWKS keys
  • JWT Validation using JWKS keys
  • Claim-based validation using authorization rules under SSO Policy
  • Revocation using the authorization policies

The article explains how to configure JWT validation through Avi Vantage.

JWT Validation Workflow

The below diagram explains the workflow used in the JWT validation.

workflow-9

The followings are the details of communication between a client, an authorization server, and Avi Vantage during the JWT validation.

  1. The client sends an unauthenticated request to the authorization server.
  2. The authorization server performs the authentication and issues a JSON web-based tokens.
  3. The client requests to access the protected resource along with the JWT.
  4. Avi Vantage validates the JWT and provides access to the requested resource.

Configuring JWT Validation

Using the UI

The following are the steps to configure JWT validation using the UI:

  1. Create a JWT Server Profile

    1. Navigate to  Templates  >  Security >  JWT Server Profile.

    2. Click on Create to create a JWT server profile.

    jwt-server-profile

    • Name — Specify the name of the JWT profile.

    • Issuer — Specify the unique name of the token issuer. This is applicable only for CLIENT_AUTH profile type.

    • Upload or Paste JWT File — You can upload the JWT file by clicking on IMPORT FILE option.

    After specifying all the details, click on Save button.

  2. Associate the JWT server profile to the Authentication Profile

    1. Navigate to  Templates  >  Auth Profile >  JWT Server Profile.

    2. Click on edit button to edit a JWT server profile.

    jwt-auth-profile

    • Name — Specify the name of the JWT profile.

    • JWT Server Profile — Select the JWT server profile from the drop-down list.

  3. Create the SSO policy

    1. Navigate to  Templates  >  Security >  SSO Policy.

    2. Click on edit button to edit a SSO Policy.

    sso-policy

    • Name — Specify the name of the SSO policy.

    • Type — Select the SSO policy type from the drop-down list.

    • Default Auth Profile — Select the default auth profile from the drop-down list.

  4. Associate the SSO Policy and the JWT virtual service configuration to the virtual service

    • Navigate to  Applications  >  Virtual Services.

    • Click on edit button to edit the virtual service.
      auth-header

    • In Access tab, select JWT option.

    • SSO Policy — Specify the SSO policy.

    • Audience — Specify the SSO audience.

    • Token Location — Select the token location as either Authorization Header or URL Query.

Using the CLI

Follow the steps mentioned in this section for the configuration of JWT validation through Avi Vantage.
Refer to the frequently used terms section of JWT validation to know the various terms used in the configuration.

  1. Creating a JWT server profile — Login to Avi CLI and use the configure jwtserverprofile <profile name> command to provide values for various attributes.

    
    [admin:controller]: > configure jwtserverprofile jwtserver1
    [admin:controller]: jwtserverprofile> issuer https://accounts.google.com
    [admin:controller]: jwtserverprofile> jwks_keys "{"keys": [{"use": "sig", "e": "AQAB", "kty": "RSA", "alg": "RS256", "n":"sUAjG7PjTm7FkhfTUZlpiMDZb9t6Ge6rjtx0RZh5vrk8ONmEqgzmi_b6WZ-rkIfF54MZfyWiISPp9QgJBoKq9lDmFGz3zlMxu6M18TJmMj39HzRzvwDKg2ll1b-447cNXgw5wPiVl0O4Ej9qccOwl7dHzHAiJ88CZ1oOSplkJOqF71M2l_0pGH25GNZA5quW9FaATRE_Unm3C_Jb_76QjslOohF7x-cOl7mcI-TNJs29_rqJeC3pJaPUr_qRl5cc-1ALQP_rVW9m47IY0GnGbUZ6VsYefAPnvswXx21-S4nOU-Nt4EhbcMf6cZ5X6q4qWFtG6wil2hTB4lfHA_olMw", "kid":"example"}]}"
    [admin:controller]: jwtserverprofile>
    [admin:controller]: jwtserverprofile> save
    +------------+--------------------------------------------------------------------------------------------------------+
    | Field             | Value                                                                                                                                                                            |
    +------------+--------------------------------------------------------------------------------------------------------+
    | uuid              | jwtserverprofile-e1c8f0c2-b38c-41f4-bf1e-0f55e282797e                                                                               |
    | name            | jwtserver1                                                                                                                                                                   |
    | jwks_keys    | {"keys": [{"use": "sig", "e": "AQAB", "kty": "RSA", "alg": "RS256", "n":"sUAjG7P                                               |
    |                      | jTm7FkhfTUZlpiMDZb9t6Ge6rjtx0RZh5vrk8ONmEqgzmi_b6WZ-rkIfF54MZfyWiISPp9QgJBoKq9lD          |
    |                      | mFGz3zlMxu6M18TJmMj39HzRzvwDKg2ll1b-447cNXgw5wPiVl0O4Ej9qccOwl7dHzHAiJ88CZ1oOSpl     |
    |                      | kJOqF71M2l_0pGH25GNZA5quW9FaATRE_Unm3C_Jb_76QjslOohF7x-cOl7mcI-TNJs29_rqJeC3pJaP       |
    |                      | Ur_qRl5cc-1ALQP_rVW9m47IY0GnGbUZ6VsYefAPnvswXx21-S4nOU-Nt4EhbcMf6cZ5X6q4qWFtG6wi    |
    |                      | l2hTB4lfHA_olMw", "kid":"example"}]}                                                                                                                    |
    | issuer           | https://accounts.google.com                                                                                                                                   |
    | tenant_ref    | admin                                                                                                                                                                          |
    +------------+--------------------------------------------------------------------------------------------------------+
    [admin:controller]: >
    
  2. Associate the JWT server profile created in the previous step to the authentication profile:

    
    [admin:controller]: > configure authprofile authprofile1
    [admin:controller]: authprofile> jwt_profile_ref jwtserver1
    [admin:controller]: authprofile> type auth_profile_jwt
    [admin:controller]: authprofile> save
    +-----------------+--------------------------------------------------+
    | Field           | Value                                            |
    +-----------------+--------------------------------------------------+
    | uuid            | authprofile-e1b763d6-bbd0-4a70-9a9b-95ab60e72e11 |
    | name            | authprofile1                                     |
    | type            | AUTH_PROFILE_JWT                                 |
    | jwt_profile_ref | jwtserver1                                       |
    | tenant_ref      | admin                                            |
    +-----------------+--------------------------------------------------+
    [admin:controller]: >
    
  3. Create an SSO policy using the configure ssopolicy <sso policy name> command. Associate this SSO policy with the authentication policy created in the previous step and set the type for the authentication policy as sso_type_jwt.
    
    [admin:controller]: > configure ssopolicy ssopolicy1
    [admin:controller]: ssopolicy> authentication_policy default_auth_profile_ref authprofile1
    [admin:controller]: ssopolicy:authentication_policy> save
    [admin:controller]: ssopolicy> type sso_type_jwt
    [admin:controller]: ssopolicy>save
    
    +----------------------------+---------------------------------+
    | Field                      |                   Value         |
    +----------------------------+---------------------------------+
    | name                       |            ssopolicy1           |
    | authentication_policy      |                                 |
    |   default_auth_profile_ref | authprofile1                    |
    | type                       | SSO_TYPE_JWT                    |
    +----------------------------+---------------------------------+
    
  4. Associate the SSO Policy and the JWT virtual service configuration to the virtual service.
    Set the value of jwt_location as jwt_location_authorization_header, if the JWT is sent as Bearer Token in the authorization header.

    
    [admin:controller]: > configure virtualservice virtualservice1
    [admin:controller]: virtualservice> 
    [admin:controller]: virtualservice> sso_policy
    sso_policy                           (submode)
    sso_policy_ref                       The SSO Policy attached to the virtualservice.
    [admin:controller]: virtualservice> sso_policy_ref
    
    WORD     The SSO Policy attached to the virtualservice.
    [admin:controller]: virtualservice> sso_policy_ref  ssopolicy1
    [admin:controller]: virtualservice> jwt_config
    audience       Uniquely identifies a resource server. This is used to validate against the aud claim.
    jwt_location   Defines where to look for JWT in the request.
    jwt_name       Name by which the JWT can be identified if the token is sent as a query param in the request url.
    [admin:controller]: virtualservice> jwt_config audience
    
    WORD     Uniquely identifies a resource server. This is used to validate against the aud claim.
    [admin:controller]: virtualservice> jwt_config audience dfsrX789jsbfheDHUW2838nfewsjdf
    
    [admin:controller]: virtualservice:jwt_config> jwt_location jwt_location_
    jwt_location_authorization_header   JWT sent in the authorizarion header of the request as a bearer token.
    jwt_location_query_param            JWT sent in the request query params.
    [admin:controller]: virtualservice:jwt_config> jwt_location jwt_location_authorization_header
    [admin:controller]: virtualservice:jwt_config> save
    

Select jwt_location_query_params as the value for jwt_location, if the JWT is sent in the URL as a query parameter.


  [admin:controller]: > configure virtualservice virtualservice1

  [admin:controller]: virtualservice> 
  [admin:controller]: virtualservice> sso_policy
  sso_policy                           (submode)
  sso_policy_ref                       The SSO Policy attached to the virtualservice.
  [admin:controller]: virtualservice> sso_policy_ref

  WORD     The SSO Policy attached to the virtualservice.
  [admin:controller]: virtualservice> sso_policy_ref  ssopolicy1

  [admin:controller]: virtualservice> jwt_config
  audience       Uniquely identifies a resource server. This is used to validate against the aud claim.
  jwt_location   Defines where to look for JWT in the request.
  jwt_name       Name by which the JWT can be identified if the token is sent as a query param in the request url.
  [admin:controller]: virtualservice> jwt_config audience

  WORD     Uniquely identifies a resource server. This is used to validate against the aud claim.
  [admin:controller]: virtualservice> jwt_config audience dfsrX789jsbfheDHUW2838nfewsjdf

  [admin:controller]: virtualservice:jwt_config> jwt_location jwt_location_query_params
  [admin:controller]: virtualservice:jwt_config> jwt_location jwt_location_query_param jwt_name "jwt_token"
  [admin:controller]: virtualservice:jwt_config> save
  

Adding Authentication Policies

Use the authentication policy option under the configure ssopolicy <sso policy name> mode to add authentication policies to enable JWT authentication only for paths /login and /default.


[admin:controller]: > configure ssopolicy ssopolicy-3
[admin:controller]: ssopolicy>
[admin:controller]: ssopolicy> type sso_type_jwt
[admin:controller]: ssopolicy> authentication_policy
[admin:controller]: ssopolicy:authentication_policy> default_auth_profile_ref authprofile-1
[admin:controller]: ssopolicy:authentication_policy> authn_rules
New object being created
[admin:controller]: ssopolicy:authentication_policy:authn_rules> action type skip_authentication
[admin:controller]: ssopolicy:authentication_policy:authn_rules:action> save
[admin:controller]: ssopolicy:authentication_policy:authn_rules> index 1
[admin:controller]: ssopolicy:authentication_policy:authn_rules> name rule1
[admin:controller]: ssopolicy:authentication_policy:authn_rules> match
[admin:controller]: ssopolicy:authentication_policy:authn_rules:match> path
[admin:controller]: ssopolicy:authentication_policy:authn_rules:match:path> match_str "login"
[admin:controller]: ssopolicy:authentication_policy:authn_rules:match:path> match_str "default"
[admin:controller]: ssopolicy:authentication_policy:authn_rules:match:path> match_criteria does_not_equal
[admin:controller]: ssopolicy:authentication_policy:authn_rules:match:path> save
[admin:controller]: ssopolicy:authentication_policy:authn_rules:match> save
[admin:controller]: ssopolicy:authentication_policy:authn_rules> save
[admin:controller]: ssopolicy:authentication_policy> save
[admin:controller]: ssopolicy> save
+----------------------------+-------------------------------------+
| Field                      | Value                               |
+----------------------------+-------------------------------------+
| uuid                       | ssopolicy-6d831f8d-4ccf-43f9-af73-aa9aae8beae4                   |
| name                       | ssopolicy-3                                                                                          |
| authentication_policy      |                                                                                                      |
|   default_auth_profile_ref | authprofile-1                                                                                        |
|   authn_rules[1]           |                                                                                                      |
|     name                   | rule1                                                                                                |
|     index                  | 1                                                                                                    |
|     enable                 | True                                                                                                 |
|     match                  |                                                                                                      |
|       path                 |                                                                                                      |
|         match_criteria     | DOES_NOT_EQUAL                                                                                       |
|         match_case         | INSENSITIVE                                                                                          |
|         match_str[1]       | login                                                                                                |
|         match_str[2]       | default                                                                                              |
|     action                 |                                                                                                      |
|       type                 | SKIP_AUTHENTICATION                                                                                  |
| type                       | SSO_TYPE_JWT                                                                                         |
| tenant_ref                 | admin                                                                                                |
+----------------------------+-------------------------------------+

Adding Authorization Policies

Use the authorization policy option under the configure ssopolicy <sso policy name> mode to enable authorization with access token match.


[admin:controller]: > configure ssopolicy ssopolicy-3
[admin:controller]: ssopolicy> authorization_policy
[admin:controller]: ssopolicy:authorization_policy> authz_rules index 1 name rule1
[admin:controller]: ssopolicy:authorization_policy:authz_rules> action status_code http_response_status_code_403 type http_local_response
[admin:controller]: ssopolicy:authorization_policy:authz_rules:action> save
[admin:controller]: ssopolicy:authorization_policy:authz_rules> match
[admin:controller]: ssopolicy:authorization_policy:authz_rules:match> access_token
[admin:controller]: ssopolicy:authorization_policy:authz_rules:match:access_token> matches
[admin:controller]: ssopolicy:authorization_policy:authz_rules:match:access_token:matches> type jwt_claim_type_string
[admin:controller]: ssopolicy:authorization_policy:authz_rules:match:access_token:matches> string_match match_str "AT-dsjfndjfndsj1234-jnfdjk"
[admin:controller]: ssopolicy:authorization_policy:authz_rules:match:access_token:matches:string_match> match_criteria equals
[admin:controller]: ssopolicy:authorization_policy:authz_rules:match:access_token:matches:string_match> save
[admin:controller]: ssopolicy:authorization_policy:authz_rules:match:access_token:matches> save
[admin:controller]: ssopolicy:authorization_policy:authz_rules:match:access_token> save
[admin:controller]: ssopolicy:authorization_policy:authz_rules:match> save
[admin:controller]: ssopolicy:authorization_policy:authz_rules> save
[admin:controller]: ssopolicy:authorization_policy> save
[admin:controller]: ssopolicy> save
+----------------------------+-------------------------------------+
| Field                      | Value                               |
+----------------------------+-------------------------------------+
| uuid                       | ssopolicy-6d831f8d-4ccf-43f9-af73-aa9aae8beae4                   |
| name                       | ssopolicy-3                        |
| authentication_policy      |                                    |
|   default_auth_profile_ref | authprofile-1                      |
|   authn_rules[1]           |                                    |
|     name                   | rule1                              |
|     index                  | 1                                  |
|     enable                 | True                               |
|     match                  |                                    |
|       path                 |                                    |
|         match_criteria     | DOES_NOT_EQUAL                     |
|         match_case         | INSENSITIVE                        |
|         match_str[1]       | login                              |
|         match_str[2]       | default                            |
|     action                 |                                    |
|       type                 | SKIP_AUTHENTICATION                |
| authorization_policy       |                                    |
|   authz_rules[1]           |                                    |
|     match                  |                                    |
|       access_token         |                                    |
|         matches[1]         |                                    |
|           is_mandatory     | True                               |
|           validate         | True                               |
|           type             | JWT_CLAIM_TYPE_STRING              |
|           string_match     |                                    |
|             match_criteria | EQUALS                             |
|             match_str[1]   | AT-dsjfndjfndsj1234-jnfdjk         |
|     action                 |                                    |
|       type                 | HTTP_LOCAL_RESPONSE                |
|       status_code          | HTTP_RESPONSE_STATUS_CODE_403      |
| type                       | SSO_TYPE_JWT                       |
| tenant_ref                 | admin                              |
+----------------------------+------------------------------------+

Revocation of JWT

JWTs are designed to be portable, decoupled identities. Once authentication is performed against an authorization server and a JWT is recieved,the JWT token’s re-validation is not required. They can not be revoked at the level of the authorization server.
Avi Vantage uses the following methods to revoke a JWT:

  • Configure the access tokens (JWTs) to be short-lived. As the JWT gets expired, the client will be forced to re-authenticate or to use a refresh token to request for the new JWT.
  • Maintain a list of the revoked token in a string group with jti as the key, one for each authorization server.
  • Use SSO policy to configure authorization rules based on certain claims like jti, or sub, or iss, etc. JWT has a claim named jit which is used to uniquely identify a JSON Web Token. For instance, If it is known that a particular token with a specific jit is compromised, authorization rules can be added to revoke the token with a particular jit.

Logs and Troubleshooting

Virtual server logs available on Avi vantage can be used to troubleshooting JWT validation issues. Refer to the Significance section of the log to know the reason for the various response codes generated by Avi Vantage.

Authorization Header Missing
The following log exhibits that the response code 403 is returned by Avi Vantage as the authorization header is missing in the request.

header-missing

Wrong or Unknown Issuer
The following log shows a response code 4xx as the JWT issuer is not known or not supported by Avi Vantage.

wrong-issuer

Wrong Audience
The following log shows a response code 4xx as the JWT is not issued for the selected application.

wrong-audience

Login to the Avi CLI and use the show virtualservice <virtual service name> stats command to check the various statistics associated with JWT validation.

stats