In the previous lesson, we saw how tokens are granted. However, a token without constraints is effectively a master key. 'Scopes' are the mechanism used to limit the amount of access a token grants to a client.
When a client redirects a user to the Authorization Server, it includes a `scope` parameter. This is essentially a request for a specific set of permissions.
๐ก Scopes are not permissions in the traditional RBAC (Role-Based Access Control) sense; they are 'consents' granted by the user for that specific session.
The user then sees a consent screen: 'This app wants to read your profile and write emails.' If the user agrees, the issued token will only be valid for those two specific actions.
A common mistake is verifying that a token is valid but forgetting to verify that the token has the correct scope for the requested resource.
app.get('/api/emails', async (req, res) => {
const token = req.headers.authorization;
const scopes = await verifyTokenScopes(token);
if (!scopes.includes('read:emails')) {
return res.status(403).send('Insufficient scope');
}
// Proceed to return emails
});| Scope Level | Example | Risk | Typical Use Case |
|---|---|---|---|
| Read-Only | user.read | Low | Viewing profile info |
| Write | user.write | Medium | Updating settings |
| Administrative | user.admin | Critical | Deleting account |
| Full Access | * | Extreme | Developer/Internal tools |
Scopes should be designed to be granular. Instead of a generic 'read' scope, use 'calendar.read' and 'contacts.read'. This minimizes the blast radius if a token is compromised.
Never allow a client to request a scope that exceeds the permissions of the user who is authorizing the request.
Verify exercises to earn โ 200 XP and unlock next lab level.