private async void RefreshTimerCallback(object state) { Logger.LogInformation($"Access token is {AutoRefreshMinsBeforeExpiry} minutes out from expiration - attempting refresh."); var refreshRequest = new TokenRefreshRequest { GrantType = "refresh_token", RefreshToken = SC.RefreshToken, }; var refreshChannel = new Channel($"{_sp.AppSvcHostname}:{_sp.AppSvcPort}", AccessToken.NullToken.ToChannelCredentials()); var ss = new SessionSvc.SessionSvcClient(refreshChannel); var sessionResponse = await ss.RefreshAccessTokenAsync(refreshRequest, new CallOptions(null, DateTime.UtcNow.AddSeconds(30))); await refreshChannel.ShutdownAsync(); if (sessionResponse.Result == SessionSvcStartSessionResult.Success) { Logger.LogInformation($"Successfully refreshed session"); SS = new SessionService(sessionResponse.SessionContext); StartServicesChannelRefresh(sessionResponse.SessionContext); } else { Logger.LogInformation($"Failed to refresh session. Session will continue with existing access token, and will end in less than {AutoRefreshMinsBeforeExpiry} minutes."); } }
public virtual async Task <SessionSvcStartSessionResult> StartSession(string candidateUsername, string candidatePassword) { var startReq = new SessionSvcStartSessionRequest { CandidateUsername = candidateUsername, CandidatePassword = candidatePassword, ClientInstanceId = new ClientInstanceIndicator(_sp.ClientInstanceId), OauthClientId = _clientId, }; // NOTE(DA) This section of the code has given me more grief than would be expected. // // Our gRPC server only uses SSL. We have one port open and it expects all incoming // traffic to be SSL. This means our client has to speak SSL to the server. // // Somewhat annoyingly (though we'll grudgingly admit the safety benefits), gRPC is // very opinionated in its use of SSL. There is only one way to get it to use SSL -- // supply a bearer credential -- which is exactly what we don't have, we're trying to // get one with this call! (Chicken and egg problem). // // We resort to forgery to trick gRPC into using SSL. We keep this forged channel // separate and use it only for authentication purposes, throwing it out after we use // it here. // // We were originally keeping the channel around to avoid recreating it, but it's used // pretty infrequently, which means (1) we don't care about performance and (2) it was // sitting idle too long, and NAT rules were killing it off. Don't try it, we did it // and it didn't work. // // Future: currently, we don't support "session multiplexing" -- users of this // component (AppClient) start a single session, and expect it to stay open for the // life of the client. We need session multiplexing for service-service communication // where we have numerous security contexts existing side-by-side. We need to do some // thinking on how to design an interface that facilitates both use cases without making // either needlessly complicated. One option would be to force the client to suply a // credential at call time, implementing an optional ApplicationClient-maintained // "credential registry" or "session registry" that the client could use to retrieve // the token at call-time, if desired. var loginChannel = new Channel($"{_sp.AppSvcHostname}:{_sp.AppSvcPort}", AccessToken.NullToken.ToChannelCredentials()); var ss = new SessionSvc.SessionSvcClient(loginChannel); var sessionResponse = await ss.TryStartSessionAsync(startReq, new CallOptions(null, DateTime.UtcNow.AddSeconds(30))); if (sessionResponse.Result == SessionSvcStartSessionResult.Success) { SS = new SessionService(sessionResponse.SessionContext); StartServicesChannelRefresh(sessionResponse.SessionContext); } await loginChannel.ShutdownAsync(); return(sessionResponse.Result); }
private void InvalidateRefreshToken() { var refreshChannel = new Channel($"{_sp.AppSvcHostname}:{_sp.AppSvcPort}", AccessToken.NullToken.ToChannelCredentials()); var ss = new SessionSvc.SessionSvcClient(refreshChannel); var request = new TokenInvalidationRequest { RefreshToken = SC.RefreshToken, }; var invalidationResponse = ss.InvalidateRefreshToken(request); var loggingInfo = invalidationResponse.Result == TokenInvalidationResult.InvalidationFailure ? "un" : ""; Logger.LogInformation($"Invalidation of Refresh Token was {loggingInfo}successful"); }