By only allowing a custom storage. To use one of the built-in storage mechanism, there is already a special-purpose `persist_tokens_to_disk` method available.
Just pass `&[&str]` into custom storage providers. The scopeset struct has a range of unnecessary internal features.
It's now also part of the interface for custom storage providers that the given scopes will be both unique and sorted.
The only slightly awkward thing is that there's no conventient way to expose a `scopes_covered_by` helper method (which almost all custom storage engines will need), but it's still included in the example code.
Instead, suggest using interior mutability (and RwLock in the example) to manage storage of token states. This makes it easier to share authenticators between threads.
Allow users to build their own token storage system by implementing the `TokenStorage` trait. This allows use of more secure storage mechanisms like OS keychains, encrypted files, or secret-management tools.
Custom storage providers are Box-ed to avoid adding more generics to the API — the indirection cost will only apply if using a custom store.
I've added `anyhow` to allow easy handling of a wide range of errors from custom storage providers.