public async Task CompleteLoginRequestAsync_should_default_idp_and_authtime()
    {
        _mockUserSession.User = new IdentityServerUser("123").CreatePrincipal();
        var req = new BackChannelAuthenticationRequest
        {
            ClientId        = _client.ClientId,
            Subject         = new IdentityServerUser("123").CreatePrincipal(),
            RequestedScopes = new[] { "scope1", "scope2", "scope3" },
        };
        var requestId = await _mockStore.CreateRequestAsync(req);

        await _subject.CompleteLoginRequestAsync(new CompleteBackchannelLoginRequest(req.InternalId)
        {
            Description           = "desc",
            ScopesValuesConsented = new string[] { "scope1", "scope2" },
            SessionId             = "sid",
            Subject = new IdentityServerUser("123")
            {
                DisplayName = "name",
                //AuthenticationTime = _mockSystemClock.UtcNow.UtcDateTime,
                //IdentityProvider = "idp",
                AdditionalClaims      = { new Claim("foo", "bar") },
                AuthenticationMethods = { "phone", "pin" }
            }.CreatePrincipal()
        });

        var item = _mockStore.Items[requestId];

        item.Subject.HasClaim("idp", "local").Should().BeTrue();
        item.Subject.HasClaim("auth_time", _mockSystemClock.UtcNow.ToUnixTimeSeconds().ToString()).Should().BeTrue();
    }
Ejemplo n.º 2
0
    async Task <BackchannelUserLoginRequest> CreateAsync(BackChannelAuthenticationRequest request)
    {
        if (request == null)
        {
            return(null);
        }

        var client = await _clientStore.FindEnabledClientByIdAsync(request.ClientId);

        if (client == null)
        {
            return(null);
        }

        var validatedResources = await _resourceValidator.ValidateRequestedResourcesAsync(new ResourceValidationRequest
        {
            Client             = client,
            Scopes             = request.RequestedScopes,
            ResourceIndicators = request.RequestedResourceIndicators,
        });

        return(new BackchannelUserLoginRequest
        {
            InternalId = request.InternalId,
            Subject = request.Subject,
            Client = client,
            ValidatedResources = validatedResources,
            RequestedResourceIndicators = request.RequestedResourceIndicators,
            AuthenticationContextReferenceClasses = request.AuthenticationContextReferenceClasses,
            BindingMessage = request.BindingMessage,
        });
    }
    public async Task CompleteLoginRequestAsync_should_require_a_valid_request_id()
    {
        var req = new BackChannelAuthenticationRequest
        {
            ClientId        = _client.ClientId,
            Subject         = new IdentityServerUser("123").CreatePrincipal(),
            RequestedScopes = new[] { "scope1", "scope2", "scope3" },
        };
        var requestId = await _mockStore.CreateRequestAsync(req);

        Func <Task> f = async() => await _subject.CompleteLoginRequestAsync(new CompleteBackchannelLoginRequest("invalid")
        {
            Description           = "desc",
            ScopesValuesConsented = new string[] { "scope1", "invalid" },
            SessionId             = "sid",
            Subject = new IdentityServerUser("123")
            {
                DisplayName           = "name",
                AuthenticationTime    = new DateTime(2000, 02, 03, 8, 15, 00, DateTimeKind.Utc),
                IdentityProvider      = "idp",
                AdditionalClaims      = { new Claim("foo", "bar") },
                AuthenticationMethods = { "phone", "pin" }
            }.CreatePrincipal()
        });

        f.Should().Throw <InvalidOperationException>().WithMessage("Invalid backchannel authentication request id.");
    }
Ejemplo n.º 4
0
    public Task <string> CreateRequestAsync(BackChannelAuthenticationRequest request)
    {
        var key = Guid.NewGuid().ToString();

        request.InternalId = key.Sha256();
        Items.Add(key, request);
        return(Task.FromResult(key));
    }
Ejemplo n.º 5
0
    /// <inheritdoc/>
    public virtual async Task <BackchannelAuthenticationResponse> ProcessAsync(BackchannelAuthenticationRequestValidationResult validationResult)
    {
        using var activity = Tracing.BasicActivitySource.StartActivity("BackchannelAuthenticationResponseGenerator.Process");

        if (validationResult == null)
        {
            throw new ArgumentNullException(nameof(validationResult));
        }
        if (validationResult.ValidatedRequest == null)
        {
            throw new ArgumentNullException(nameof(validationResult.ValidatedRequest));
        }
        if (validationResult.ValidatedRequest.Client == null)
        {
            throw new ArgumentNullException(nameof(validationResult.ValidatedRequest.Client));
        }

        Logger.LogTrace("Creating response for backchannel authentication request");

        var request = new BackChannelAuthenticationRequest
        {
            CreationTime                = Clock.UtcNow.UtcDateTime,
            ClientId                    = validationResult.ValidatedRequest.ClientId,
            RequestedScopes             = validationResult.ValidatedRequest.ValidatedResources.RawScopeValues,
            RequestedResourceIndicators = validationResult.ValidatedRequest.RequestedResourceIndiators,
            Subject  = validationResult.ValidatedRequest.Subject,
            Lifetime = validationResult.ValidatedRequest.Expiry,
            AuthenticationContextReferenceClasses = validationResult.ValidatedRequest.AuthenticationContextReferenceClasses,
            Tenant         = validationResult.ValidatedRequest.Tenant,
            IdP            = validationResult.ValidatedRequest.IdP,
            BindingMessage = validationResult.ValidatedRequest.BindingMessage,
        };

        var requestId = await BackChannelAuthenticationRequestStore.CreateRequestAsync(request);

        var interval = validationResult.ValidatedRequest.Client.PollingInterval ?? Options.Ciba.DefaultPollingInterval;
        var response = new BackchannelAuthenticationResponse()
        {
            AuthenticationRequestId = requestId,
            ExpiresIn = request.Lifetime,
            Interval  = interval,
        };

        await UserLoginService.SendLoginRequestAsync(new BackchannelUserLoginRequest
        {
            InternalId                            = request.InternalId,
            Subject                               = validationResult.ValidatedRequest.Subject,
            Client                                = validationResult.ValidatedRequest.Client,
            ValidatedResources                    = validationResult.ValidatedRequest.ValidatedResources,
            RequestedResourceIndicators           = validationResult.ValidatedRequest.RequestedResourceIndiators,
            BindingMessage                        = validationResult.ValidatedRequest.BindingMessage,
            AuthenticationContextReferenceClasses = validationResult.ValidatedRequest.AuthenticationContextReferenceClasses,
            Tenant                                = validationResult.ValidatedRequest.Tenant,
            IdP = validationResult.ValidatedRequest.IdP,
        });

        return(response);
    }
Ejemplo n.º 6
0
    public Task UpdateByInternalIdAsync(string id, BackChannelAuthenticationRequest request)
    {
        var item = Items.SingleOrDefault(x => x.Value.InternalId == id);

        if (item.Key != null)
        {
            Items.Remove(item.Key);
            Items.Add(item.Key, request);
        }
        return(Task.CompletedTask);
    }
    public async Task CompleteLoginRequestAsync_should_require_request_object()
    {
        _mockUserSession.User = new IdentityServerUser("123").CreatePrincipal();
        var req = new BackChannelAuthenticationRequest
        {
            ClientId        = _client.ClientId,
            Subject         = new IdentityServerUser("123").CreatePrincipal(),
            RequestedScopes = new[] { "scope1", "scope2", "scope3" },
        };
        var requestId = await _mockStore.CreateRequestAsync(req);

        Func <Task> f = async() => await _subject.CompleteLoginRequestAsync(null);

        f.Should().Throw <ArgumentNullException>();
    }
    /// <inheritdoc/>
    public async Task <bool> ShouldSlowDown(string requestId, BackChannelAuthenticationRequest details)
    {
        using var activity = Tracing.ServiceActivitySource.StartActivity("DistributedBackchannelAuthenticationThrottlingService.ShouldSlowDown");

        if (requestId == null)
        {
            throw new ArgumentNullException(nameof(requestId));
        }

        var key     = KeyPrefix + requestId;
        var options = new DistributedCacheEntryOptions {
            AbsoluteExpiration = _clock.UtcNow.AddSeconds(details.Lifetime)
        };

        var lastSeenAsString = await _cache.GetStringAsync(key);

        // record new
        if (lastSeenAsString == null)
        {
            await _cache.SetStringAsync(key, _clock.UtcNow.ToString("O"), options);

            return(false);
        }

        // check interval
        if (DateTime.TryParse(lastSeenAsString, out var lastSeen))
        {
            lastSeen = lastSeen.ToUniversalTime();

            var client = await _clientStore.FindEnabledClientByIdAsync(details.ClientId);

            var interval = client?.PollingInterval ?? _options.Ciba.DefaultPollingInterval;
            if (_clock.UtcNow.UtcDateTime < lastSeen.AddSeconds(interval))
            {
                await _cache.SetStringAsync(key, _clock.UtcNow.ToString("O"), options);

                return(true);
            }
        }

        // store current and continue
        await _cache.SetStringAsync(key, _clock.UtcNow.ToString("O"), options);

        return(false);
    }
    public async Task GetLoginRequestByInternalIdAsync_should_return_correct_item()
    {
        _mockUserSession.User = new IdentityServerUser("123").CreatePrincipal();
        var req = new BackChannelAuthenticationRequest
        {
            ClientId = _client.ClientId,
            Subject  = new IdentityServerUser("123").CreatePrincipal(),
        };
        var requestId = await _mockStore.CreateRequestAsync(req);

        await _mockStore.CreateRequestAsync(new BackChannelAuthenticationRequest
        {
            ClientId = _client.ClientId,
            Subject  = new IdentityServerUser("other").CreatePrincipal()
        });

        var result = await _subject.GetLoginRequestByInternalIdAsync(req.InternalId);

        result.InternalId.Should().Be(req.InternalId);
    }
    public async Task GetPendingLoginRequestsForCurrentUserAsync_should_use_current_sub_to_filter_results()
    {
        _mockUserSession.User = new IdentityServerUser("123").CreatePrincipal();
        var req = new BackChannelAuthenticationRequest
        {
            ClientId = _client.ClientId,
            Subject  = new IdentityServerUser("123").CreatePrincipal(),
        };
        await _mockStore.CreateRequestAsync(req);

        await _mockStore.CreateRequestAsync(new BackChannelAuthenticationRequest
        {
            ClientId = _client.ClientId,
            Subject  = new IdentityServerUser("other").CreatePrincipal()
        });

        var results = await _subject.GetPendingLoginRequestsForCurrentUserAsync();

        results.Count().Should().Be(1);
        results.First().InternalId.Should().Be(req.InternalId);
    }
    public async Task CompleteLoginRequestAsync_for_valid_request_should_mark_login_request_complete()
    {
        _mockUserSession.User = new IdentityServerUser("123").CreatePrincipal();
        var req = new BackChannelAuthenticationRequest
        {
            ClientId        = _client.ClientId,
            Subject         = new IdentityServerUser("123").CreatePrincipal(),
            RequestedScopes = new[] { "scope1", "scope2", "scope3" },
        };
        var requestId = await _mockStore.CreateRequestAsync(req);

        await _subject.CompleteLoginRequestAsync(new CompleteBackchannelLoginRequest(req.InternalId)
        {
            Description           = "desc",
            ScopesValuesConsented = new string[] { "scope1", "scope2" },
            SessionId             = "sid",
            Subject = new IdentityServerUser("123")
            {
                DisplayName           = "name",
                AuthenticationTime    = new DateTime(2000, 02, 03, 8, 15, 00, DateTimeKind.Utc),
                IdentityProvider      = "idp",
                AdditionalClaims      = { new Claim("foo", "bar") },
                AuthenticationMethods = { "phone", "pin" }
            }.CreatePrincipal()
        });

        var item = _mockStore.Items[requestId];

        item.IsComplete.Should().BeTrue();
        item.Description.Should().Be("desc");
        item.SessionId.Should().Be("sid");
        item.AuthorizedScopes.Should().BeEquivalentTo(new[] { "scope2", "scope1" });

        item.Subject.HasClaim("sub", "123").Should().BeTrue();
        item.Subject.HasClaim("foo", "bar").Should().BeTrue();
        item.Subject.HasClaim("amr", "phone").Should().BeTrue();
        item.Subject.HasClaim("amr", "pin").Should().BeTrue();
        item.Subject.HasClaim("idp", "idp").Should().BeTrue();
        item.Subject.HasClaim("auth_time", new DateTimeOffset(new DateTime(2000, 02, 03, 8, 15, 00, DateTimeKind.Utc)).ToUnixTimeSeconds().ToString()).Should().BeTrue();
    }