Check Pipelines
You can add check pipelines to request units to perform checks on incoming requests. check pipelines needs only to explicitly green-light the incoming request, otherwise an error is returned to the caller without executing the main pipeline.
check pipelines can also be used to contribute to the rate limiting and access control features of Xapix.

Check Pipeline Protocol

A check pipeline needs to adhere to the following data structure:
1
result.pass - Boolean, required
2
result.error.body - String, optional; error body
3
result.error.status - Integer, optional; http error status
Copied!
In case result.pass is set to false (or undefined), an error is returned to the user. If result.error.body and/or result.error.status are set, those are used to create the error response. In case multiple check pipelines fail and provide an error body / status, one of them is picked. It's recommended to always define both, error body and status. If no error body or status is defined, a 401 with the body "Access denied." is returned.
In case result.pass is set to true for all check pipelines, the request is allowed to proceed.

Custom Authentication Pipeline

The check pipeline can also be used to authenticate users, and pass details about the user back to the main pipeline. The result can also be used with the rate limiting and access control features of Xapix.
To use the rate limiting and access control features with check pipelines, you first need to set the user management to custom (see examples section below).
And one of the check pipeline needs to return the following data structure, with result.pass set to true in case the authorization passed:
1
result.pass - Boolean, required
2
result.user.id - String; user id to be used for rate limiting
3
result.user.roles - Array of Strings; roles to be used for access control and rate limiting
Copied!
The result.user.id needs to be unique per user, and will be used to rate limit access as defined in the users' roles.
The result.user.roles needs to list the user's roles, which are used to control access and enforce rate limits as defined by those roles. The roles are looked up by their id. If the user has no roles or no matching roles, access will be denied.

Examples

Smallest Check Pipeline

For an easy example, let's assume you want to require basic authentication to be present, and otherwise deny access. In that case you could use the following check pipeline:
1
---
2
version: v1
3
kind: Pipeline
4
metadata:
5
id: simple-check
6
project: simple-check
7
definition:
8
units:
9
- version: v1
10
kind: Unit/Entry
11
metadata:
12
id: entry
13
definition:
14
name: Entry
15
parameters:
16
- name: header
17
type: object
18
properties:
19
- name: Authorization
20
type: string
21
sample: Basic dGVzdDp0ZXN0
22
- version: v1
23
kind: Unit/Result
24
metadata:
25
id: result
26
definition:
27
name: Result
28
inputs:
29
- entry
30
parameters:
31
- name: result
32
type: object
33
properties:
34
- name: pass
35
type: boolean
36
formula: "entry.header.Authorization = 'Basic dGVzdDp0ZXN0'"
Copied!
The request pipeline would then look like this:
1
---
2
version: v1
3
kind: Endpoint/REST
4
metadata:
5
id: test
6
project: simple-check
7
definition:
8
name: test
9
path: test
10
httpMethod: get
11
pipeline:
12
units:
13
- version: v1
14
kind: Unit/Request
15
metadata:
16
id: request
17
definition:
18
name: Request
19
parameters:
20
- name: header
21
type: object
22
properties:
23
- name: Authorization
24
type: string
25
checkPipelines:
26
- simple-check
27
- version: v1
28
kind: Unit/Endpoint
29
metadata:
30
id: endpoint
31
definition:
32
name: Endpoint
33
inputs:
34
- request
35
parameters:
36
- name: body
37
type: object
38
properties:
39
- name: status
40
formula: '"ok"'
Copied!
Note the checkPipelines in the Unit/Request resource which references the simple-check pipeline defined above.

Check Pipeline for Authentication, Rate Limiting and Access Controls

To switch a project to use a custom check pipeline for authentication, and to use rate limiting and access controls, apply the following ApiPublishing resource definition to switch user management to custom
1
---
2
version: v1
3
kind: ApiPublishing
4
metadata:
5
id: <project-id>
6
definition:
7
enabled: true
8
userManagement: custom
Copied!
Then adjust the check-pipeline above to return result.user.id and result.user.roles.

Custom JWT Check Pipeline

For a more realistic example, let's assume you want to validate your custom JWTs and only permit access for users with valid tokens and valid roles. The check pipeline would look something like this:
1
---
2
version: v1
3
kind: Credential/PublicPrivateKey
4
metadata:
5
id: jwt-verification-key
6
definition:
7
name: JWT verification key
8
publicKey: |
9
-----BEGIN PUBLIC KEY-----
10
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv
11
vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc
12
aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy
13
tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0
14
e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb
15
V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9
16
MwIDAQAB
17
-----END PUBLIC KEY-----
18
---
19
version: v1
20
kind: Pipeline
21
metadata:
22
id: jwt-request-check
23
definition:
24
units:
25
- version: v1
26
kind: Unit/Entry
27
metadata:
28
id: entry
29
definition:
30
name: Entry
31
parameters:
32
- name: header
33
type: object
34
properties:
35
- name: Authorization
36
type: string
37
sample: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwibmJmIjoxNTgyMjE1ODYwLCJleHAiOjE1ODQ4MDg1NTV9.b_a_hY9svkBuSLwTr25VvGUfAddoYGV8bSG1dxvfHv5scgbVFfmfowOxqBtA4c2D_KmIIRfQsFGsBi9j3JMnKHmU6ABL1KJqqV7OmNlC4MQX-Ai0fySqTcC9kQ47CjrUdGybv38WLCr_iBGlV_FMD6bp51VmoJvqK6KlOu5M_DRmrVpuIoDcaoakZaV-dMI5oPIhDz9g0CCfSyOT1AkVz1kjVsa67afOW3meiynz7oGqsKxs4zpOaw7kUjFKc5aSfcUnsGeYZoWj6qk8mBD8C9mck4fNpOyPLxlHK7R0U7DtD_Kzi373AFVAsptPmM07RlIaOfWfmULArUy0RwExMQ
38
- version: v1
39
kind: Unit/SecureStore
40
metadata:
41
id: secure-store
42
definition:
43
name: Secure Store
44
credentials:
45
- jwt-verification-key
46
- version: v1
47
kind: Unit/Transform
48
metadata:
49
id: extract
50
definition:
51
name: Extract
52
inputs:
53
- entry
54
- secure-store
55
parameters:
56
- name: auth
57
type: string
58
sample:
59
formula: |
60
WITH(
61
jwt, REGEXEXTRACT(IF(entry.header.Authorization, entry.header.Authorization, ""), '^Bearer (.+)'),
62
key, KEY.PUB(secure-store.jwt-verification-key_public_key),
63
JWT.VERIFY('RS256', IF(jwt, jwt, ""), key)
64
)
65
- version: v1
66
kind: Unit/Result
67
metadata:
68
id: result
69
definition:
70
name: Result
71
inputs:
72
- extract
73
parameters:
74
- name: result
75
type: object
76
properties:
77
- name: pass
78
type: boolean
79
formula: |
80
AND(
81
NOT(.extract.auth.error),
82
NOW() >= .extract.auth.payload.nbf,
83
NOW() < .extract.auth.payload.exp)
84
sample: "true"
85
- name: user
86
type: object
87
properties:
88
- name: id
89
formula: ".extract.auth.payload.sub"
90
sample: "1234567890"
91
- name: roles
92
formula: ".extract.auth.payload.roles"
93
sample: "default_test_role"
94
- name: error
95
type: object
96
properties:
97
- name: body
98
formula: ".extract.auth.error.message"
99
- name: status
100
formula: "401"
Copied!
This assumes that for your JWTs you're using the following format:
1
{
2
"sub": "1234567890",
3
"nbf": 1582215860,
4
"exp": 1584808555,
5
"roles": ["some_role"]
6
}
Copied!
To check the JWT, only the public key is needed. If the key is valid and not yet expired (checking "nbf" and "exp", see line 82-83), the check pipeline returns the token's subject (line 89) and roles (line 92). The roles need to be created in Xapix, and access is only given if at least one role from the token matches with the list of roles which have access to the endpoint. If you do not want to check access permissions with Xapix, you can simply use a static role instead of taking them from the token.
Last modified 1yr ago