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;
            }
        }
Exemple #2
0
        /// <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))