protected override async Task <Outcome <ActorToken> > OnGetAccessTokenAsync(CancellationToken cancellationToken) { try { var accessTokenOutcome = await base.OnGetAccessTokenAsync(cancellationToken); if (!accessTokenOutcome) { return(accessTokenOutcome); } // try getting a cached exchanged token ... var accessToken = accessTokenOutcome.Value; var cachedOutcome = await getCachedIdentityTokenAsync(accessToken); if (cachedOutcome) { return(cachedOutcome); } // exchange token for var clientCredentials = await OnGetClientCredentials(); var credentials = new BasicAuthCredentials(clientCredentials.Identity, clientCredentials.Secret); var bearerToken = accessTokenOutcome.Value as BearerToken; var isBearerToken = bearerToken is { }; var subjectToken = isBearerToken ? bearerToken.Value : accessTokenOutcome.Value.ToString(); var txOutcome = await _tokenExchangeService.ExchangeAccessTokenAsync( credentials, subjectToken, cancellationToken); if (!txOutcome || !ActorToken.TryParse(txOutcome.Value.AccessToken, out var actorToken)) { return(Outcome <ActorToken> .Fail(txOutcome.Exception)); } var exchangedToken = isBearerToken ? new BearerToken(actorToken.Identity, false) : actorToken; // cache exchanged token and return it ... await cacheTokenExchangeAsync(accessToken, exchangedToken); return(Outcome <ActorToken> .Success(exchangedToken)); } catch (Exception ex) { Logger.Error(new Exception($"Claims transformation failure: {ex.Message}", ex)); throw; } }
/// <summary> /// Tries obtaining an access token from the request. /// </summary> /// <returns> /// An <see cref="Outcome{T}"/> instance indicating success/failure. On success the outcome /// holds the access token in its <see cref="Outcome{T}.Value"/> property. On failure the outcome /// declares the problem via its <see cref="Outcome.Exception"/> property. /// </returns> /// <seealso cref="GetAccessToken(Microsoft.AspNetCore.Http.HttpContext, TetraPakAuthConfig)"/> /// <see cref="GetAccessTokenAsync(Microsoft.AspNetCore.Http.HttpRequest, TetraPakAuthConfig)"/> public static Task <Outcome <ActorToken> > GetAccessTokenAsync(this HttpContext self, TetraPakAuthConfig authConfig) { if (self.Items.TryGetValue(AmbientData.Keys.AccessToken, out var o) && o is string s && ActorToken.TryParse(s, out var actorToken)) { return(Task.FromResult(Outcome <ActorToken> .Success(actorToken))); } var headerIdent = authConfig?.AuthorizationHeader ?? HeaderNames.Authorization; s = self.Request.Headers[headerIdent].FirstOrDefault(); if (s is {} && ActorToken.TryParse(s, out actorToken))