A robust authentication provider that can automatically refresh user tokens.
npm
:npm i @donation-alerts/auth
yarn
:yarn add @donation-alerts/auth
pnpm
:pnpm add @donation-alerts/auth
The authentication provider is a class that implements the AuthProvider interface, allowing you to register and manage users along with their authentication data (access tokens, refresh tokens, etc.).
Two built-in providers are available:
If these implementations do not suit your requirements — such as when you need to share authentication data across multiple processes — you can implement your own provider (e.g., using Redis) that adheres to the AuthProvider interface.
Before using the provider, you must register your application in Donation Alerts OAuth server and obtain a client ID and a client secret. Learn more in the Authorization section.
The StaticAuthProvider lets you register users and store their credentials in an internal registry, enabling you to retrieve their access tokens when needed. Note that this provider does not support automatic token refresh upon expiration.
To create an instance of StaticAuthProvider
, provide your application’s client ID:
import { StaticAuthProvider } from '@donation-alerts/auth';
const authProvider = new StaticAuthProvider('<CLIENT_ID>');
You can also specify an array of required scopes for the registering tokens:
const authProvider = new StaticAuthUser('<CLIENT_ID>', ['oauth-user-show', 'oauth-donation-index']);
If a token is registered without all the required scopes, a MissingScopeError will be thrown.
If no scopes are specified, scope validation is skipped.
It is recommended to always set scopes for added tokens so that the library can verify that the token meets the requested scopes.
The StaticAuthProvider
offers several methods to manage users:
hasUser: Checks if a user is registered.
const exists = authProvider.hasUser(123456789);
// returns a boolean
addUser: Registers a user with their authentication data.
authProvider.addUser(123456789, '<ACCESS_TOKEN>', [
'oauth-user-show',
'oauth-donation-index',
'oauth-custom_alert-store',
]);
removeUser: Unregisters a user.
authProvider.removeUser(123456789);
After a user is registered, you can retrieve their access token by using the getAccessTokenForUser method:
const token = await authProvider.getAccessTokenForUser(123456789);
This method also accepts an optional array of scopes as the second argument. If you provide scopes, the provider verifies that the token is valid for those scopes. If not, a MissingScopeError will be thrown.
For example:
// Register token with 'oauth-user-show' and 'oauth-donation-index' scopes
authProvider.addUser(123456789, {
accessToken: '<ACCESS_TOKEN>',
scopes: ['oauth-user-show', 'oauth-donation-index'],
});
// Attempting to retrieve the token with an additional required scope
// will throw a 'MissingScopeError' if the token lacks 'oauth-custom_alert-store'
const token = await authProvider.getAccessTokenForUser(123456789, ['oauth-custom_alert-store']);
The method returns an AccessTokenWithUserId object.
Unlike the StaticAuthProvider, the RefreshingAuthProvider can automatically refresh user tokens when needed.
To instantiate a RefreshingAuthProvider
, configure it with a RefreshingAuthProviderConfig:
addUserForCode
method to exchange an authorization code for an access token.import { RefreshingAuthProvider } from '@donation-alerts/auth';
const authProvider = new RefreshingAuthProvider({
clientId: '<CLIENT_ID>',
clientSecret: '<CLIENT_SECRET>',
redirectUri: '<REDIRECT_URI>',
scopes: ['oauth-user-show', 'oauth-donation-index', 'oauth-custom_alert-store'],
});
hasUser: Checks whether a user is already added to the provider.
const hasUser = authProvider.hasUser(123456789);
Returns a boolean
.
addUser: Registers a user with their token data:
const userId = 123456789;
authProvider.addUser(userId, {
accessToken: '<ACCESS_TOKEN>',
refreshToken: '<REFRESH_TOKEN>',
expiresIn: 0,
obtainmentTimestamp: 0,
scopes: ['oauth-user-show', 'oauth-donation-index', 'oauth-custom_alert-store'],
});
If expiresIn
and obtainmentTimestamp
are unknown, set them to 0
to force a token refresh on first access.
Since there is no dynamic way to verify token scopes, if you require scope validation, ensure valid scopes are provided when adding the token. It is recommended to store the token along with its valid scopes and obtainment timestamp in persistent storage (e.g., a database) after the authentication process.
This method returns an AccessTokenWithUserId object.
Both accessToken
and refreshToken
must be non-empty strings; otherwise, an InvalidTokenError will be thrown.
addUserForToken: You can also add a user using only token data:
const tokenWithUserId = await authProvider.addUserForToken({
accessToken: '<ACCESS_TOKEN>',
refreshToken: '<REFRESH_TOKEN>',
expiresIn: 0,
obtainmentTimestamp: 0,
scopes: ['oauth-user-show', 'oauth-donation-index', 'oauth-custom_alert-store'],
});
The user will be fetched internally followed by adding it to the provider with the given token data.
This method returns an AccessTokenWithUserId object.
The token must be valid for the oauth-user-show
scope to fetch user data; otherwise, a MissingScopeError will be thrown.
addUserForCode
Alternatively, you can add a user using an authorization code obtained during the OAuth2 flow:
const tokenWithUserId = await authProvider.addUserForCode('<AUTH_CODE>', [
'oauth-user-show',
'oauth-donation-index',
'oauth-custom_alert-store',
]);
The addUserForCode
method accepts an array of scopes as its second argument; these will be compared against the provider's scopes (if specified).
This method exchanges the code for an access token, retrieves the user associated with the token, and adds them to the auth provider.
This method returns an AccessTokenWithUserId object.
The token must include the oauth-user-show
scope to fetch user data; otherwise, a MissingScopeError will be thrown.
removeUser
Removes a user from the provider by their user ID:
authProvider.removeUser(123456789);
getAccessTokenForUser
Retrieves the user's access token. If the token has expired, it will be automatically refreshed, and the new token will be returned:
const token = await authProvider.getAccessTokenForUser(12345678);
Returns an AccessTokenWithUserId object.
refreshAccessTokenForUser
For cases when you need to force a token refresh, call the refreshAccessTokenForUser
method:
const token = await authProvider.refreshAccessTokenForUser(12345678);
Returns a AccessTokenWithUserId object.
Whenever an access token is refreshed — either automatically or manually — the onRefresh
event is triggered. This allows you to perform actions such as saving the updated token to persistent storage:
import { AccessToken } from '@donation-alerts/auth';
authProvider.onRefresh((userId: number, token: AccessToken) => {
console.log(`The access token was refreshed for user ${userId}`);
});
For a complete list of available methods and properties, please refer to the StaticAuthProvider and RefreshingAuthProvider documentation.
This package also provides some utility functions you may find useful if you handle some tasks outside the library:
Date
object.For more detailed information, please refer to the documentation.