-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
jwt-claims as arguments example (#50)
* jwt-claims as arguments example * cleanup * cleanup * cleanup * cleanup * wip - JWT claims with explicit SQL predicate * chore: quick overview * remove dups * chore: cleanup * chore: add testing
- Loading branch information
1 parent
35ed095
commit c844a26
Showing
8 changed files
with
359 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Pulling field arguments from JWT claims | ||
|
||
Uses a SQL predicate to limit customer rows returned from a database | ||
to those matching the regions defined in a JWT claim. | ||
|
||
# Try it Out | ||
|
||
Run the [sample operations](operations.graphql): | ||
|
||
JWT with `regions: IN`. | ||
|
||
``` | ||
stepzen request -f operations.graphql --operation-name=Customers \ | ||
--header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1IiwicmVnaW9ucyI6WyJJTiJdfQ.hDi3-qaIOSFKzlFvaXwSh0trXC3vjiOehSKE0OxgOdE" | ||
``` | ||
|
||
JWT with `regions: IN, UK`. | ||
|
||
``` | ||
stepzen request -f operations.graphql --operation-name=Customers \ | ||
--header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1IiwicmVnaW9ucyI6WyJJTiIsIlVLIl19.CRD85IIMMwjaFebtQ_p3AjSoUM6KtH4gvjcfLQfdmjw" | ||
``` | ||
|
||
JWT with `regions: US, UK`. | ||
|
||
``` | ||
stepzen request -f operations.graphql --operation-name=Customers \ | ||
--header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1IiwicmVnaW9ucyI6WyJVUyIsIlVLIl19.pf0-A6TN_hT-ldCvsZyqYGv4Twjm9s6wO1aatCjK9Aw" | ||
``` | ||
|
||
JWT with `regions: US, UK` and user supplied filter | ||
|
||
``` | ||
stepzen request -f operations.graphql --operation-name=Customers \ | ||
--var f='{"city": {"eq":"London"}}' \ | ||
--header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1IiwicmVnaW9ucyI6WyJVUyIsIlVLIl19.pf0-A6TN_hT-ldCvsZyqYGv4Twjm9s6wO1aatCjK9Aw" | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
deployment: | ||
identity: | ||
keys: | ||
- algorithm: HS256 | ||
key: development-only | ||
access: | ||
policies: | ||
- type: Query | ||
policyDefault: | ||
condition: false | ||
rules: | ||
- name: "jwt-control" | ||
fields: [customers] | ||
condition: "?$jwt" | ||
- name: "introspection" | ||
fields: [__schema, __type] | ||
condition: true | ||
configurationset: | ||
- configuration: | ||
name: postgresql_config | ||
uri: postgresql://postgresql.introspection.stepzen.net/introspection?user=testUserIntrospection&password=HurricaneStartingSample1934 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
schema | ||
@sdl( | ||
files: ["paging.graphql"] | ||
# visibilty controls how fields included through files in this directive | ||
# are visible outside the scope of this directive to GraphQL introspection | ||
# and field references through @materializer etc. | ||
# | ||
# types and fields are regular expressions that match type and field names. | ||
# Like field access rules if aat least one visibility pattern is present then by default | ||
# root operation type (Query, Mutation, Subscription) fields are not exposed. | ||
visibility: [{ expose: true, types: "Query", fields: ".*" }] | ||
) { | ||
query: Query | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
query Customers($f: CustomerFilter) { | ||
customers(filter: $f) { | ||
id | ||
name | ||
city | ||
region | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
type Customer { | ||
id: ID! | ||
name: String | ||
email: String | ||
street: String | ||
city: String | ||
region: String | ||
} | ||
|
||
""" | ||
`CustomerConnection` is the connection type for `Customer` pagination. | ||
""" | ||
type CustomerConnection { | ||
edges: [CustomerEdge] | ||
pageInfo: PageInfo! | ||
} | ||
|
||
""" | ||
`CustomerEdge` provides access to the node and its cursor. | ||
""" | ||
type CustomerEdge { | ||
node: Customer | ||
cursor: String | ||
} | ||
|
||
input StringFilter { | ||
eq: String | ||
ne: String | ||
} | ||
|
||
input CustomerFilter { | ||
name: StringFilter | ||
email: StringFilter | ||
city: StringFilter | ||
} | ||
|
||
type _RegionsList { | ||
regions: [String]! | ||
} | ||
|
||
extend type Query { | ||
# customers is the exposed field that limits the caller to regions | ||
# based upon the regions claim in the request's JWT. | ||
customers(first: Int! = 10, filter: CustomerFilter): [Customer] | ||
@sequence( | ||
steps: [ | ||
{ query: "_regions" } | ||
{ | ||
query: "_customers_flatten" | ||
arguments: [ | ||
{ name: "first", argument: "first" } | ||
{ name: "filter", argument: "filter" } | ||
] | ||
} | ||
] | ||
) | ||
|
||
# extracts the regions visible to the request from the JWT. | ||
_regions: _RegionsList | ||
@value( | ||
script: { | ||
src: """ | ||
{"regions": `$jwt`.regions } | ||
""" | ||
language: JSONATA | ||
} | ||
) | ||
|
||
# this flattens the customer connection pagination structure | ||
# into a simple list of Customer objects. | ||
# This is needed as @sequence is not supported for connection types. | ||
_customers_flatten( | ||
first: Int! = 10 | ||
filter: CustomerFilter | ||
regions: [String]! | ||
): [Customer] @materializer(query: "_customers { edges { node }}") | ||
|
||
# Standard paginated field for a customers table in a database. | ||
# Additional regions argument that is used to limit customer | ||
# visibility based upon the 'regions' claim in a JWT. | ||
# The regions allows a list of regions and uses SQL ANY to match rows. | ||
_customers( | ||
first: Int! = 10 | ||
after: String! = "" | ||
filter: CustomerFilter | ||
regions: [String]! | ||
): CustomerConnection | ||
@dbquery( | ||
type: "postgresql" | ||
schema: "public" | ||
query: """ | ||
SELECT C.id, C.name, C.email, A.street, A.city, A.countryregion AS region | ||
FROM customer C, address A, customeraddress CA | ||
WHERE | ||
CA.customerid = C.id AND | ||
CA.addressid = A.id AND | ||
A.countryregion = ANY(CAST($1 AS VARCHAR ARRAY)) | ||
""" | ||
configuration: "postgresql_config" | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"endpoint": "api/miscellaneous" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
const fs = require("fs"); | ||
const path = require("node:path"); | ||
const { | ||
deployAndRun, | ||
runtests, | ||
GQLHeaders, | ||
endpoint, | ||
getTestDescription, | ||
} = require("../../../tests/gqltest.js"); | ||
|
||
testDescription = getTestDescription("snippets", __dirname); | ||
|
||
const requestsFile = path.join(path.dirname(__dirname), "operations.graphql"); | ||
const requests = fs.readFileSync(requestsFile, "utf8").toString(); | ||
|
||
describe(testDescription, function () { | ||
// just deploy | ||
deployAndRun(__dirname, [], undefined); | ||
|
||
// and then run with various JWTs | ||
runtests( | ||
"regions-in", | ||
endpoint, | ||
new GQLHeaders().withToken( | ||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1IiwicmVnaW9ucyI6WyJJTiJdfQ.hDi3-qaIOSFKzlFvaXwSh0trXC3vjiOehSKE0OxgOdE" | ||
), | ||
[ | ||
{ | ||
label: "customers", | ||
query: requests, | ||
operationName: "Customers", | ||
expected: { | ||
customers: [ | ||
{ | ||
id: "10", | ||
name: "Salma Khan ", | ||
city: "Delhi ", | ||
region: "IN ", | ||
}, | ||
], | ||
}, | ||
}, | ||
] | ||
); | ||
runtests( | ||
"regions-in-uk", | ||
endpoint, | ||
new GQLHeaders().withToken( | ||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1IiwicmVnaW9ucyI6WyJJTiIsIlVLIl19.CRD85IIMMwjaFebtQ_p3AjSoUM6KtH4gvjcfLQfdmjw" | ||
), | ||
[ | ||
{ | ||
label: "customers", | ||
query: requests, | ||
operationName: "Customers", | ||
expected: { | ||
customers: [ | ||
{ | ||
id: "3", | ||
name: "Salim Ali ", | ||
city: "London ", | ||
region: "UK ", | ||
}, | ||
{ | ||
id: "4", | ||
name: "Jane Xiu ", | ||
city: "Edinburgh ", | ||
region: "UK ", | ||
}, | ||
{ | ||
id: "10", | ||
name: "Salma Khan ", | ||
city: "Delhi ", | ||
region: "IN ", | ||
}, | ||
], | ||
}, | ||
}, | ||
] | ||
); | ||
runtests( | ||
"regions-us-uk", | ||
endpoint, | ||
new GQLHeaders().withToken( | ||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1IiwicmVnaW9ucyI6WyJVUyIsIlVLIl19.pf0-A6TN_hT-ldCvsZyqYGv4Twjm9s6wO1aatCjK9Aw" | ||
), | ||
[ | ||
{ | ||
label: "customers", | ||
query: requests, | ||
operationName: "Customers", | ||
expected: { | ||
customers: [ | ||
{ | ||
id: "1", | ||
name: "Lucas Bill ", | ||
city: "Boston ", | ||
region: "US ", | ||
}, | ||
{ | ||
id: "2", | ||
name: "Mandy Jones ", | ||
city: "Round Rock ", | ||
region: "US ", | ||
}, | ||
{ | ||
id: "3", | ||
name: "Salim Ali ", | ||
city: "London ", | ||
region: "UK ", | ||
}, | ||
{ | ||
id: "4", | ||
name: "Jane Xiu ", | ||
city: "Edinburgh ", | ||
region: "UK ", | ||
}, | ||
{ | ||
id: "5", | ||
name: "John Doe ", | ||
city: "Miami ", | ||
region: "US ", | ||
}, | ||
{ | ||
id: "6", | ||
name: "Jane Smith ", | ||
city: "San Francisco ", | ||
region: "US ", | ||
}, | ||
{ | ||
id: "7", | ||
name: "Sandeep Bhushan ", | ||
city: "New York ", | ||
region: "US ", | ||
}, | ||
{ | ||
id: "8", | ||
name: "George Han ", | ||
city: "Seattle ", | ||
region: "US ", | ||
}, | ||
{ | ||
id: "9", | ||
name: "Asha Kumari ", | ||
city: "Chicago ", | ||
region: "US ", | ||
}, | ||
], | ||
}, | ||
}, | ||
{ | ||
label: "customers-filter", | ||
query: requests, | ||
operationName: "Customers", | ||
variables: { | ||
f: { city: { eq: "London" } }, | ||
}, | ||
expected: { | ||
customers: [ | ||
{ | ||
id: "3", | ||
name: "Salim Ali ", | ||
city: "London ", | ||
region: "UK ", | ||
}, | ||
], | ||
}, | ||
}, | ||
] | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters