Skip to main content

Security for deleting resources

The most common lifecycle of a resource flows from Creation, to Updates, to Deletion. When a resource is created access must be given to the user so that they can read and write to it afterwards. By default new resources in an application don't imply access control. If creation is when access records are created, then reads and updates are when access records are verified. There are many examples of these in the available SDKs.

For Deletion an application must take special attention to handling updates and possibly removing permissions to a resource so that resource is freed for future usage. A great example of this in the wild is DNS subdomain takeover. In simple terms, you own, and also point at your custom site. Lot's of providers will give you a CNAME to point at, for instance => {GUID} When you delete your site, your DNS still points at {GUID}, which means that anyone who navigates to will still go there. Additionally because {GUId} is now free anyone on can grab it. When they grab it, they now have a site that serves content on your domain!

Because of flaws in DNS there's no solution to fix this currently available, other than taking proper precautions, but the same issue exists for resources in your application as well. However, since access control is governed by Authress, the issue is greatly mitigated. There are steps, that the app developers should still implement however, and we'll go through them below.

Authress provided security

Authress provides security features out of the box to help prevent account resource takeover.

Token-Cache coupling

Resources and permissions in Authress are cached and those caches are automatically coupled to the JWT access token used to check the permission. When the token for the user is rotated, the caches is no longer valid and therefore requests will be realtime. Fundamentally, a user that logs out, will release access to any resource they no longer should be able to access. (Still live tokens should be treated as such and never exposed while they are active, doing so is a security risk.)

Additionally the Cache-Control set on every resource is bounded by the ceiling of the token lifetime, preventing expired tokens from being used directly with Authress.

Cache invalidation

When the resource is actually removed the Authress API supports forcing resource removal. By signalling to Authress that the resource no longer exists, it will DENY actions requiring permissions for that resource and sub resources. This additionally prevents deleted resources from being taken over until the expiry on the deletion is permanent.

{% include separator.html %}

Suggested application security

Application security is a two fold responsibility, while Authress provides most of the functionality by default, additional application patterns should be utilized in application.

Resource visibility masking

Application resources that are deleted should be marked internally as DELETED, but not actually deleted. This allows the application to managed future reads and updates to the resource. It's easy to translate a DELETED resource to a 404, but it's impossible to handle application access correctly once the resource has been deleted. When there needs to be different handling between a deleted resource and a resource that doesn't exist yet, it's beneficial to save the resource and delete it after a cutoff time.

Account and tenant caching

In application authorizers the user or tenant when user is part of an account, can be cached in your authorizer. Since the user tenants very rarely change (or never for some applications). It avoids the need to lookup the user's tenants every time a request is made. It's easy to do a quick validation in app for security purposes before making a check out to Authress. In most cases this is unnecessary and Authress handles the validations, often when providing the user with options in a UI it helps to drive behavior when an application already knows the relevant tenants.

This information can be cached with the JWT or realistically can even live within the JWT. It can be fetched using the API endpoint /users/{userId}/resources?resourceUri=/accounts for example if the resources in the application are scoped to accounts.

Forcing token invalidation

When a user deletes their own user or removes/deletes a tenant or account, a complete disassociation may be necessary. The best way to achieve this requires logging the user out. Immediately discard the user's JWT access token, and get a new one. Since the permissions and resources will be updated and no longer cached, all new requests would be made. And from this the user will see the application resources as if it never existed.

Async handling of deletion

As with many resources, async handling of deletion is preferred for most actions. There are always eventual concurrency issues and the best practice is to embrace them rather than trying to ensure everything is consistent. It's better to let additional sub-resources be created and then clean them up after, since you can't check all of them up front. So treat the parent resource as if it exists as well as the permissions when sub-resources are modified. When a parent resource is deleted, schedule an async action to take place sometime after the user's token expires. Then, at that moment clean up all resources and delete the relevant Authress access records that correspond to the resource that should no longer exist. This removes a burden on optimized caching, cache invalidation, excessive DB reads/writes, and allows for common async access patterns.