示例#1
0
        public async Task Request_with_response_type_code_supported()
        {
            await _mockPipeline.LoginAsync("bob");

            var metadata = await _mockPipeline.BackChannelClient.GetAsync(IdentityServerPipeline.DiscoveryEndpoint);

            metadata.StatusCode.Should().Be(HttpStatusCode.OK);

            var state = Guid.NewGuid().ToString();
            var nonce = Guid.NewGuid().ToString();

            var url = _mockPipeline.CreateAuthorizeUrl(
                clientId: "code_client",
                responseType: "code",
                scope: "openid",
                redirectUri: "https://code_client/callback",
                state: state,
                nonce: nonce);
            var response = await _mockPipeline.BrowserClient.GetAsync(url);

            response.StatusCode.Should().Be(HttpStatusCode.Found);

            var authorization = new IdentityModel.Client.AuthorizeResponse(response.Headers.Location.ToString());

            authorization.IsError.Should().BeFalse();
            authorization.Code.Should().NotBeNull();
            authorization.State.Should().Be(state);
        }
示例#2
0
        public async Task get_request_should_redirect_to_configured_logout_path()
        {
            _mockPipeline.Options.UserInteraction.LogoutUrl         = "/logout";
            _mockPipeline.Options.UserInteraction.LogoutIdParameter = "id";

            await _mockPipeline.LoginAsync("bob");

            var url = _mockPipeline.CreateAuthorizeUrl(
                clientId: "client1",
                responseType: "id_token",
                scope: "openid",
                redirectUri: "https://client1/callback",
                state: "123_state",
                nonce: "123_nonce");

            _mockPipeline.BrowserClient.AllowAutoRedirect = false;
            var response = await _mockPipeline.BrowserClient.GetAsync(url);

            var authorization = new IdentityModel.Client.AuthorizeResponse(response.Headers.Location.ToString());
            var id_token      = authorization.IdentityToken;

            response = await _mockPipeline.BrowserClient.GetAsync(IdentityServerPipeline.EndSessionEndpoint +
                                                                  "?id_token_hint=" + id_token +
                                                                  "&post_logout_redirect_uri=https://client1/signout-callback");

            response.StatusCode.Should().Be(HttpStatusCode.Redirect);
            response.Headers.Location.ToString().Should().StartWith("https://server/logout?id=");
        }
        public async Task Anonymous_user_with_valid_request_should_receive_authorization_response()
        {
            var url = _mockPipeline.CreateAuthorizeUrl(
                clientId: "client4",
                responseType: "code",
                scope: "openid",
                redirectUri: "https://client4/callback",
                state: "123_state",
                nonce: "123_nonce",
                acrValues: "0",
                responseMode: "json");
            var response = await _mockPipeline.BrowserClient.GetAsync(url);

            var result = JObject.Parse(await response.Content.ReadAsStringAsync());

            var tokenResponse = await _mockPipeline.BrowserClient.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest()
            {
                Code        = (string)result["code"],
                RedirectUri = "https://client4/callback",
                Address     = IdentityServerPipeline.TokenEndpoint,
                ClientId    = "client4",
            });

            tokenResponse.IsError.Should().BeFalse();
            tokenResponse.AccessToken.Should().NotBeNull();
            tokenResponse.IdentityToken.Should().NotBeNull();
        }
示例#4
0
        public async Task No_state_should_not_result_in_shash()
        {
            await _pipeline.LoginAsync("bob");

            var nonce = Guid.NewGuid().ToString();

            _pipeline.BrowserClient.AllowAutoRedirect = false;
            var url = _pipeline.CreateAuthorizeUrl(
                clientId: "code_pipeline.Client",
                responseType: "code",
                scope: "openid",
                redirectUri: "https://code_pipeline.Client/callback?foo=bar&baz=quux",
                nonce: nonce);
            var response = await _pipeline.BrowserClient.GetAsync(url);

            var authorization = _pipeline.ParseAuthorizationResponseUrl(response.Headers.Location.ToString());

            authorization.Code.Should().NotBeNull();

            var code = authorization.Code;

            // backchannel client
            var wrapper     = new MessageHandlerWrapper(_pipeline.Handler);
            var tokenClient = new HttpClient(wrapper);
            var tokenResult = await tokenClient.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest
            {
                Address      = IdentityServerPipeline.TokenEndpoint,
                ClientId     = "code_pipeline.Client",
                ClientSecret = "secret",

                Code        = code,
                RedirectUri = "https://code_pipeline.Client/callback?foo=bar&baz=quux"
            });

            tokenResult.IsError.Should().BeFalse();
            tokenResult.HttpErrorReason.Should().Be("OK");
            tokenResult.TokenType.Should().Be("Bearer");
            tokenResult.AccessToken.Should().NotBeNull();
            tokenResult.ExpiresIn.Should().BeGreaterThan(0);
            tokenResult.IdentityToken.Should().NotBeNull();

            var token = new JwtSecurityToken(tokenResult.IdentityToken);

            token.Claims.Count().Should().Be(12);
            var s_hash = token.Claims.FirstOrDefault(c => c.Type == "s_hash");

            s_hash.Should().BeNull();
        }
        public async Task custom_profile_should_return_claims_for_implicit_client()
        {
            await _mockPipeline.LoginAsync("bob");

            var url = _mockPipeline.CreateAuthorizeUrl(
                clientId: "implicit",
                responseType: "id_token",
                scope: "openid custom_identity",
                redirectUri: "https://client/callback",
                state: "state",
                nonce: "nonce");

            _mockPipeline.BrowserClient.AllowAutoRedirect = false;
            var response = await _mockPipeline.BrowserClient.GetAsync(url);

            response.StatusCode.Should().Be(HttpStatusCode.Redirect);
            response.Headers.Location.ToString().Should().StartWith("https://client/callback");

            var authorization = new IdentityModel.Client.AuthorizeResponse(response.Headers.Location.ToString());

            authorization.IsError.Should().BeFalse();
            authorization.IdentityToken.Should().NotBeNull();

            var payload = authorization.IdentityToken.Split('.')[1];
            var json    = Encoding.UTF8.GetString(Base64Url.Decode(payload));
            var obj     = JObject.Parse(json);

            obj.GetValue("foo").Should().NotBeNull();
            obj["foo"].ToString().Should().Be("bar");
        }
示例#6
0
        public async Task client_requires_consent_should_show_consent_page()
        {
            await _mockPipeline.LoginAsync("bob");

            var url = _mockPipeline.CreateAuthorizeUrl(
                clientId: "client2",
                responseType: "id_token",
                scope: "openid",
                redirectUri: "https://client2/callback",
                state: "123_state",
                nonce: "123_nonce"
                );
            var response = await _mockPipeline.BrowserClient.GetAsync(url);

            _mockPipeline.ConsentWasCalled.Should().BeTrue();
        }
示例#7
0
    public async Task Token_endpoint_supports_client_authentication_with_basic_authentication_with_POST()
    {
        await _pipeline.LoginAsync("bob");

        var nonce = Guid.NewGuid().ToString();

        _pipeline.BrowserClient.AllowAutoRedirect = false;
        var url = _pipeline.CreateAuthorizeUrl(
            clientId: "code_pipeline.Client",
            responseType: "code",
            scope: "openid",
            redirectUri: "https://code_pipeline.Client/callback?foo=bar&baz=quux",
            nonce: nonce);
        var response = await _pipeline.BrowserClient.GetAsync(url);

        var authorization = _pipeline.ParseAuthorizationResponseUrl(response.Headers.Location.ToString());

        authorization.Code.Should().NotBeNull();

        var code = authorization.Code;

        // backchannel client
        var wrapper     = new MessageHandlerWrapper(_pipeline.Handler);
        var tokenClient = new HttpClient(wrapper);
        var tokenResult = await tokenClient.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest
        {
            Address      = IdentityServerPipeline.TokenEndpoint,
            ClientId     = "code_pipeline.Client",
            ClientSecret = "secret",

            Code        = code,
            RedirectUri = "https://code_pipeline.Client/callback?foo=bar&baz=quux"
        });

        tokenResult.IsError.Should().BeFalse();
        tokenResult.HttpErrorReason.Should().Be("OK");
        tokenResult.TokenType.Should().Be("Bearer");
        tokenResult.AccessToken.Should().NotBeNull();
        tokenResult.ExpiresIn.Should().BeGreaterThan(0);
        tokenResult.IdentityToken.Should().NotBeNull();

        wrapper.Response.Headers.CacheControl.NoCache.Should().BeTrue();
        wrapper.Response.Headers.CacheControl.NoStore.Should().BeTrue();
    }
        public async Task Reject_redirect_uri_not_matching_registered_redirect_uri()
        {
            await _mockPipeline.LoginAsync("bob");

            var nonce = Guid.NewGuid().ToString();
            var state = Guid.NewGuid().ToString();

            var url = _mockPipeline.CreateAuthorizeUrl(
                clientId: "code_client",
                responseType: "code",
                scope: "openid",
                redirectUri: "https://bad",
                state: state,
                nonce: nonce);
            var response = await _mockPipeline.BrowserClient.GetAsync(url);

            _mockPipeline.ErrorWasCalled.Should().BeTrue();
            _mockPipeline.ErrorMessage.Error.Should().Be("invalid_request");
        }
示例#9
0
        public async Task malformed_clientId_should_be_handled_correctly()
        {
            await _mockPipeline.LoginAsync("bob");

            _mockPipeline.BrowserClient.AllowAutoRedirect = false;

            var url = _mockPipeline.CreateAuthorizeUrl(
                clientId: "client1}",
                responseType: "id_token",
                responseMode: "form_post",
                scope: "openid",
                redirectUri: "https://client1/callback",
                state: "123_state",
                nonce: "123_nonce");
            var response = await _mockPipeline.BrowserClient.GetAsync(url);

            response.StatusCode.Should().Be(HttpStatusCode.Redirect);
            response.Headers.Location.ToString().Should().StartWith("https://server/home/error");
        }
示例#10
0
        public async Task no_resource_indicator_on_code_exchange_should_succeed()
        {
            await _mockPipeline.LoginAsync("bob");

            _mockPipeline.BrowserClient.AllowAutoRedirect = false;

            var url = _mockPipeline.CreateAuthorizeUrl(
                clientId: "client1",
                responseType: "code",
                scope: "openid profile scope1 scope2 scope3 scope4 offline_access",
                redirectUri: "https://client1/callback");

            url += "&resource=urn:resource1";
            url += "&resource=urn:resource3";

            var response = await _mockPipeline.BrowserClient.GetAsync(url);

            var code = GetCode(response);

            var tokenResponse = await _mockPipeline.BackChannelClient.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest
            {
                Address      = IdentityServerPipeline.TokenEndpoint,
                ClientId     = "client1",
                ClientSecret = "secret",
                Code         = code,
                RedirectUri  = "https://client1/callback"
            });

            {
                var claims = ParseAccessTokenClaims(tokenResponse);
                claims.Where(x => x.Type == "aud").Select(x => x.Value).Should().BeEquivalentTo(new[] { "urn:resource1", "urn:resource2" });
                claims.Where(x => x.Type == "scope").Select(x => x.Value).Should().BeEquivalentTo(new[] { "openid", "profile", "scope1", "scope2", "scope3", "scope4", "offline_access" });
            }
        }
        public async Task Unrestricted_implicit_client_can_request_IdToken()
        {
            await _mockPipeline.LoginAsync(_user);

            var url = _mockPipeline.CreateAuthorizeUrl("client1",
                                                       "id_token", "openid", "https://client1/callback", "state", "nonce");

            _mockPipeline.BrowserClient.AllowAutoRedirect = false;
            var response = await _mockPipeline.BrowserClient.GetAsync(url);

            response.StatusCode.Should().Be(HttpStatusCode.Found);
            response.Headers.Location.AbsoluteUri.Should().StartWith("https://client1/callback");
            var authorization = new IdentityModel.Client.AuthorizeResponse(response.Headers.Location.ToString());

            authorization.IdentityToken.Should().NotBeNull();
            authorization.AccessToken.Should().BeNull();
        }
示例#12
0
        public async Task anonymous_user_should_be_redirected_to_login_page()
        {
            var url = _mockPipeline.CreateAuthorizeUrl(
                clientId: "client1",
                responseType: "id_token",
                scope: "openid",
                redirectUri: "https://client1/callback",
                state: "123_state",
                nonce: "123_nonce");
            var response = await _mockPipeline.BrowserClient.GetAsync(url);

            _mockPipeline.LoginWasCalled.Should().BeTrue();
        }
        public async Task missing_request_object_should_fail()
        {
            var url = _mockPipeline.CreateAuthorizeUrl(
                clientId: _client.ClientId,
                responseType: "id_token",
                scope: "openid profile",
                state: "123state",
                nonce: "123nonce",
                redirectUri: "https://client/callback");

            var response = await _mockPipeline.BrowserClient.GetAsync(url);

            _mockPipeline.ErrorMessage.Error.Should().Be("invalid_request");
            _mockPipeline.ErrorMessage.ErrorDescription.Should().Be("Client must use request object, but no request or request_uri parameter present");
            _mockPipeline.LoginRequest.Should().BeNull();
        }
        public async Task authorize_should_accept_valid_JWT_request_object_parameters_using_X509_certificate()
        {
            var requestJwt = CreateRequestJwt(
                issuer: _client.ClientId,
                audience: IdentityServerPipeline.BaseUrl,
                credential: new X509SigningCredentials(TestCert.Load()),
                claims: new[] {
                new Claim("client_id", _client.ClientId),
                new Claim("response_type", "id_token"),
                new Claim("scope", "openid profile"),
                new Claim("state", "123state"),
                new Claim("nonce", "123nonce"),
                new Claim("redirect_uri", "https://client/callback"),
                new Claim("acr_values", "acr_1 acr_2 tenant:tenant_value idp:idp_value"),
                new Claim("login_hint", "login_hint_value"),
                new Claim("display", "popup"),
                new Claim("ui_locales", "ui_locale_value"),
                new Claim("foo", "123foo"),
            });

            var url = _mockPipeline.CreateAuthorizeUrl(
                clientId: _client.ClientId,
                responseType: "id_token",
                extra: new
            {
                request = requestJwt
            });
            var response = await _mockPipeline.BrowserClient.GetAsync(url);

            _mockPipeline.LoginRequest.Should().NotBeNull();
            _mockPipeline.LoginRequest.ClientId.Should().Be(_client.ClientId);
            _mockPipeline.LoginRequest.DisplayMode.Should().Be("popup");
            _mockPipeline.LoginRequest.UiLocales.Should().Be("ui_locale_value");
            _mockPipeline.LoginRequest.IdP.Should().Be("idp_value");
            _mockPipeline.LoginRequest.Tenant.Should().Be("tenant_value");
            _mockPipeline.LoginRequest.LoginHint.Should().Be("login_hint_value");
            _mockPipeline.LoginRequest.AcrValues.Should().BeEquivalentTo(new string[] { "acr_2", "acr_1" });

            _mockPipeline.LoginRequest.Parameters.AllKeys.Should().Contain("foo");
            _mockPipeline.LoginRequest.Parameters["foo"].Should().Be("123foo");

            _mockPipeline.LoginRequest.RequestObjectValues.Count.Should().Be(11);
            _mockPipeline.LoginRequest.RequestObjectValues.Should().ContainKey("foo");
            _mockPipeline.LoginRequest.RequestObjectValues["foo"].Should().Be("123foo");
        }
示例#15
0
        public async Task Shared_session_id_should_be_included_in_anonymous_access_token_always()
        {
            var url = _mockPipeline.CreateAuthorizeUrl(
                clientId: "client2",
                responseType: "id_token token",
                scope: "openid api2",
                redirectUri: "https://client2/callback",
                state: "123_state",
                nonce: "123_nonce",
                acrValues: "0",
                responseMode: "json");
            var response = await _mockPipeline.BrowserClient.GetAsync(url);

            var result = JObject.Parse(await response.Content.ReadAsStringAsync());
            var token  = _mockPipeline.ReadJwtToken(((string)result["access_token"]));

            token.Claims.Should().Contain(c => c.Type == JwtClaimTypes.SharedSessionId);
        }
示例#16
0
        public async Task Shared_session_id_should_be_included_in_anonymous_access_token_always()
        {
            var url = _mockPipeline.CreateAuthorizeUrl(
                clientId: "client4",
                responseType: "code",
                scope: "openid",
                redirectUri: "https://client4/callback",
                state: "123_state",
                nonce: "123_nonce",
                acrValues: "0",
                responseMode: "json");
            var response = await _mockPipeline.BrowserClient.GetAsync(url);

            var result        = JObject.Parse(await response.Content.ReadAsStringAsync());
            var tokenResponse = await _mockPipeline.BrowserClient.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest()
            {
                Code        = (string)result["code"],
                RedirectUri = "https://client4/callback",
                Address     = IdentityServerPipeline.TokenEndpoint,
                ClientId    = "client4",
            });

            var token = _mockPipeline.ReadJwtToken(tokenResponse.AccessToken);

            token.Claims.Should().Contain(c => c.Type == JwtClaimTypes.SharedSessionId);
        }