Gadget has a built-in, role-based access control system. As you build out models and actions, Gadget auto-generates permissions that manage who can read data or run those actions. To read data or run an action, the actor making the request needs to be granted the specific permission to read that data or run that action. Actors are granted permissions by assigning roles to an actor. API keys are one type of actor -- they can be assigned roles within the Gadget editor quickly and easily. For more advanced use cases, like a full user-facing authentication system, specific records can be granted roles, which allows you to dynamically assign roles at runtime.
A Gadget app has one global list of roles which governs permissions across the application. Each role is a set of permissions that allow or deny access to a particular resource. People or systems that want to use a Gadget application must be assigned roles which grants them a set of permissions.
By default, every Gadget project is given four distinct roles:
- System Admin: This role is intended for developers working on building the application. Unlike other roles, the System Admin is permitted access to the internal API.
- Writers: The writer role is intended for users and API keys that should have both read and write access. Writers are granted read and action permissions on all of your public API endpoints by default.
- Readers: The reader role is intended for users and API keys that should have read-only access. Readers are not able to run actions. Gadget automatically assigns read permissions on all new models to the reader role by default.
- Unauthenticated: The unauthenticated role governs what an unauthenticated user or API key may access. By default, an unauthenticated user is only able to login/logout. Aside from the initial defaults, Gadget does not automatically assign any other permissions to this role.
New roles can be added, or the default roles can be deleted, if you want a different structure for your permissions system.
Every role, regardless of whether it’s assigned to an API key or a user, is given a set of permissions. Each permission is represented by a checkbox in the Roles and Permissions screen. When checked, the users and API Keys who have that role assigned become allowed to perform the operation in question.
Permissions are automatically generated for your models. Every time you create a new model, Gadget automatically generates distinct permissions for reading the model (the read permission), as well as one permission per action for that model. For a default model with an unchanged CRUD statechart, the model will generate create, update, and delete permissions that can be given to the appropriate roles. If you add custom actions to a model, Gadget will also generate permissions for them.
You can also teach Gadget to automatically grant permissions by using the Permission Defaults.
Default Read: On selection tells Gadget to automatically enable read permissions on all new models. The System Admin, Writer and Reader roles that come with every project are configured to be granted read permissions on all new models.
Default Actions: On selection tells Gadget to automatically enable permissions on all actions. The System Admin and Writer roles are configured to be granted action permissions on all new models.
Every API Key created in the Gadget Editor has a list of roles that entitle it to perform actions within the application. System Admins can change each API Key's role list, or revoke the key altogether, preventing any future use.
We recommend using API Keys to implement secure system-to-system communication with a Gadget application. API Keys are great as a simple way to write a script to import data from your local development machine or as the secure way to move high volumes of data from another production system. API Keys are secrets, so care should be taken to ensure they are stored securely and never shared with untrusted parties.
Note: API Keys role lists can be changed, but they can't be modified dynamically at runtime. If you need a wide variety of different permissions for different actors in your system, consider creating one API Key for each actor, or using a model with the RoleAssignments field type.
To represent individual entities that are entitled to a certain degree of access, individual records of a model in Gadget can also be assigned Roles. This is accomplished by using the RoleAssignments field type. Role Assignments are like any other field in Gadget -- they can be stored and retrieved, manipulated via API calls or Action effects, edited in the editor, etc. Once a record has a RoleAssignments field type, that field stores a list of Role keys, and they can now make requests and be entitled to perform the actions granted to those roles.
Role Assignments allow you to build traditional authentication systems like a User model. You can model your User model however you wish -- rename it, change its fields, add a second copy for a different set of people, or do whatever you need to to solve your problem. If the model has Role Assignments, then it can be a request actor.
Gadget creates each new application with a User model set up to have RoleAssignments by default. This model can be changed or deleted if you don't need it -- it's just a starting point to help you get going quickly.
Often the roles that a specific User might have are sensitive -- not just anyone should be able to make a request as that user and touch their stuff. For this reason, models with RoleAssignments are often protected by an authorization system, where the user needs to prove they are who they say they are before they are allowed to take any actions.
Gadget creates each new application with a Session model to manage this authorization process by default. The default Session model implements actions to allow Users to log in with an email / password. The default Session model is intended as a starting point to allow you to get going quickly. The Set User and Unset User effects can be used to implement login and logout on a different model or different actions within the Session model.