Created
June 28, 2020 15:51
-
-
Save smaglio81/1ccd98789d960639d26a9d82556db123 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using Microsoft.IdentityModel.JsonWebTokens; | |
using Nito.AsyncEx; | |
namespace YourProject | |
{ | |
public interface IAtlassianOAuthCredentialsManager | |
{ | |
Task<string> GetJwtAsync(); | |
Task RefreshJwtAsync(); | |
} | |
private readonly IAtlassianOAuthenticator _authenticator; | |
private readonly AsyncReaderWriterLock _jwtLock = new AsyncReaderWriterLock(); | |
private AtlassianOAuthTokenResponse _tokenResponse = null; | |
private DateTime? _validTo = null; | |
public AtlassianOAuthCredentialsManager( | |
IAtlassianOAuthenticator authenticator | |
) | |
{ | |
_authenticator = authenticator; | |
} | |
public async Task<string> GetJwtAsync() | |
{ | |
if (await ShouldRefreshJwtAsync()) | |
{ | |
await RefreshJwtAsync(); | |
} | |
string result; | |
using (await _jwtLock.ReaderLockAsync()) | |
{ | |
result = _tokenResponse.access_token; // should make an immutable copy | |
} | |
return result; | |
} | |
public async Task<AtlassianOAuthTokenResponse> GetCurrentTokenResponse() | |
{ | |
using (await _jwtLock.ReaderLockAsync()) | |
{ | |
var result = new AtlassianOAuthTokenResponse() | |
{ | |
access_token = _tokenResponse.access_token, | |
scope = _tokenResponse.scope, | |
expires_in = _tokenResponse.expires_in, | |
token_type = _tokenResponse.token_type | |
}; | |
return result; | |
} | |
} | |
private async Task<bool> ShouldRefreshJwtAsync() | |
{ | |
using(await _jwtLock.ReaderLockAsync()) { | |
if (_tokenResponse == null) return true; | |
if (_validTo == null) return true; | |
if (DateTime.Now >= _validTo.Value) return true; | |
return false; | |
} | |
} | |
public async Task RefreshJwtAsync() | |
{ | |
using(await _jwtLock.WriterLockAsync()) { | |
var response = await _authenticator.AuthenticateAsync(); | |
SetJwt(response); | |
} | |
} | |
private void SetJwt(AtlassianOAuthTokenResponse tokenResponse) | |
{ | |
_tokenResponse = tokenResponse; | |
var jwtHandler = new JsonWebTokenHandler(); | |
var token = jwtHandler.ReadJsonWebToken(_tokenResponse.access_token); | |
// https://developer.atlassian.com/cloud/jira/software/integrate-jsw-cloud-with-onpremises-tools/ | |
// Write your code to anticipate that a granted token might no longer work. For example, | |
// track the expiration time and request a new token before the existing one expires | |
// (at least 30-60 seconds prior). | |
_validTo = token.ValidTo.AddMinutes(-1); | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment