FLAT uses the security scheme of type apiKey to implement Bearer Authentication based on JSON Web Tokens (JWT).
FLAT’s x-flat-jwt extension property allows you to specify the details.
x-flat-jwt Property # The x-flat-jwt property is an object with properties describing the expected JWT token:
key: Required key to decode the JSON Web Signature (JWS). This can either be specified with a value, or by referencing a file (file) or an environment variable (env).alg: The signing algorithm the JWS is expected to be created with. This can either be specified with a value, or by referencing a file (file) or an environment variable (env). Valid values are HS256, HS385, HS512, RS256, RS384 or RS512
as well as HS or RS for any one of the supported HMAC or RSASSA algorithms.out-var: The name of the variable that stores the JWT and can be used in the flow. It must be a proper variable name, starting with $ (default: "$jwt").out-header: The name of an HTTP request header that shall carry the JWT in upstream requests.claims: An object with claims the JWT payload is expected to contain. The property names are the claim names, the expected claim value is specified either with a value, or by referencing a file (file) or an environment variable (env).scope-claim: The name of the claim, storing the scope of the token (string; default: scope). The claim value must either be
"scope1 scope2 scope3") or["scope1", "scope2", "scope3"]).post-check-flow: The path to a flow executed after the JWT is checked and found valid. In this flow, e.g. additional checks can be implemented (use the error action to throw errors).The token is considered valid if all of the following are true:
$jwt or the alternative variable specified in out-var and the header specified in out-header will be unset if the token is not valid.
Authorization Header # Use a Security Scheme Object with type: apiKey, in: header and name: Authorization if the JWT is expected to be sent as a bearer token in an Authorization header; e.g.:
securityDefinitions:
JWTHeaderAuth:
type: apiKey
in: header
name: Authorization
x-flat-jwt:
key:
file: secret.pem
alg:
env: FLAT_JWT_ALG
out-var: $header_token
scope-claim: permission
claims:
aud:
env: FLAT_JWT_AUDIENCE
The code in this example defines a security scheme named JWTHeaderAuth.
The token is expected to be a bearer token in the Authorization header.
The key is read from a file named secret.pem relative to the swagger.yaml.
The signing algorithm is read from the FLAT_JWT_ALG environment variable.
The JWT will be stored in the $header_token variable.
The scope of the token is specified in a permission claim.
The JWT payload is expected to contain an aud claim with a value read from the FLAT_JWT_AUDIENCE environment variable.
If the request does not contain an Authorization header with the proper bearer structure, or the token is invalid, this security scheme will fail.
Use a Security Scheme Object with type: apiKey, in: header, name: Cookie and x-flat-cookiename: <name> if the JWT is expected to be sent as a cookie value; e.g.:
securityDefinitions:
JWTCookieAuth:
type: apiKey
in: header
name: Cookie
x-flat-cookiename: authtoken
x-flat-jwt:
key:
env: FLAT_COOKIE_SECRET
out-var: $cookie_token
In this example the key is read from the FLAT_COOKIE_SECRET environment variable.
The JWT signing algorithm is unspecified – it defaults to HS256.
The JWT will be stored in $cookie_token.
No claims are expected.
If the request does not contain a Cookie header with an authtoken cookie, or the token is invalid, this security scheme will fail.
In Swagger, security schemes can be specified at the top level (default security) or for specific operations. With FLAT, you can also specify a security scheme for a specific path (default security for all operations on the path).
In the following example, a GET request to /foo must satisfy the security scheme named JWTHeaderAuth,
a POST request to /foo must satisfy the security scheme named JWTHeaderAuth and the token must have both write:foo and read:bar scopes,
while e.g. a DELETE or PUT request to /foo must satisfy the security scheme named JWTCookieAuth.
All other requests must satisfy either the JWTHeaderAuth or JWTCookieAuth security schemes.
Note: While in Swagger 2.0, specifying scopes in security requirements is limited to OAuth2 security definitions, FLAT has no such limitation.
# default
security:
- JWTHeaderAuth: []
- JWTCookieAuth: []
paths:
/foo:
# default for all operations on /foo
security:
- JWTCookieAuth: []
get:
# specific for GET on /foo
security:
- JWTHeaderAuth: []
post:
# specific for POST on /foo
security:
- JWTHeaderAuth: [ write:foo, read:bar ]
If a request does not pass the security check, it is rejected with status code 401 or 403 and error code 3206, and the error flow is run, if configured.
The security check is performed after validation.
securityDefinitions:
JWTHeaderAuth:
type: apiKey
in: header
name: Authorization
x-flat-jwt:
key:
file: secret.pem
alg:
env: FLAT_JWT_ALG
out-var: $header_token
scope-claim: permission
claims:
aud:
env: FLAT_JWT_AUDIENCE
JWTCookieAuth:
type: apiKey
in: header
name: Cookie
x-flat-cookiename: authtoken
x-flat-jwt:
key:
env: FLAT_COOKIE_SECRET
out-var: $cookie_token
JWTCookieAuth2:
type: apiKey
in: header
name: Cookie
x-flat-cookiename: authtoken2
x-flat-jwt:
key:
env: FLAT_COOKIE_SECRET
out-var: $cookie_token2
post-check-flow: check-cookie-jwt.xml
security: # alternatives: token in Authorization header or authtoken cookie
- JWTHeaderAuth: []
- JWTCookieAuth: []
paths:
/: # default security as defined at top-level
/foo:
get:
security: # token must be in Authorization header
- JWTHeaderAuth: []
post:
# specific for POST on /foo
security:
- JWTHeaderAuth: [ write:foo, read:bar ]
/projects/{p}:
get:
security:
- JWTCookieAuth2: []
parameters:
- name: p
in: path
type: string
required: true
The flow check-cookie-jwt.xml checks whether the value of the pid JWT claim equals the p request path parameter:
<flow>
<log>
{
"token_id": {{ $cookie_token2/pid }},
"path_id": {{ $request/params/p }}
}
</log>
<error if="not($cookie_token2/pid) or $cookie_token2/pid != $request/params/p">
{
"status": 401,
"message": "Token is not applicable for this project."
}
</error>
</flow>
The claims of an incoming JWT are stored in $jwt – or in the global
variable that you specify in the out-var
property of x-flat-jwt.
In a request or
proxy-request action you can send
these claims upstream, for example using a query parameter or a header:
<flow>
<proxy-request>
{
"url": "https://httpbin.org/get",
"query": {{ $jwt }}, <!-- ⬅ as query parameters -->
"headers": {
"Token": {{ json-stringify($jwt) }} <!-- ⬅ as 'Token' header -->
}
}
</proxy-request>
</flow>
If we assume the value of $jwt being {"id":42,"name":"John Doe"}, the resulting
upstream request URL would be https://httpbin.org/get?id=42&name=John%20Doe
and the request would include a Token header: Token: {"id":42,"name":"John Doe"}.
To just forward the received JWT token upstream as a header, you can also specify
the desired header name with the out-header property of x-flat-jwt:
securityDefinitions:
JWTHeaderAuth:
…
x-flat-jwt:
key: …
out-header: Token # ⬅ forwards this JWT in the 'Token' header
The headers section in proxy-request is then no longer needed:
<flow>
<proxy-request>
{
"url": "https://httpbin.org/get"
}
</proxy-request>
</flow>
Moreover, if you just want to proxy requests, there’s no need to define a flow
and you can simply set up your requests using x-flat-proxy:
…
securityDefinitions:
JWTHeaderAuth:
…
x-flat-jwt:
key: …
out-header: Token # ⬅ forwards the JWT in the 'Token' header
paths:
/:
get:
x-flat-proxy: # ⬅ no more x-flat-flow
url: https://httpbin.org/get
security:
- JWTHeaderAuth: []