Using JWT Library Functions | MuleSoft Documentation
# Using JWT Library Functions
To view an example policy project that uses Flex Gateway Policy Development Kit (PDK)'s JWT library, see JWT Validation Policy Example.   
---  
JSON Web Token (JWT) is a URL-secure method of representing claims to be transferred between two parties. The JWT token contains claims encoded in a JSON object as either the payload of a JSON Web Signature (JWS) or as a JSON web encryption (JWE) structure in plain text, which enables the claims to be digitally signed and protected with a message authentication code (MAC). Because the token is signed, you can trust the information and its source.
PDK’s JWT library provides a set of tools to validate the JWT signatures and to extract and validate the claims of all incoming requests.
## Extract a JWT Token
PDK provides a `TokenProvider` struct that has the `bearer` function to extract JWT tokens that have the format `Bearer <token>` in the authorization header. The following code demonstrates how to use the `bearer` function:
```
// [...]
use pdk::jwt::*;
// [...]
async fn filter(
  state: RequestState,
) -> Flow<()> {
  let headers_state = state.into_headers_state().await;
  // Extract token
  let token = TokenProvider::bearer(headers_state.handler())?;
// [...]
```

If you are using a JWT token from a different source or with a different format, you can implement Rust logic to get any other part of the request. Use a DataWeave parameter to configure extraction to create a policy where you can dynamically change the JWT source.
## Validate a JWT Signature
The JWT library provides a helper for performing signature validation of the incoming requests authorization tokens. Depending on the algorithm used by the policy, initialize a `SignatureValidator` with the corresponding configuration:
```
pub fn new(algorithm: SigningAlgorithm, key_length: SigningKeyLength, key: String) -> Result<SignatureValidator, JWTError>
```

PDK supports the following signing algorithms and key lengths:
Signing Algorithm |  Signing Key Length  
---|---  
256, 384 and 512  
256, 384 and 512  
The `SigningAlgorithm` enum defines the available signing algorithms:
```
pub enum SigningAlgorithm {
  Rsa,
  Hmac,
  Es,
}
```

The `SigningKeyLength` enum defines the available signing key lengths:
```
pub enum SigningKeyLength {
  Len256,
  Len384,
  Len512,
}
```

A `SignatureValidator` instance implements the `SignatureValidation` trait. This `SignatureValidation` trait exposes a `validate` function that accepts tokens as `String` parameters and returns a `Result` that contains the parsed `JWTClaims` or a `JWTError` in the event of an error:
```
pub trait SignatureValidation {
  fn validate(&self, token: String) -> Result<JWTClaims, JWTError>;
}
```

The following code example shows how to initialize the `SignatureValidator` and validate an incoming token signed with a 256-byte HMAC algorithm:
```
use anyhow::Result;
use pdk::hl::*;
use pdk::jwt::*;
// [...]
async fn filter(
  state: RequestState,
  signature_validator: &SignatureValidator,
) -> Flow<()> {
  let headers_state = state.into_headers_state().await;
  // Extract token
  let token = TokenProvider::bearer(headers_state.handler())?;
  if token.is_err() {
    return Flow::Break(Response::new(401).with_body("Bearer not found"));
  }
  // Validating signature
  let claims = signature_validator.validate(token.unwrap());
  if claims.is_err() {
    return Flow::Break(Response::new(401).with_body("Invalid token"));
  }
  // [...]
}
#[entrypoint]
async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> {
  let config: Config = serde_json::from_slice(&configuration)?;
  let signature_validator = SignatureValidator::new(
    model::SigningAlgorithm::Hmac,
    model::SigningKeyLength::Len256,
    config.secret.clone(),
  )?;
  launcher
    .launch(on_request(|request| {
      filter(request, &signature_validator)
    }))
    .await?;
  Ok(())
}
```

Because, the `SignatureValidator` confirms that the policy configurations are correct during initialization, initializing the `SignatureValidator` in the `#[entrypoint]` function throws an early error when the policy is applied rather than when the API receives a request.
After initialization, the policy passes the `SignatureValidator` to the `on_request` wrapped function to perform `validate` method on incoming requests.
## Access Claims and Propagating to Headers
After the signature validation executes, the result contains the parsed JWT claims from the JWT token.
In case the signature is invalid or you choose not to validate the signature, PDK provides the `JWTClaimsParser` to parse claims. This structure provides a `parse` method that returns `Result<JWTClaims, JWTError>`.
```
// Being "token" a String that contains a JWT token
let parsed_claims = JWTClaimsParser::parse(token);
if claims.is_err() {
  return Flow::Break(Response::new(401).with_body("Invalid token"));
}
```

After you run the signature validation or the parsing method, use the following methods exposed by the `JWTClaims` struct to access the JWT claims:
```
pub fn audience(&self) -> Option<Result<Vec<String>, JWTError>>
pub fn not_before(&self) -> Option<DateTime<Utc>>
pub fn expiration(&self) -> Option<DateTime<Utc>>
pub fn issued_at(&self) -> Option<DateTime<Utc>>
pub fn issuer(&self) -> Option<String>
pub fn jti(&self) -> Option<String>
pub fn nonce(&self) -> Option<String>
pub fn subject(&self) -> Option<String>
pub fn has_claim(&self, name: &str) -> bool
pub fn get_claim<T>(&self, name: &str) -> Option<T> where T: ValueRetrieval,
pub fn has_header(&self, name: &str) -> bool
pub fn get_header(&self, name: &str) -> Option<String>
pub fn get_claims(&self) -> pdk_script::Value
pub fn get_headers(&self) -> pdk_script::Value
```

The provided methods are designed to return each one of the standard JWT claims.
The `get_claim` method can return any standard or custom claim. Because `get_claim` supports different target variable types, the user must specify the output type. `get_claim` supports `String`, `f64`, `Vec<String>`, `chrono::DateTime<chono::Utc>`, and `serde_json::Value` output types. Because the claim might not exist in the token, you must wrap the type with an `Option`, for example:
```
let some_custom_claim: Option<String> = claims.get_claim("username");
```

The following example shows how to parse a JWT token, get a custom claim, and propagate it to the request headers from a wrapped function:
```
async fn filter(
  state: RequestState,
) -> Flow<()> {
  let headers_state = state.into_headers_state().await;
  // Extract token
  let token = TokenProvider::bearer(headers_state.handler())?;
  if token.is_err() {
    return Flow::Break(Response::new(401).with_body("Bearer not found"));
  }
  // Being "token" a String that contains a JWT token
  let parsed_claims = JWTClaimsParser::parse(token.unwrap());
  if claims.is_err() {
    return Flow::Break(Response::new(401).with_body("Invalid token"));
  }
  let claims = claims.unwrap();
  let username: Option<String> = claims.get_claim("username");
  if let Some(custom_claim) = some_custom_claim {
    headers_state
      .handler()
      .set_header("username", custom_claim.as_str());
  }
  Flow::Continue(())
}
```

## Validate Claims
JWT tokens typically contain a set of standard and non-standard claims that you can validate. Use the methods from Access Claims and Propagating to Headers to retrieve the claims present in the JWT tokens’s header or payload. Once retrieved, validate the value of the claims.
The following code example validates that the JWT token:
  * Is not expired by validating the `exp` claim.
  * Has the correct audience value by validating the `aud` claim.
  * Has the correct custom `role` claim by using a custom validator configured as a DataWeave expression policy parameter.
## Validate Claims
JWT tokens typically contain a set of standard and non-standard claims that you can validate. Use the methods from Access Claims and Propagating to Headers to retrieve the claims present in the JWT tokens’s header or payload. Once retrieved, validate the value of the claims.
The following code example validates that the JWT token:
  * Is not expired by validating the `exp` claim.
  * Has the correct audience value by validating the `aud` claim.
  * Has the correct custom `role` claim by using a custom validator configured as a DataWeave expression policy parameter.


```
use chrono::Utc;
use pdk::hl::*;
use pdk::jwt::*;
use pdk::logger::info;
use pdk::script::Evaluator;
async fn filter(
  state: RequestState,
  mut custom_validator: Evaluator<'_>,
) -> Flow<()> {
  let headers_state = state.into_headers_state().await;
  let token = TokenProvider::bearer(headers_state.handler());
  if token.is_err() {
    return Flow::Break(Response::new(400).with_body("Bearer not found"));
  }
  // Being "token" a String that contains a JWT token
  let parsed_claims = JWTClaimsParser::parse(token.unwrap());
  if claims.is_err() {
    return Flow::Break(Response::new(401).with_body("Invalid token"));
  }
  let claims = claims.unwrap();
  // Validating token expiration
  if let Some(exp) = claims.expiration() {
    if exp < Utc::now() {
      return Flow::Break(Response::new(400).with_body("token expired"));
    }
  } else {
    return Flow::Break(Response::new(400).with_body("token missing exp claim"));
  }
  // Validating audience
  if let Some(aud) = claims.audience() {
     if !aud_value.iter_mut().any(|a| a == "myAudience") {
      return Flow::Break(Response::new(400).with_body("token does not have the expected audience"));
    }
  }
  // Custom claim validation
  custom_validator.bind_vars("claimSet", claims.get_claims());
  let result = custom_validator_role_claim.eval();
  if !result.ok().and_then(|value| value.as_bool()).unwrap_or_default() {
    return Flow::Break(Response::new(400).with_body("custom token validations failed."));
  }
  Flow::Continue(())
}
#[entrypoint]
async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> {
  let config: Config = serde_json::from_slice(&configuration)?;
  launcher
    .launch(on_request(|request| {
      filter(request, config.custom_validator_role.evaluator())
    }))
    .await?;
  Ok(())
}
```

In the above example, the custom `role` claim is defined by a DataWeave expression configured as an input parameter in the `gcl.yaml` schema definition as follows:
```
# [...]
spec:
 extends:
  - name: extension-definition
   namespace: default
 properties:
  customValidatorRole:
   type: string
   format: dataweave
   default: "#[vars.claimSet.role == 'superRole']"
   # [...]
 required:
  - customValidatorRole
```

## See Also
  * Implementing Your Custom Policy Features in Rust