Skip to content

Latest commit

 

History

History
119 lines (102 loc) · 3.17 KB

README.md

File metadata and controls

119 lines (102 loc) · 3.17 KB

Creating JWT

To create and sign JWT, you can use the jwt_sign() function and the jwt_signing_profile block:

E.g. let's create a simple OAuth authorization server token endpoint:

server {
  endpoint "/token" {
    response {
      json_body = {
        access_token = jwt_sign("myjwt", {
          sub = request.form_body.username[0]
          aud = "The_Audience"
        })
        token_type = "Bearer"
        expires_in = 600
      }
    }
  }
}
...

In an endpoint for the path /token we use the json_body attribute to create a JSON response body. The jwt_sign() function creates the value for the access_token property. In order to sign a JWT we need a jwt_signing_profile which is configured in the definitions block and referenced by the label myjwt. With the properties sub and aud we add some additional claims to the JWT.

...
definitions {
  jwt_signing_profile "myjwt" {
    signature_algorithm = "RS256"
    key_file = "priv_key.pem"
    ttl = "600s"
    claims = {
      iss = "MyAS"
      iat = unixtime()
    }
    headers = {
      kid = "my-jwk-id"
    }
  }
}

In the jwt_signing_profile block we specify the signature algorithm (RS256), the file containing the private key (priv_key.pem), the time-to-live of the token, some default claims and the header field kid. The unixtime() function returns the current UNIX timestamp in seconds as a number.

Call Couper with

$ curl -s --data-urlencode "username=john.doe" http://localhost:8080/token

The response looks similar to

{
  "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Im15LWp3ay1pZCIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJUaGVfQXVkaWVuY2UiLCJleHAiOjE2MzM1OTE0OTIsImlhdCI6MTYzMzU5MDg5MiwiaXNzIjoiTXlBUyIsInN1YiI6ImpvaG4uZG9lIn0.qv6E3ILUe_9WR7wUhN4ZU6HWR-YoyyTNdXhf7TmiteUwXXpqUqngRqw_1h4CXJbPs250AaUf3BLeK7hJTxThCwBJl5aolngmPVnHcEiby6mq-EWOMjG-XP6NkJNI_GzmtWjpRIGcQ9zS8qMONE_GHRn_QvrtxR9rudVr6vUkLbN_6UJSETEaEH-WaKWRXUc7tsSQvB5wqnX2mVvmwchDG7lDLxL5oWM7GbpuEZQVdOEBgrLv-9D1yGkzcbaP1Y0AJWH9JaS-vpWSfwfUVvCr-Yf-iTA0EyEPFLGsTi9plz-8x5Qj_17SCSHN8M1j9MXJj_aSMH4-sVgIJf85C-EgIg",
  "expires_in": 600,
  "token_type": "Bearer"
}

When you look at the decoded access_token, the header contains the alg property as well as the kid field as configured in our jwt_signing_profile.

{
  "alg": "RS256",
  "kid": "my-jwk-id",
  "typ": "JWT"
}

Looking at the decoded payload you will find the claims iss and iat from the jwt_signing_profile, a calculated exp claim and the two additional claims aud and sub from the jwt_sign() function.

{
  "aud": "The_Audience",
  "exp": 1633591492,
  "iat": 1633590892,
  "iss": "MyAS",
  "sub": "john.doe"
}

Note: If you create "local" tokens that are consumed by your API only, you can also use a jwt block with a signing_ttl, e.g.:

...
  endpoint "/token/local" {
    response {
      json_body = {
        access_token = jwt_sign("LocalToken", {})
        token_type = "Bearer"
        expires_in = 600
      }
    }
  }
  api {
    access_control = ["LocalToken"]
    ...
  }
}

definitions {
  ...
  jwt "LocalToken" {
    signature_algorithm = "HS256"
    key = "Th3$e(rEt"
    signing_ttl = "600s"
  }
}