https://github.com/jamesrandall/stravatokenmanager
C# project for managing the Strava token exchange process
https://github.com/jamesrandall/stravatokenmanager
Last synced: 5 months ago
JSON representation
C# project for managing the Strava token exchange process
- Host: GitHub
- URL: https://github.com/jamesrandall/stravatokenmanager
- Owner: JamesRandall
- License: mit
- Created: 2019-01-10T11:15:21.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2019-11-05T13:10:12.000Z (almost 7 years ago)
- Last Synced: 2024-11-21T13:43:34.503Z (over 1 year ago)
- Language: C#
- Size: 40 KB
- Stars: 2
- Watchers: 3
- Forks: 3
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Strava Token Manager
 Master
 Production
_Before reading this guide it is highly recommended you read the [Strava authentication documentation](https://developers.strava.com/docs/authentication/)._
This package can help you manage the server side part of the Strava authentication flow. Its functionality is accessed by the _ITokenManager_ interface made available through depedendency injection.
## Getting Started
First install two NuGet packages:
Install-Package AccidentalFish.Strava.TokenManager
Install-Package AccidentalFish.Strava.TokenManager.AzureTableTokenStore
To register the dependencies use the _UseStravaTokenManager_ extension method on the _IServiceCollection_ interface, for example:
IServiceCollection collection = ...; // typically provided by a framework startup system e.g. ASP. Net Core
collection.UseStravaTokenManager(new AccidentalFish.Strava.TokenManager.Options {
StravaClientId = Environment.GetEnvironmentVariable("stravaClientId"),
StravaClientSecret = Environment.GetEnvironmentVariable("stravaClientSecret") // or key vault!
});
_In a future version the following step will be optional but for the moment the token manager stores a refresh token and will use it to obtain new access tokens upon access token expiry._
You will also need to register a persistent store for tokens:
collection.UseAzureTableStorageTokenRepository(
new AccidentalFish.Strava.TokenManager.AzureTableStorageTokenStore.Options
{
StorageAccountConnectionString = Environment.GetEnvironmentVariable("your-storage-connection-string")
});
## Token Exchange - Obtaining an access token
After a user has completed the Strava authentication process Strava will redirect to your application and give you a code. This code needs to be sent back to Strava with your client ID and secret to obtain an access token that you can then use to call Strava APIs. The _TokenExchange_ method on the _ITokenManager_ interface can handle this process for you, the following simple class shows the _ITokenManager_ being injected and the code being used to obtain an access token:
class MyTokenService
{
private readonly ITokenManager _tokenManager;
public MyTokenService(ITokenManager tokenManager)
{
_tokenManager = tokenManager;
}
public async Task GetAccessTokenFromCode(string code)
{
TokenSet tokenSet = await _tokenManager.TokenExchange(code);
return tokenSet.AccessCode;
}
}
The TokenSet class will also has properties that contain the expiry date and time of the access token (_ExpiresAtUtc_) and the athletes Strava ID (_AthleteId_).
## Validating an access token
Typically you will want to ensure that an access token is valid (for example during a REST API call from a client) and you can do this by attempting to retrieve the _TokenSet_ for an access token through the _ITokenManager_ interface:
public Task VerifyAccessToken(string accessToken)
{
TokenSet tokenSet = await _tokenManager.GetTokenSetForAccessToken(accessToken, false);
Console.Log($"Token validated for athlete {tokenSet.AthleteId}");
return true;
}
If the token is invalid for some reason then an exception will be thrown by _GetTokenSetForAccessToken_.
The second parameter of _GetTokenSetForAccessToken_ indicates to the token manager if the refresh token should be used to renew the access token if it is out of date. This will return a new access token in the _TokenSet_ that you will need to use on subsequent calls. If it is false token renewal will not be attempted.
If you need to obtain a token during a background process then you can do so using the _GetTokenSetForAthleteId_ method - this behaves in exactly the same way as the _GetTokenSetForAccessToken_ method but accepts an athlete ID rather than an access token.
Note that the refresh token is never returned from the token manager - due to its long life and capability to create a new access token this is a potentially sensitive token, it is therefore not returned to mitigate leakage. If you do need access to the refresh token you can obtain it through the _ITokenRepository_ interface (dependency injectable).
## Caching of tokens
In a REST API implementation the _GetTokenSetForAccessToken_ call will be called on every REST call and so there is significant benefit in making this a cheap operation. The NuGet package _AccidentalFish.Strava.TokenManager.Abstractions_ exposes an _ITokenCache_ interface that you can use to implement a cache (the methods are fairly self explanatory). An already built Redis based cache is supplied in the _AccidentalFish.Strave.TokenManager.RedisCache_ package. To use this first add the package:
Install-Package AccidentalFish.Strava.TokenManager
And then register it with the _IServiceCollection_:
collection.UseRedisTokenCache(new AccidentalFish.Strava.TokenManager.RedisCache.Options
{
RedisConnectionString = Environment.GetEnvironmentVariable("redis-connection-string")
});
## Implementing your own token storage repository
The _AccidentalFish.Strava.TokenManager.Abstractions_ NuGet package exposes an _ITokenRepository_ interface that can be implemented to provide a storage mechanism of your choice. The methods on this interface are fairly self explanatory.
## Code Status
There are a few improvements I'd like to make and will over time but fundamentally the token manager works in simple projects and it has a set of unit tests. If you come across any issues then please reach out to me on [Twitter](https://twitter.com/AzureTrenches) or use the GitHub Issues here.