public async Task When_Registering_A_Client_Then_No_Exception_Is_Thrown() { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("stateless_client", "stateless_client"), _server.Client, new Uri($"{BaseUrl}/.well-known/openid-configuration")); var grantedToken = await tokenClient.GetToken(TokenRequest.FromScopes("manager")).ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; var registrationClient = await ManagementClient.Create( _server.Client, new Uri($"{BaseUrl}/.well-known/openid-configuration")) .ConfigureAwait(false); var client = await registrationClient.Register( new Client { JsonWebKeys = TestKeys.SecretKey.CreateSignatureJwk().ToSet(), AllowedScopes = new[] { "openid" }, ClientName = "Test", ClientId = "id", RedirectionUrls = new[] { new Uri("https://localhost"), }, RequestUris = new[] { new Uri("https://localhost") }, }, grantedToken.Item.AccessToken) .ConfigureAwait(false) as Option <Client> .Result; Assert.NotNull(client); }
public async Task When_Empty_Json_Request_Is_Passed_To_Registration_Api_Then_Error_Is_Returned() { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("stateless_client", "stateless_client"), _server.Client, new Uri($"{BaseUrl}/.well-known/openid-configuration")); var grantedToken = await tokenClient.GetToken(TokenRequest.FromScopes("register_client")) .ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; var obj = new { fake = "fake" }; var fakeJson = JsonConvert.SerializeObject( obj, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); var httpRequest = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = new Uri($"{BaseUrl}/clients"), Content = new StringContent(fakeJson) }; httpRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); httpRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", grantedToken.Item.AccessToken); var httpResult = await _server.Client().SendAsync(httpRequest).ConfigureAwait(false); Assert.Equal(HttpStatusCode.BadRequest, httpResult.StatusCode); }
public void SuccessfulMultiplePermissionsCreation() { GrantedTokenResponse grantedToken = null !; UmaClient client = null !; string resourceId = null !; string ticketId = null !; "and a valid UMA token".x( async() => { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("clientCredentials", "clientCredentials"), Fixture.Client, new Uri(WellKnownUmaConfiguration)); var token = await tokenClient.GetToken(TokenRequest.FromScopes("uma_protection")) .ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; grantedToken = token !.Item; Assert.NotNull(grantedToken); }); "and a properly configured uma client".x( () => client = new UmaClient(Fixture.Client, new Uri(WellKnownUmaConfiguration))); "when registering resource".x( async() => { var resource = await client.AddResource( new ResourceSet { Name = "picture", Scopes = new[] { "read", "write" } }, grantedToken.AccessToken) .ConfigureAwait(false) as Option <AddResourceSetResponse> .Result; resourceId = resource !.Item.Id; Assert.NotNull(resourceId); }); "and adding permission".x( async() => { var response = await client.RequestPermission( grantedToken.AccessToken, CancellationToken.None, new PermissionRequest { ResourceSetId = resourceId, Scopes = new[] { "write" } }, new PermissionRequest { ResourceSetId = resourceId, Scopes = new[] { "read" } }) .ConfigureAwait(false) as Option <TicketResponse> .Result; ticketId = response !.Item.TicketId; Assert.NotNull(ticketId); }); "then returns ticket id".x(() => { Assert.NotNull(ticketId); }); }
public void SuccessfulPermissionCreation() { GrantedTokenResponse grantedToken = null !; UmaClient client = null !; JsonWebKeySet jwks = null !; string resourceId = null !; string ticketId = null !; "and the server's signing key".x( async() => { var json = await _fixture.Client().GetStringAsync(BaseUrl + "/jwks").ConfigureAwait(false); jwks = new JsonWebKeySet(json); Assert.NotEmpty(jwks.Keys); }); "and a valid UMA token".x( async() => { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("clientCredentials", "clientCredentials"), _fixture.Client, new Uri(WellKnownUmaConfiguration)); var token = await tokenClient.GetToken(TokenRequest.FromScopes("uma_protection")) .ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; grantedToken = token !.Item; }); "and a properly configured uma client".x( () => client = new UmaClient(_fixture.Client, new Uri(WellKnownUmaConfiguration))); "when registering resource".x( async() => { var resource = await client.AddResource( new ResourceSet { Name = "picture", Scopes = new[] { "read" } }, grantedToken.AccessToken) .ConfigureAwait(false) as Option <AddResourceSetResponse> .Result; resourceId = resource.Item.Id; }); "and adding permission".x( async() => { var response = await client.RequestPermission( grantedToken.AccessToken, requests: new PermissionRequest { ResourceSetId = resourceId, Scopes = new[] { "read" } }) .ConfigureAwait(false) as Option <TicketResponse> .Result; ticketId = response !.Item.TicketId; }); "then returns ticket id".x(() => { Assert.NotNull(ticketId); }); }
/// <summary> /// 获取一个Token /// </summary> /// <returns></returns> private byte[] GetToken(bool checkExpire = true) { if (checkExpire && _tokenUtil.IsTokenExipre()) { CloseToken(); InitToken(); } return(Serializer.Serialize(_tokenUtil.GetToken())); }
public async Task When_Using_ClientCredentials_Grant_Type_Then_AccessToken_Is_Returned() { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("resource_server", "resource_server"), _server.Client, new Uri(BaseUrl + WellKnownUma2Configuration)); var result = await tokenClient.GetToken(TokenRequest.FromScopes("uma_protection", "uma_authorization")) .ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; Assert.NotEmpty(result.Item.AccessToken); }
public async Task WhenPassingClientAccessTokenToUserInfoThenClientClaimsAreReturned() { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("stateless_client", "stateless_client"), _server.Client, new Uri(BaseUrl + WellKnownOpenidConfiguration)); var result = await tokenClient.GetToken(TokenRequest.FromScopes("openid")).ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; var getUserInfoResult = await _userInfoClient.GetUserInfo(result.Item.AccessToken).ConfigureAwait(false); Assert.IsType <Option <JwtPayload> .Result>(getUserInfoResult); }
public async Task When_Pass_Access_Token_Then_Jwe_Is_Returned() { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("client_userinfo_enc_rsa15", "client_userinfo_enc_rsa15"), _server.Client, new Uri(BaseUrl + WellKnownOpenidConfiguration)); var result = await tokenClient .GetToken(TokenRequest.FromPassword("administrator", "password", new[] { "scim" })) .ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; var getUserInfoResult = await _userInfoClient.GetUserInfo(result.Item.AccessToken).ConfigureAwait(false); Assert.IsType <Option <JwtPayload> .Result>(getUserInfoResult); }
public async Task When_Ticket_Id_Does_Not_Exist_Then_Error_Is_Returned() { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("resource_server", "resource_server"), _server.Client, new Uri(BaseUrl + WellKnownUma2Configuration)); // Try to get the access token via "ticket_id" grant-type. var token = await tokenClient.GetToken(TokenRequest.FromTicketId("ticket_id", "")).ConfigureAwait(false) as Option <GrantedTokenResponse> .Error; Assert.Equal(ErrorCodes.InvalidGrant, token.Details.Title); Assert.Equal(string.Format(Strings.TheTicketDoesntExist, "ticket_id"), token.Details.Detail); }
public async Task When_Pass_Redirect_Uri_With_Fragment_Then_Error_Is_Returned() { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("stateless_client", "stateless_client"), _server.Client, new Uri($"{BaseUrl}/.well-known/openid-configuration")); var grantedToken = await tokenClient.GetToken(TokenRequest.FromScopes("register_client")) .ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; var obj = new { JsonWebKeys = TestKeys.SecretKey.CreateSignatureJwk().ToSet(), AllowedScopes = new[] { "openid" }, RequestUris = new[] { new Uri("https://localhost") }, RedirectionUrls = new[] { new Uri("http://localhost#fragment") }, //LogoUri = "http://google.com", ClientUri = new Uri("https://valid") }; var fakeJson = JsonConvert.SerializeObject( obj, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); var httpRequest = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = new Uri($"{BaseUrl}/registration"), Content = new StringContent(fakeJson) }; httpRequest.Content.Headers.ContentType = new MediaTypeHeaderValue(ApplicationJson); httpRequest.Headers.Authorization = new AuthenticationHeaderValue( grantedToken.Item.TokenType, grantedToken.Item.AccessToken); var httpResult = await _server.SharedCtx.Client().SendAsync(httpRequest).ConfigureAwait(false); //Assert.Equal(HttpStatusCode.OK, httpResult.StatusCode); var json = await httpResult.Content.ReadAsStringAsync().ConfigureAwait(false); var error = JsonConvert.DeserializeObject <ErrorDetails>(json); Assert.Equal("invalid_redirect_uri", error !.Title); Assert.Equal( string.Format(Strings.TheRedirectUrlCannotContainsFragment, "http://localhost/#fragment"), error.Detail); }
public void SuccessfulTokenValidationFromMetadata() { GrantedTokenResponse tokenResponse = null !; JsonWebKeySet jwks = null !; "And a valid token".x( async() => { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("clientCredentials", "clientCredentials"), Fixture.Client, new Uri(WellKnownOpenidConfiguration)); var response = await tokenClient.GetToken(TokenRequest.FromScopes("api1")).ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; Assert.NotNull(response); tokenResponse = response.Item; }); "then can download json web key set".x( async() => { var jwksJson = await Fixture.Client().GetStringAsync(BaseUrl + "/jwks").ConfigureAwait(false); Assert.NotNull(jwksJson); jwks = JsonWebKeySet.Create(jwksJson); }); "Then can create token validation parameters from service metadata".x( () => { var validationParameters = new TokenValidationParameters { IssuerSigningKeys = jwks.Keys, ValidIssuer = "https://localhost", ValidAudience = "clientCredentials" }; var handler = new JwtSecurityTokenHandler(); handler.ValidateToken(tokenResponse.AccessToken, validationParameters, out var securityToken); Assert.NotNull(securityToken); }); }
public async Task CanGetToken() { var client = new TokenClient( TokenCredentials.FromClientCredentials("client", "secret"), () => new HttpClient(), new Uri("http://localhost:8080/.well-known/openid-configuration")); await _fixture.GetUser().ConfigureAwait(false); for (var i = 0; i < 100; i++) { var token = await client.GetToken(TokenRequest.FromPassword("user", "password", new[] { "read" })) .ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; Assert.NotNull(token.Item); } }
public async Task When_Introspecting_AccessToken_Then_Information_Are_Returned() { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("client", "client"), _server.Client, new Uri(BaseUrl + WellKnownOpenidConfiguration)); var result = await tokenClient.GetToken(TokenRequest.FromPassword("administrator", "password", new[] { "scim" })) .ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; var introspection = await tokenClient.Introspect( IntrospectionRequest.Create(result.Item.AccessToken, TokenTypes.AccessToken, "pat")) .ConfigureAwait(false) as Option <OauthIntrospectionResponse> .Result; Assert.Single(introspection.Item.Scope); Assert.Equal("scim", introspection.Item.Scope.First()); }
public async Task WhenPassInvalidRedirectUrisThenErrorIsReturned() { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("stateless_client", "stateless_client"), _server.Client, new Uri($"{BaseUrl}/.well-known/openid-configuration")); var grantedToken = await tokenClient.GetToken(TokenRequest.FromScopes("manager")).ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; var obj = new { allowed_scopes = new[] { "openid" }, request_uris = new[] { new Uri("https://localhost") }, redirect_uris = new[] { "localhost" }, client_uri = new Uri("http://google.com"), tos_uri = new Uri("http://google.com"), jwks = TestKeys.SecretKey.CreateSignatureJwk().ToSet() }; var fakeJson = JsonConvert.SerializeObject( obj, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); var httpRequest = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = new Uri($"{BaseUrl}/clients"), Content = new StringContent(fakeJson) }; httpRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); httpRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", grantedToken.Item.AccessToken); var httpResult = await _server.Client().SendAsync(httpRequest).ConfigureAwait(false); Assert.Equal(HttpStatusCode.BadRequest, httpResult.StatusCode); var json = await httpResult.Content.ReadAsStringAsync().ConfigureAwait(false); var error = JsonConvert.DeserializeObject <ErrorDetails>(json); Assert.Equal(ErrorCodes.InvalidRedirectUri, error !.Title); }
public async Task When_Pass_Invalid_Tos_Uri_Then_Error_Is_Returned() { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("stateless_client", "stateless_client"), _server.Client, new Uri($"{BaseUrl}/.well-known/openid-configuration")); var grantedToken = await tokenClient.GetToken(TokenRequest.FromScopes("register_client")) .ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; var obj = new { AllowedScopes = new[] { "openid" }, RequestUris = new[] { new Uri("https://localhost") }, RedirectionUrls = new[] { new Uri("http://localhost") }, LogoUri = new Uri("http://google.com"), ClientUri = new Uri("https://valid_client_uri"), TosUri = "invalid" }; var fakeJson = JsonConvert.SerializeObject( obj, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); var httpRequest = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = new Uri($"{BaseUrl}/registration"), Content = new StringContent(fakeJson) }; httpRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); httpRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", grantedToken.Item.AccessToken); var httpResult = await _server.Client().SendAsync(httpRequest).ConfigureAwait(false); var json = await httpResult.Content.ReadAsStringAsync().ConfigureAwait(false); var error = JsonConvert.DeserializeObject <ErrorDetails>(json); Assert.Equal("invalid_client_metadata", error !.Title); Assert.Equal("the parameter tos_uri is not correct", error.Detail); }
public async Task When_Revoke_Token_And_Client_Is_Different_Then_Error_Is_Returned() { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("client_userinfo_enc_rsa15", "client_userinfo_enc_rsa15"), _server.Client, new Uri(BaseUrl + WellKnownOpenidConfiguration)); var result = await tokenClient .GetToken(TokenRequest.FromPassword("administrator", "password", new[] { "scim" })) .ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; var revokeClient = new TokenClient( TokenCredentials.FromClientCredentials("client", "client"), _server.Client, new Uri(BaseUrl + WellKnownOpenidConfiguration)); var ex = await revokeClient .RevokeToken(RevokeTokenRequest.Create(result.Item.AccessToken, TokenTypes.AccessToken)) .ConfigureAwait(false) as Option.Error; Assert.Equal("invalid_token", ex.Details.Title); Assert.Equal("The token has not been issued for the given client id 'client'", ex.Details.Detail); }
public async Task When_Revoking_RefreshToken_Then_True_Is_Returned() { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("client", "client"), _server.Client, new Uri(BaseUrl + WellKnownOpenidConfiguration)); var result = await tokenClient .GetToken(TokenRequest.FromPassword("administrator", "password", new[] { "scim", "offline" })) .ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; var revoke = await tokenClient .RevokeToken(RevokeTokenRequest.Create(result.Item.RefreshToken, TokenTypes.RefreshToken)) .ConfigureAwait(false); var introspectClient = new UmaClient(_server.Client, new Uri(BaseUrl + WellKnownOpenidConfiguration)); var ex = await introspectClient.Introspect( IntrospectionRequest.Create(result.Item.RefreshToken, TokenTypes.RefreshToken, "pat")) .ConfigureAwait(false); Assert.IsType <Option.Success>(revoke); Assert.IsType <Option <UmaIntrospectionResponse> .Error>(ex); }
public async Task When_Using_TicketId_Grant_Type_Then_AccessToken_Is_Returned() { var handler = new JwtSecurityTokenHandler(); var set = new JsonWebKeySet(); set.Keys.Add(_server.SharedUmaCtx.SignatureKey); var securityToken = new JwtSecurityToken( "http://server.example.com", "s6BhdRkqt3", new[] { new Claim("sub", "248289761001") }, null, DateTime.UtcNow.AddYears(1), new SigningCredentials(set.GetSignKeys().First(), SecurityAlgorithms.HmacSha256)); var jwt = handler.WriteToken(securityToken); var tc = new TokenClient( TokenCredentials.FromClientCredentials("resource_server", "resource_server"), _server.Client, new Uri(BaseUrl + WellKnownUma2Configuration)); // Get PAT. var result = await tc.GetToken(TokenRequest.FromScopes("uma_protection", "uma_authorization")) .ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; var resourceSet = new ResourceSet { Name = "name", Scopes = new[] { "read", "write", "execute" }, AuthorizationPolicies = new[] { new PolicyRule { ClientIdsAllowed = new[] { "resource_server" }, Scopes = new[] { "read", "write", "execute" } } } }; var resource = await _umaClient.AddResource(resourceSet, result.Item.AccessToken).ConfigureAwait(false) as Option <AddResourceSetResponse> .Result; resourceSet = resourceSet with { Id = resource.Item.Id }; await _umaClient.UpdateResource(resourceSet, result.Item.AccessToken).ConfigureAwait(false); var ticket = await _umaClient.RequestPermission( "header", requests : new PermissionRequest // Add permission & retrieve a ticket id. { ResourceSetId = resource.Item.Id, Scopes = new[] { "read" } }) .ConfigureAwait(false) as Option <TicketResponse> .Result; Assert.NotNull(ticket.Item); var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("resource_server", "resource_server"), _server.Client, new Uri(BaseUrl + WellKnownUma2Configuration)); var token = await tokenClient.GetToken(TokenRequest.FromTicketId(ticket.Item.TicketId, jwt)) .ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; var jwtToken = handler.ReadJwtToken(token.Item.AccessToken); Assert.NotNull(jwtToken.Claims); }
public void ExecuteDeviceAuthorizationFlowWithUserApproval() { const string clientId = "device"; ITokenClient tokenClient = null !; DeviceAuthorizationResponse response = null !; GrantedTokenResponse token = null !; Task <Option <GrantedTokenResponse> > pollingTask = null !; "Given a token client".x( () => { tokenClient = new TokenClient( TokenCredentials.AsDevice(), _fixture.Client, new Uri(WellKnownOpenidConfiguration)); Assert.NotNull(tokenClient); }); "and an access token".x( async() => { var authClient = new TokenClient( TokenCredentials.FromClientCredentials(clientId, "client"), _fixture.Client, new Uri(WellKnownOpenidConfiguration)); var tokenResponse = await authClient.GetToken( TokenRequest.FromPassword("user", "password", new[] { "openid" })) .ConfigureAwait(false); Assert.IsType <Option <GrantedTokenResponse> .Result>(tokenResponse); token = (tokenResponse as Option <GrantedTokenResponse> .Result).Item; }); "When a device requests authorization".x( async() => { var genericResponse = await tokenClient.GetAuthorization(new DeviceAuthorizationRequest(clientId)) .ConfigureAwait(false); Assert.IsType <Option <DeviceAuthorizationResponse> .Result>(genericResponse); response = (genericResponse as Option <DeviceAuthorizationResponse> .Result).Item; }); "and the device polls the token server".x( async() => { pollingTask = tokenClient.GetToken( TokenRequest.FromDeviceCode(clientId, response.DeviceCode, response.Interval)); Assert.False(pollingTask.IsCompleted); }); "and user successfully posts user code".x( async() => { var client = _fixture.Client(); var msg = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = new Uri(response.VerificationUri), Content = new FormUrlEncodedContent( new[] { new KeyValuePair <string, string>("code", response.UserCode) }) }; msg.Headers.Authorization = new AuthenticationHeaderValue(token.TokenType, token.AccessToken); var approval = await client.SendAsync(msg).ConfigureAwait(false); Assert.Equal(HttpStatusCode.OK, approval.StatusCode); }); "then token is returned from polling".x( async() => { var tokenResponse = await pollingTask.ConfigureAwait(false); Assert.IsType <Option <GrantedTokenResponse> .Result>(tokenResponse); }); }
/// <summary> /// Creates the token. /// </summary> /// <returns>Task.</returns> public async Task CreateToken() { await tokenClient.GetToken(new TokenRequest(Username, Password)); }
public async Task <string> Typed([FromServices] TokenClient tokenClient) { return(await tokenClient.GetToken()); }
public void SuccessfulPermissionCreation() { TestServerFixture fixture = null !; GrantedTokenResponse grantedToken = null !; UmaClient client = null !; string resourceId = null !; string ticketId = null !; "Given a running auth server".x(() => fixture = new TestServerFixture(_outputHelper, BaseUrl)) .Teardown(() => fixture.Dispose()); "and the server's signing key".x( async() => { var json = await fixture.Client().GetStringAsync(BaseUrl + "/jwks").ConfigureAwait(false); var jwks = new JsonWebKeySet(json); Assert.NotEmpty(jwks.Keys); }); "and a valid UMA token".x( async() => { var tokenClient = new TokenClient( TokenCredentials.FromClientCredentials("clientCredentials", "clientCredentials"), fixture.Client, new Uri(WellKnownUmaConfiguration)); var token = await tokenClient.GetToken(TokenRequest.FromScopes("uma_protection")) .ConfigureAwait(false) as Option <GrantedTokenResponse> .Result; var handler = new JwtSecurityTokenHandler(); var principal = handler.ReadJwtToken(token.Item.AccessToken); Assert.NotNull(principal.Issuer); grantedToken = token.Item; }); "and a properly configured uma client".x( () => client = new UmaClient(fixture.Client, new Uri(WellKnownUmaConfiguration))); "when registering resource".x( async() => { var resource = await client.AddResource( new ResourceSet { Name = "picture", Scopes = new[] { "read" } }, grantedToken.AccessToken) .ConfigureAwait(false) as Option <AddResourceSetResponse> .Result; resourceId = resource.Item.Id; }); "and adding permission".x( async() => { var response = await client.RequestPermission( grantedToken.AccessToken, requests: new PermissionRequest { IdToken = grantedToken.IdToken, ResourceSetId = resourceId, Scopes = new[] { "read" } }) .ConfigureAwait(false) as Option <TicketResponse> .Result; Assert.NotNull(response); ticketId = response.Item.TicketId; }); "then returns ticket id".x(() => { Assert.NotNull(ticketId); }); }