예제 #1
0
        public void ProcessAsync_should_throw_if_incorrect_sub_issued_by_profile_service()
        {
            _identityResources.Add(new IdentityResource("id1", new[] { "foo" }));
            _identityResources.Add(new IdentityResource("id2", new[] { "bar" }));
            _mockProfileService.ProfileClaims = new[]
            {
                new Claim("sub", "fred")
            };

            var result = new UserInfoRequestValidationResult
            {
                Subject = _user,
                TokenValidationResult = new TokenValidationResult
                {
                    Claims = new List <Claim>
                    {
                        { new Claim("scope", "id1") },
                        { new Claim("scope", "id2") },
                        { new Claim("scope", "id3") }
                    },
                    Client = _client
                }
            };

            Func <Task> act = () => _subject.ProcessAsync(result);

            act.Should().Throw <InvalidOperationException>()
            .And.Message.Should().Contain("subject");
        }
예제 #2
0
        public async Task ProcessAsync_should_call_profile_service_with_requested_claim_types()
        {
            _identityResources.Add(new IdentityResource("id1", new[] { "foo" }));
            _identityResources.Add(new IdentityResource("id2", new[] { "bar" }));

            var result = new UserInfoRequestValidationResult
            {
                Subject = _user,
                TokenValidationResult = new TokenValidationResult
                {
                    Claims = new List <Claim>
                    {
                        { new Claim("scope", "id1") },
                        { new Claim("scope", "id2") },
                        { new Claim("scope", "id3") }
                    },
                    Client = _client
                }
            };

            var claims = await _subject.ProcessAsync(result);

            _mockProfileService.GetProfileWasCalled.Should().BeTrue();
            _mockProfileService.ProfileContext.RequestedClaimTypes.Should().BeEquivalentTo(new[] { "foo", "bar" });
        }
예제 #3
0
        public async Task ProcessAsync_should_return_sub_from_user()
        {
            _identityResources.Add(new IdentityResource("id1", new[] { "foo" }));
            _identityResources.Add(new IdentityResource("id2", new[] { "bar" }));

            var result = new UserInfoRequestValidationResult
            {
                Subject = _user,
                TokenValidationResult = new TokenValidationResult
                {
                    Claims = new List <Claim>
                    {
                        { new Claim("scope", "id1") },
                        { new Claim("scope", "id2") },
                        { new Claim("scope", "id3") }
                    },
                    Client = _client
                }
            };

            var claims = await _subject.ProcessAsync(result);

            claims.Should().ContainKey("sub");
            claims["sub"].Should().Be("bob");
        }
예제 #4
0
        public async Task ProcessAsync_should_return_claims_issued_by_profile_service()
        {
            _identityResources.Add(new IdentityResource("id1", new[] { "foo" }));
            _identityResources.Add(new IdentityResource("id2", new[] { "bar" }));
            _mockProfileService.ProfileClaims = new[]
            {
                new Claim("email", "*****@*****.**"),
                new Claim("name", "fred jones")
            };

            var result = new UserInfoRequestValidationResult
            {
                Subject = _user,
                TokenValidationResult = new TokenValidationResult
                {
                    Claims = new List <Claim>
                    {
                        { new Claim("scope", "id1") },
                        { new Claim("scope", "id2") },
                        { new Claim("scope", "id3") }
                    },
                    Client = _client
                }
            };

            var claims = await _subject.ProcessAsync(result);

            claims.Should().ContainKey("email");
            claims["email"].Should().Be("*****@*****.**");
            claims.Should().ContainKey("name");
            claims["name"].Should().Be("fred jones");
        }
    /// <summary>
    /// Creates the response.
    /// </summary>
    /// <param name="validationResult">The userinfo request validation result.</param>
    /// <returns></returns>
    /// <exception cref="System.InvalidOperationException">Profile service returned incorrect subject value</exception>
    public virtual async Task <Dictionary <string, object> > ProcessAsync(UserInfoRequestValidationResult validationResult)
    {
        using var activity = Tracing.BasicActivitySource.StartActivity("UserInfoResponseGenerator.Process");

        Logger.LogDebug("Creating userinfo response");

        // extract scopes and turn into requested claim types
        var scopes = validationResult.TokenValidationResult.Claims.Where(c => c.Type == JwtClaimTypes.Scope).Select(c => c.Value);

        var validatedResources = await GetRequestedResourcesAsync(scopes);

        var requestedClaimTypes = await GetRequestedClaimTypesAsync(validatedResources);

        Logger.LogDebug("Requested claim types: {claimTypes}", requestedClaimTypes.ToSpaceSeparatedString());

        // call profile service
        var context = new ProfileDataRequestContext(
            validationResult.Subject,
            validationResult.TokenValidationResult.Client,
            IdentityServerConstants.ProfileDataCallers.UserInfoEndpoint,
            requestedClaimTypes);

        context.RequestedResources = validatedResources;

        await Profile.GetProfileDataAsync(context);

        var profileClaims = context.IssuedClaims;

        // construct outgoing claims
        var outgoingClaims = new List <Claim>();

        if (profileClaims == null)
        {
            Logger.LogInformation("Profile service returned no claims (null)");
        }
        else
        {
            outgoingClaims.AddRange(profileClaims);
            Logger.LogInformation("Profile service returned the following claim types: {types}", profileClaims.Select(c => c.Type).ToSpaceSeparatedString());
        }

        var subClaim = outgoingClaims.SingleOrDefault(x => x.Type == JwtClaimTypes.Subject);

        if (subClaim == null)
        {
            outgoingClaims.Add(new Claim(JwtClaimTypes.Subject, validationResult.Subject.GetSubjectId()));
        }
        else if (subClaim.Value != validationResult.Subject.GetSubjectId())
        {
            Logger.LogError("Profile service returned incorrect subject value: {sub}", subClaim);
            throw new InvalidOperationException("Profile service returned incorrect subject value");
        }

        return(outgoingClaims.ToClaimsDictionary());
    }
    public async Task ProcessAsync_should_return_claims_issued_by_profile_service()
    {
        _identityResources.Add(new IdentityResource("id1", new[] { "foo" }));
        _identityResources.Add(new IdentityResource("id2", new[] { "bar" }));

        var address = new
        {
            street_address = "One Hacker Way",
            locality       = "Heidelberg",
            postal_code    = 69118,
            country        = "Germany"
        };

        _mockProfileService.ProfileClaims = new[]
        {
            new Claim("email", "*****@*****.**"),
            new Claim("name", "fred jones"),
            new Claim("address", @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }", IdentityServerConstants.ClaimValueTypes.Json),
            new Claim("address2", JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json)
        };

        var result = new UserInfoRequestValidationResult
        {
            Subject = _user,
            TokenValidationResult = new TokenValidationResult
            {
                Claims = new List <Claim>
                {
                    { new Claim("scope", "id1") },
                    { new Claim("scope", "id2") },
                    { new Claim("scope", "id3") }
                },
                Client = _client
            }
        };

        var claims = await _subject.ProcessAsync(result);

        claims.Should().ContainKey("email");
        claims["email"].Should().Be("*****@*****.**");
        claims.Should().ContainKey("name");
        claims["name"].Should().Be("fred jones");

        // this will be treated as a string because this is not valid JSON from the System.Text library point of view
        claims.Should().ContainKey("address");
        claims["address"].Should().Be("{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }");

        // this is a JsonElement
        claims.Should().ContainKey("address2");
        claims["address2"].ToString().Should().Be("{\"street_address\":\"One Hacker Way\",\"locality\":\"Heidelberg\",\"postal_code\":69118,\"country\":\"Germany\"}");
    }
 public override Task <Dictionary <string, object> > ProcessAsync(UserInfoRequestValidationResult validationResult)
 {
     return(base.ProcessAsync(validationResult));
 }