/// <inheritdoc/> public async Task <TokenResultModel> GetTokenForAsync(string resource, IEnumerable <string> scopes) { var exceptions = new List <Exception>(); foreach (var config in _config.Query(resource, AuthProvider.AuthService)) { if (string.IsNullOrEmpty(config.ClientSecret)) { continue; } try { var client = Http.CreateClient("token_client"); var response = await client.RequestClientCredentialsTokenAsync( new ClientCredentialsTokenRequest { Address = $"{config.GetAuthorityUrl()}/connect/token", ClientId = config.ClientId, ClientSecret = config.ClientSecret }); if (response.IsError) { _logger.Error("Error {error} aquiring token for {resource} with {config}", response.Error, resource, config.GetName()); return(null); } var result = JwtSecurityTokenEx.Parse(response.AccessToken); _logger.Information( "Successfully acquired token for {resource} with {config}.", resource, config.GetName()); return(result); } catch (Exception exc) { _logger.Debug(exc, "Failed to get token for {resource} using {config}", resource, config.GetName()); exceptions.Add(exc); } } if (exceptions.Count != 0) { throw new AggregateException(exceptions); } return(null); }
/// <inheritdoc/> public async Task <TokenResultModel> GetTokenForAsync(string resource, IEnumerable <string> scopes) { var exceptions = new List <Exception>(); foreach (var(config, provider) in Get(resource)) { try { var token = await provider.KeyVaultTokenCallback( config.GetAuthorityUrl(true), config.GetAudience(scopes), config.GetScopeNames(scopes)?.FirstOrDefault()); if (token == null) { return(null); } var result = JwtSecurityTokenEx.Parse(token); if (result.ExpiresOn < DateTime.UtcNow) { return(null); } _logger.Information( "Successfully acquired token for {resource} with {config}.", resource, config.GetName()); return(result); } catch (Exception ex) { _logger.Debug(ex, "Failed to retrieve token for {resource} using {config}", resource, config.GetName()); exceptions.Add(ex); continue; } } if (exceptions.Count != 0) { throw new AggregateException(exceptions); } return(null); }
/// <summary> /// Helper to get token from cache /// </summary> /// <returns></returns> private async Task <TokenResultModel> GetTokenFromCacheAsync(string resource, IEnumerable <string> scopes) { var cached = await _cache.GetAsync(GetKey(resource)); if (cached != null) { var token = JwtSecurityTokenEx.Parse(Encoding.UTF8.GetString(cached)); if (token.ExpiresOn >= DateTimeOffset.UtcNow + TimeSpan.FromSeconds(30)) { if (scopes != null) { // TODO: Check token has all scope is part of the token if (!scopes.All(scope => string.IsNullOrEmpty(scope))) { return(null); } } return(token); } } return(null); }
/// <inheritdoc/> public async Task <TokenResultModel> GetTokenForAsync(string resource, IEnumerable <string> scopes) { const string kAccessTokenKey = "access_token"; if (_ctx.HttpContext == null) { return(null); } string token = null; if (_providers == null) { token = await _ctx.HttpContext.GetTokenAsync(kAccessTokenKey); } else { foreach (var provider in _providers) { token = await _ctx.HttpContext.GetTokenAsync(provider, kAccessTokenKey); if (token != null) { break; // Use first found token } } } if (string.IsNullOrEmpty(token)) { return(null); } var result = JwtSecurityTokenEx.Parse(token); result.Cached = true; // Already cached as part of context return(result); }
/// <inheritdoc/> public async Task <TokenResultModel> GetTokenForAsync(string resource, IEnumerable <string> scopes) { var user = _ctx.HttpContext?.User; if (user == null) { return(null); } var schemes = await _schemes.GetAllSchemesAsync(); if (!schemes.Any(s => s.Name == AuthProvider.AuthService)) { return(null); } if (!user.Identity.IsAuthenticated) { _logger.Debug("User is not authenticated."); return(null); } var userName = user.FindFirst(JwtClaimTypes.Name)?.Value ?? user.FindFirst(JwtClaimTypes.Subject)?.Value ?? "unknown"; var(accessToken, expiration, refreshToken) = await GetTokenFromCacheAsync(); if (refreshToken == null) { _logger.Debug("No token data found in user token store."); return(null); } var dtRefresh = expiration.Value.Subtract(TimeSpan.FromMinutes(1)); if (dtRefresh >= _clock.UtcNow) { // Token still valid - use it. var token = JwtSecurityTokenEx.Parse(accessToken); token.Cached = true; return(token); } var exceptions = new List <Exception>(); foreach (var config in _config.Query(resource, AuthProvider.AuthService)) { try { _logger.Debug("Token for user {user} needs refreshing.", userName); try { accessToken = await kRequests.GetOrAdd(refreshToken, t => { return(new Lazy <Task <string> >(async() => { var refreshed = await RefreshUserAccessTokenAsync(t, config); return refreshed.AccessToken; })); }).Value; var token = JwtSecurityTokenEx.Parse(accessToken); token.Cached = true; _logger.Information( "Successfully refreshed token for {resource} with {config}.", resource, config.GetName()); return(token); } finally { kRequests.TryRemove(refreshToken, out _); } } catch (Exception e) { _logger.Debug(e, "Failed to get token for {resource} with {config}.", resource, config.GetName()); exceptions.Add(e); continue; } } if (exceptions.Count != 0) { throw new AggregateException(exceptions); } return(null); }