Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
June 22, 2022 01:20 pm GMT

Securing and caching your Hyperlambda endpoints

In this article we build upon the work we did in our previous article where we created our first manual Hyperlambda endpoint wrapping an SQL query. This article also has an associated YouTube video you can find below.

Security and JWT tokens in Magic

Magic is built upon JWT. JWT is an Open Standard for authentication and authorisation. You can read more about JWT at JWT.io. JWT tokens are what's referred to as "transparent authorisation tokens". This implies you can parse them semantically in your frontend, to see things such as username, roles, and other claims associated with the user. In a later article we will look at how you can create JWT tokens in Magic to authenticate users, but for now realising how to secure your Hyperlambda endpoints such that only authorised users can invoke them is sufficient.

To demand that a user belongs to one or more roles, you'd typically use the [auth.ticket.verify] slot. This slot simply throws an exception unless your user belongs to one of the comma separated roles you pass in as an argument to its invocation. Below is the code we started out with in the above video for your convenience.

.arguments   genre:string// This line throws unless user belongs to root or admin roleauth.ticket.verify:root, adminsqlite.connect:chinook   sqlite.select:@"select distinct c.Email, c.FirstName, c.LastName, g.name  from Customer c    inner join Invoice i on c.CustomerId = i.CustomerId    inner join InvoiceLine ii on i.InvoiceId = ii.InvoiceId    inner join Track t ON ii.TrackId = t.TrackId    inner join Genre g ON t.GenreId = g.GenreId  where g.Name = @genre  order by c.Email"      @genre:x:@.arguments/*/genre   return:x:-/*

If you modify your Hyperlambda file from our previous article and exchange its content with the above, and you try to invoke the endpoint in an incognito browser window, you'll be given a 401 error saying "access denied". This is because your browser does not associate the correct JWT token with your request.

This allows you to apply RBAC for your endpoints, implying "Role Based Access Control", to control who's got access to invoke your endpoints. RBAC is a well known authorisation mechanism for controlling who's got access to your application, and of course managing users and roles in Magic is extremely easy. Below is a screenshot of adding a user to a role from your Magic dashboard.

RBAC administration in Magic

A user can belong to one or more roles, and each endpoint can be locked for all users except those belonging to one or more roles. This pattern allows you to easily control who's got access to invoke what endpoint on your server.

Caching and the HTTP response object

In the last parts of the above video we go through how you can add HTTP headers that are returned back to the client. Specifically, we apply the Cache-Control HTTP header, which allows the client to cache the response object for "n amount of seconds". For endpoints that rarely changes their result given the same QUERY parameters, this is an easy win in regards to optimisations, and makes sure you application becomes much faster, and that the frontend becomes much more responsive, since it allows the browser to cache the endpoint's result for some pre-defined amount of time. You can find the complete code we're using to apply cache below.

.arguments   genre:stringauth.ticket.verify:root, admin// This line of code will cache your response for 200 secondsresponse.headers.set   Cache-Control:private, max-age=200sqlite.connect:chinook   sqlite.select:@"select distinct c.Email, c.FirstName, c.LastName, g.name  from Customer c    inner join Invoice i on c.CustomerId = i.CustomerId    inner join InvoiceLine ii on i.InvoiceId = ii.InvoiceId    inner join Track t ON ii.TrackId = t.TrackId    inner join Genre g ON t.GenreId = g.GenreId  where g.Name = @genre  order by c.Email"      @genre:x:@.arguments/*/genre   return:x:-/*

Validators

A validator is kind of like a "reusable business rule component", and in Magic there exists server side validators for most things you can imagine, such as email addresses, integer numbers, date and time objects, etc - And they are typically one liners and easily applied in your Hyperlambda. Below is the example code from our YouTube video where we apply a validator for our [foo] integer argument.

.arguments   genre:string   foo:intauth.ticket.verify:root, admin// This makes the genre argument mandatory.validators.mandatory:x:@.arguments/*/genre// This ensure the [foo] argument is between 100 and 200validators.integer:x:@.arguments/*/foo   min:100   max:200response.headers.set   Cache-Control:private, max-age=200sqlite.connect:chinook   sqlite.select:@"select distinct c.Email, c.FirstName, c.LastName, g.name  from Customer c    inner join Invoice i on c.CustomerId = i.CustomerId    inner join InvoiceLine ii on i.InvoiceId = ii.InvoiceId    inner join Track t ON ii.TrackId = t.TrackId    inner join Genre g ON t.GenreId = g.GenreId  where g.Name = @genre  order by c.Email"      @genre:x:@.arguments/*/genre   return:x:-/*

Notice the subtle parts above where [genre] is mandatory, but [foo] is not mandatory. However, if [foo] is given, it has to have a value between 100 and 200. If you wanted the [foo] argument to also be mandatory, you'd have to add a mandatory validator for it.

In later articles we will dive deeper into Hyperlambda validators.


Original Link: https://dev.to/polterguy/securing-and-caching-your-hyperlambda-endpoints-25kc

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To