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); }
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(); }
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"); }
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(); }
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"); }
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"); }
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(); }
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"); }
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); }
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); }