public static async Task InstanceDiscoveryTestAsync(Sts sts) { SetCredential(sts); var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); AuthenticationResultProxy result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifySuccessResult(sts, result); AuthenticationContextProxy.SetEnvironmentVariable("ExtraQueryParameter", string.Empty); // PROD discovery endpoint knows about PPE as well, so this passes discovery and fails later as refresh token is invalid for PPE. context = new AuthenticationContextProxy(sts.Authority.Replace("windows.net", "windows-ppe.net"), sts.ValidateAuthority); result = await context.AcquireTokenByRefreshTokenAsync(result.RefreshToken, sts.ValidClientId, sts.ValidResource); VerifyErrorResult(result, "invalid_grant", "Refresh Token"); try { context = new AuthenticationContextProxy(sts.Authority.Replace("windows.net", "windows.unknown"), sts.ValidateAuthority); result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifyErrorResult(result, "authority_not_in_valid_list", "authority"); } #if TEST_ADAL_WINPHONE_UNIT catch (AdalServiceException ex) { Verify.AreNotEqual(sts.Type, StsType.ADFS); Verify.AreEqual(ex.ErrorCode, Sts.AuthorityNotInValidList); Verify.IsTrue(ex.Message.Contains("authority")); } #endif finally { } }
public static async Task MultiResourceRefreshTokenTestAsync(Sts sts) { SetCredential(sts); var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); AuthenticationResultProxy result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifySuccessResult(sts, result); AuthenticationResultProxy result2 = await context.AcquireTokenByRefreshTokenAsync(result.RefreshToken, sts.ValidClientId, sts.ValidResource2); if (sts.Type == StsType.AAD) { VerifySuccessResult(sts, result2, true, false); Verify.IsTrue(result.IsMultipleResourceRefreshToken); Verify.IsTrue(result2.IsMultipleResourceRefreshToken); } result2 = context.AcquireToken(sts.ValidResource2, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifySuccessResult(sts, result2); if (sts.Type == StsType.ADFS) { Verify.IsFalse(result.IsMultipleResourceRefreshToken); } else { Verify.IsTrue(result.IsMultipleResourceRefreshToken); } if (sts.Type == StsType.AAD) { result2 = context.AcquireToken(sts.ValidResource3, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifySuccessResult(sts, result2); Verify.IsTrue(result.IsMultipleResourceRefreshToken); } }
public static void AcquireTokenPositiveTest(Sts sts) { SetCredential(sts); var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); AuthenticationResultProxy result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifySuccessResult(sts, result); }
public static async Task AcquireTokenWithAuthenticationCanceledTestAsync(Sts sts) { AuthenticationContextProxy.SetCredentials(null, null); var context = new AuthenticationContextProxy(TestConstants.DefaultAuthorityCommonTenant, sts.ValidateAuthority); AuthenticationResultProxy result = await context.AcquireTokenAsync(TestConstants.DefaultResource, TestConstants.DefaultClientId, TestConstants.DefaultResource, PlatformParameters, new UserIdentifier("*****@*****.**", UserIdentifierType.OptionalDisplayableId)); VerifyErrorResult(result, Sts.AuthenticationCanceledError, "canceled"); }
public static void AcquireTokenWithAuthenticationCanceledTest(Sts sts) { AuthenticationContextProxy.SetCredentials(null, null); var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); AuthenticationResultProxy result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, new UserIdentifier("*****@*****.**", UserIdentifierType.OptionalDisplayableId)); VerifyErrorResult(result, Sts.AuthenticationCanceledError, "canceled"); }
public static void AcquireTokenWithInvalidClientIdTest(Sts sts) { SetCredential(sts); var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); AuthenticationResultProxy result = context.AcquireToken(sts.ValidResource, sts.InvalidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifyErrorResult(result, Sts.AuthenticationCanceledError, null); }
private static void VerifySuccessResultAndTokenContent(Sts sts, AuthenticationResultProxy result, bool supportRefreshToken = true, bool supportUserInfo = true) { VerifySuccessResult(sts, result, supportRefreshToken, supportUserInfo); if (supportUserInfo) { VerifyTokenContent(result); } }
public static void AcquireTokenWithIncorrectUserCredentialTest(Sts sts) { AuthenticationContextProxy.SetCredentials(sts.InvalidUserName, "invalid_password"); var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); AuthenticationResultProxy result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, UserIdentifier.AnyUser, "incorrect_user"); VerifyErrorResult(result, Sts.AuthenticationCanceledError, "canceled"); }
public static async Task ConfidentialClientTestAsync(Sts sts) { SetCredential(sts); var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); string authorizationCode = context.AcquireAccessCode(sts.ValidResource, sts.ValidConfidentialClientId, sts.ValidRedirectUriForConfidentialClient, sts.ValidUserId); var credential = new ClientCredential(sts.ValidConfidentialClientId, sts.ValidConfidentialClientSecret); AuthenticationResultProxy result = await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode, sts.ValidRedirectUriForConfidentialClient, credential); VerifySuccessResult(sts, result); AuthenticationContextProxy.Delay(2000); // 2 seconds delay context.SetCorrelationId(new Guid("2ddbba59-1a04-43fb-b363-7fb0ae785031")); // Test cache usage in AcquireTokenByAuthorizationCodeAsync // There is no cache lookup, so the results should be different. AuthenticationResultProxy result2 = await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode, sts.ValidRedirectUriForConfidentialClient, credential); VerifySuccessResult(sts, result2); Verify.AreNotEqual(result.AccessToken, result2.AccessToken); AuthenticationContextProxy.ClearDefaultCache(); result = await context.AcquireTokenByRefreshTokenAsync(result.RefreshToken, credential); VerifySuccessResult(sts, result, true, false); result = await context.AcquireTokenByRefreshTokenAsync(result.RefreshToken, sts.ValidConfidentialClientId, sts.ValidResource); VerifyErrorResult(result, "invalid_request", null, 400, "90014"); // ACS90014: The request body must contain the following parameter: 'client_secret or client_assertion'. result = await context.AcquireTokenByAuthorizationCodeAsync(null, sts.ValidRedirectUriForConfidentialClient, credential); VerifyErrorResult(result, "invalid_argument", "authorizationCode"); result = await context.AcquireTokenByAuthorizationCodeAsync(string.Empty, sts.ValidRedirectUriForConfidentialClient, credential); VerifyErrorResult(result, "invalid_argument", "authorizationCode"); result = await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode + "x", sts.ValidRedirectUriForConfidentialClient, credential); VerifyErrorResult(result, "invalid_grant", "authorization code"); result = await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode, new Uri(sts.ValidRedirectUriForConfidentialClient.AbsoluteUri + "x"), credential); VerifyErrorResult(result, "invalid_grant", "does not match the reply address", 400, "70002"); result = await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode, sts.ValidRedirectUriForConfidentialClient, (ClientCredential)null); VerifyErrorResult(result, "invalid_argument", "credential"); var invalidCredential = new ClientCredential(sts.ValidConfidentialClientId, sts.ValidConfidentialClientSecret + "x"); result = await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode, sts.ValidRedirectUriForConfidentialClient, invalidCredential); VerifyErrorResult(result, "invalid_client", "client secret", 401); }
internal void VerifySingleItemInCache(AuthenticationResultProxy result, StsType stsType) { List<TokenCacheItem> items = this.context.TokenCache.ReadItems().ToList(); Verify.AreEqual(1, items.Count); Verify.AreEqual(result.AccessToken, items[0].AccessToken); Verify.AreEqual(result.RefreshToken, items[0].RefreshToken); Verify.AreEqual(result.IdToken, items[0].IdToken); Verify.IsTrue(stsType == StsType.ADFS || items[0].IdToken != null); }
internal void VerifySingleItemInCache(AuthenticationResultProxy result, StsType stsType) { List <TokenCacheItem> items = this.context.TokenCache.ReadItems().ToList(); Verify.AreEqual(1, items.Count); Verify.AreEqual(result.AccessToken, items[0].AccessToken); Verify.AreEqual(result.IdToken ?? string.Empty, items[0].IdToken ?? string.Empty); Verify.IsTrue(stsType == StsType.ADFS || items[0].IdToken != null); }
public static void VerifySuccessResult(Sts sts, AuthenticationResultProxy result, bool supportRefreshToken = true, bool supportUserInfo = true) { Log.Comment("Verifying success result..."); if (result.Status != AuthenticationStatusProxy.Success) { Log.Comment(string.Format("Unexpected '{0}' error from service: {1}", result.Error, result.ErrorDescription)); } Verify.AreEqual(AuthenticationStatusProxy.Success, result.Status, "AuthenticationResult.Status"); Verify.IsNotNullOrEmptyString(result.AccessToken, "AuthenticationResult.AccessToken"); if (supportRefreshToken) { Verify.IsNotNullOrEmptyString(result.RefreshToken, "AuthenticationResult.RefreshToken"); } else { Verify.IsNullOrEmptyString(result.RefreshToken, "AuthenticationResult.RefreshToken"); } Verify.IsNullOrEmptyString(result.Error, "AuthenticationResult.Error"); Verify.IsNullOrEmptyString(result.ErrorDescription, "AuthenticationResult.ErrorDescription"); if (sts.Type != StsType.ADFS && supportUserInfo) { Action <string, string, bool> ValidateUserInfo = (string field, string caption, bool required) => { if (string.IsNullOrEmpty(field)) { if (required) { Log.Error("No " + caption); } else { Log.Warning("No " + caption); } } else { Log.Comment(field, caption); } }; ValidateUserInfo(result.TenantId, "tenant id", true); ValidateUserInfo(result.UserInfo.UniqueId, "user unique id", true); ValidateUserInfo(result.UserInfo.DisplayableId, "user displayable id", true); ValidateUserInfo(result.UserInfo.IdentityProvider, "identity provider", true); ValidateUserInfo(result.UserInfo.GivenName, "given name", false); ValidateUserInfo(result.UserInfo.FamilyName, "family name", false); } long expiresIn = (long)(result.ExpiresOn - DateTime.UtcNow).TotalSeconds; Log.Comment("Verifying token expiration..."); Verify.IsGreaterThanOrEqual(expiresIn, (long)0, "Token ExpiresOn"); }
public static void NonHttpsURLNegativeTest(Sts sts) { AuthenticationContextProxy.SetCredentials(sts.ValidUserName, sts.ValidPassword); var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); // Obtain a token interactively. AuthenticationResultProxy result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifyErrorDescriptionContains(result.ErrorDescription, "Non-HTTPS url redirect is not supported in webview"); }
private static void ValidateAuthenticationResultsAreEqual(AuthenticationResultProxy result, AuthenticationResultProxy result2) { Verify.AreEqual(result.AccessToken, result2.AccessToken, "AuthenticationResult.AccessToken"); Verify.AreEqual(result.RefreshToken, result2.RefreshToken, "AuthenticationResult.RefreshToken"); Verify.AreEqual(result.UserInfo.UniqueId, result2.UserInfo.UniqueId); Verify.AreEqual(result.UserInfo.DisplayableId, result2.UserInfo.DisplayableId); Verify.AreEqual(result.UserInfo.GivenName, result2.UserInfo.GivenName); Verify.AreEqual(result.UserInfo.FamilyName, result2.UserInfo.FamilyName); Verify.AreEqual(result.TenantId, result2.TenantId); }
public static async Task UserInfoTestAsync(Sts sts) { SetCredential(sts); var context = new AuthenticationContextProxy(TestConstants.DefaultAuthorityCommonTenant, sts.ValidateAuthority); AuthenticationResultProxy result = await context.AcquireTokenAsync(TestConstants.DefaultResource, TestConstants.DefaultClientId, TestConstants.DefaultResource, PlatformParameters, sts.ValidUserId); VerifySuccessResult(sts, result); AuthenticationResultProxy result2; if (sts.Type == StsType.AAD) { Verify.AreEqual(sts.ValidUserName, result.UserInfo.DisplayableId); Verify.IsNotNullOrEmptyString(result.UserInfo.UniqueId); Verify.IsNotNullOrEmptyString(result.UserInfo.GivenName); Verify.IsNotNullOrEmptyString(result.UserInfo.FamilyName); EndBrowserDialogSession(); Log.Comment("Waiting 2 seconds before next token request..."); AuthenticationContextProxy.Delay(2000); // 2 seconds delay AuthenticationContextProxy.SetCredentials(null, null); result2 = await context.AcquireTokenAsync(TestConstants.DefaultResource, TestConstants.DefaultClientId, TestConstants.DefaultResource, PlatformParameters, new UserIdentifier(result.UserInfo.DisplayableId, UserIdentifierType.OptionalDisplayableId), SecondCallExtraQueryParameter); ValidateAuthenticationResultsAreEqual(result, result2); } AuthenticationContextProxy.SetCredentials(null, null); result2 = await context.AcquireTokenAsync(TestConstants.DefaultResource, TestConstants.DefaultClientId, TestConstants.DefaultResource, PlatformParameters); Verify.AreEqual(result.AccessToken, result2.AccessToken); SetCredential(sts); result2 = await context.AcquireTokenAsync(TestConstants.DefaultResource, TestConstants.DefaultClientId, TestConstants.DefaultResource, PlatformParameters, sts.ValidUserId, ThirdCallExtraQueryParameter); VerifySuccessResult(sts, result2); if (result.UserInfo != null) { ValidateAuthenticationResultsAreEqual(result, result2); } else { VerifyExpiresOnAreNotEqual(result, result2); } EndBrowserDialogSession(); Log.Comment("Waiting 2 seconds before next token request..."); AuthenticationContextProxy.Delay(2000); // 2 seconds delay AuthenticationContextProxy.SetCredentials(sts.ValidUserName, sts.ValidPassword); result2 = await context.AcquireTokenAsync(TestConstants.DefaultResource, TestConstants.DefaultClientId, TestConstants.DefaultResource, PlatformParameters, sts.InvalidRequiredUserId, SecondCallExtraQueryParameter); VerifyErrorResult(result2, "user_mismatch", null); }
public static void VerifyExpiresOnAreNotEqual(AuthenticationResultProxy result, AuthenticationResultProxy result2) { bool equal = AreDateTimeOffsetsEqual(result.ExpiresOn, result2.ExpiresOn); if (equal) { Log.Comment(result.ExpiresOn.ToString("R") + " <> " + result2.ExpiresOn.ToString("R")); } Verify.IsFalse(equal, "AuthenticationResult.ExpiresOn"); }
internal static async Task MultiUserCacheTestAsync(Sts sts) { Log.Comment("Acquire token for user1 interactively"); AuthenticationContextProxy.SetCredentials(null, sts.ValidPassword); var context = new AuthenticationContextProxy(TestConstants.DefaultAuthorityCommonTenant, sts.ValidateAuthority); AuthenticationResultProxy result = await context.AcquireTokenAsync(TestConstants.DefaultResource, TestConstants.DefaultClientId, TestConstants.DefaultResource, PlatformParameters, sts.ValidUserId); VerifySuccessResultAndTokenContent(sts, result); Verify.AreEqual(sts.ValidUserName, result.UserInfo.DisplayableId); Log.Comment("Acquire token for user1 returning cached token"); AuthenticationContextProxy.SetCredentials(null, null); result = await context.AcquireTokenAsync(TestConstants.DefaultResource, TestConstants.DefaultClientId, TestConstants.DefaultResource, PlatformParameters, sts.ValidUserId); VerifySuccessResultAndTokenContent(sts, result); Verify.AreEqual(sts.ValidUserName, result.UserInfo.DisplayableId); Log.Comment("Clear cookie and acquire token for user2 interactively"); EndBrowserDialogSession(); AuthenticationContextProxy.SetCredentials(null, sts.ValidPassword2); AuthenticationResultProxy result2 = await context.AcquireTokenAsync(TestConstants.DefaultResource, TestConstants.DefaultClientId, TestConstants.DefaultResource, PlatformParameters, sts.ValidRequiredUserId2); VerifySuccessResultAndTokenContent(sts, result2); Verify.AreEqual(sts.ValidUserName2, result2.UserInfo.DisplayableId); Log.Comment("Acquire token for user1 returning cached token"); AuthenticationContextProxy.SetCredentials(null, null); result = await context.AcquireTokenAsync(TestConstants.DefaultResource, TestConstants.DefaultClientId, TestConstants.DefaultResource, PlatformParameters, sts.ValidUserId); VerifySuccessResultAndTokenContent(sts, result); Verify.AreEqual(sts.ValidUserName, result.UserInfo.DisplayableId); Log.Comment("Acquire token for user2 returning cached token"); AuthenticationContextProxy.SetCredentials(null, null); result2 = await context.AcquireTokenAsync(TestConstants.DefaultResource, TestConstants.DefaultClientId, TestConstants.DefaultResource, PlatformParameters, sts.ValidRequiredUserId2); VerifySuccessResultAndTokenContent(sts, result2); Verify.AreEqual(sts.ValidUserName2, result2.UserInfo.DisplayableId); Log.Comment("Acquire token for user1 and resource2 using cached multi resource refresh token"); AuthenticationContextProxy.SetCredentials(null, null); result = await context.AcquireTokenAsync(TestConstants.DefaultResource2, TestConstants.DefaultClientId, TestConstants.DefaultResource, PlatformParameters, sts.ValidUserId); VerifySuccessResultAndTokenContent(sts, result); Verify.AreEqual(sts.ValidUserName, result.UserInfo.DisplayableId); Log.Comment("Acquire token for user2 and resource2 using cached multi resource refresh token"); AuthenticationContextProxy.SetCredentials(null, null); result2 = await context.AcquireTokenAsync(TestConstants.DefaultResource2, TestConstants.DefaultClientId, TestConstants.DefaultResource, PlatformParameters, sts.ValidRequiredUserId2); VerifySuccessResultAndTokenContent(sts, result2); Verify.AreEqual(sts.ValidUserName2, result2.UserInfo.DisplayableId); }
internal static AuthenticationResultProxy Deserialize(string obj) { AuthenticationResultProxy output = null; var serializer = new DataContractJsonSerializer(typeof(AuthenticationResultProxy)); byte[] serializedObjectBytes = Encoding.UTF8.GetBytes(obj); using (var stream = new MemoryStream(serializedObjectBytes)) { output = (AuthenticationResultProxy)serializer.ReadObject(stream); } return(output); }
public static void AcquireTokenPositiveWithFederatedTenantTest(Sts sts) { var userId = sts.ValidUserId; AuthenticationContextProxy.SetCredentials(userId.Id, sts.ValidPassword); var context = new AuthenticationContextProxy(sts.Authority, false, TokenCacheType.Null); AuthenticationResultProxy result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, userId); VerifySuccessResult(sts, result); result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, UserIdentifier.AnyUser); VerifySuccessResult(sts, result); }
internal static async Task AcquireTokenOnBehalfAndClientAssertionTestAsync(Sts sts) { SetCredential(sts); var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); AuthenticationResultProxy result = context.AcquireToken(sts.ValidConfidentialClientId, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifySuccessResult(sts, result); RecorderJwtId.JwtIdIndex = 13; ClientAssertion clientAssertion = CreateClientAssertion(sts.Authority, sts.ValidConfidentialClientId, sts.ConfidentialClientCertificateName, sts.ConfidentialClientCertificatePassword); AuthenticationResultProxy result2 = await context.AcquireTokenAsync(null, clientAssertion, result.AccessToken); VerifyErrorResult(result2, Sts.InvalidArgumentError, "resource"); result2 = await context.AcquireTokenAsync(sts.ValidResource, clientAssertion, null); VerifyErrorResult(result2, Sts.InvalidArgumentError, "userAssertion"); result2 = await context.AcquireTokenAsync(sts.ValidResource, (ClientAssertion)null, result.AccessToken); VerifyErrorResult(result2, Sts.InvalidArgumentError, "clientAssertion"); result2 = await context.AcquireTokenAsync(sts.ValidResource, clientAssertion, result.AccessToken); VerifySuccessResult(sts, result2, true, false); // Testing cache AuthenticationContextProxy.Delay(2000); // 2 seconds delay AuthenticationResultProxy result3 = await context.AcquireTokenAsync(sts.ValidResource, clientAssertion, result.AccessToken); VerifySuccessResult(sts, result3, true, false); VerifyExpiresOnAreEqual(result2, result3); // Using MRRT in cached token to acquire token for a different resource AuthenticationResultProxy result4 = await context.AcquireTokenAsync(sts.ValidResource2, clientAssertion, result.AccessToken); VerifySuccessResult(sts, result4, true, false); AuthenticationContextProxy.ClearDefaultCache(); result2 = await context.AcquireTokenAsync(sts.ValidResource, clientAssertion, result.AccessToken); VerifySuccessResult(sts, result2, true, false); // Using MRRT in cached token to acquire token for a different resource result3 = await context.AcquireTokenSilentAsync(sts.ValidResource2, clientAssertion, UserIdentifier.AnyUser); VerifySuccessResult(sts, result3, true, false); }
public static async Task MixedCaseUserNameTestAsync(Sts sts) { var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); UserCredentialProxy credential = new UserCredentialProxy(sts.ValidUserName3, sts.ValidPassword3); AuthenticationResultProxy result = await context.AcquireTokenAsync(sts.ValidResource, sts.ValidClientId, credential); VerifySuccessResult(sts, result); Verify.IsNotNull(result.UserInfo); Verify.AreNotEqual(result.UserInfo.DisplayableId, result.UserInfo.DisplayableId.ToLower()); AuthenticationContextProxy.Delay(2000); // 2 seconds delay AuthenticationResultProxy result2 = await context.AcquireTokenAsync(sts.ValidResource, sts.ValidClientId, credential); VerifySuccessResult(sts, result2); Verify.IsTrue(AreDateTimeOffsetsEqual(result.ExpiresOn, result2.ExpiresOn)); }
public static void AcquireTokenAndRefreshSessionTest(Sts sts) { var userId = sts.ValidUserId; AuthenticationContextProxy.SetCredentials(userId.Id, sts.ValidPassword); var context = new AuthenticationContextProxy(sts.Authority, false, TokenCacheType.InMemory); AuthenticationResultProxy result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, userId); VerifySuccessResult(sts, result); AuthenticationContextProxy.Delay(2000); AuthenticationResultProxy result2 = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.RefreshSession, userId); VerifySuccessResult(sts, result2); Verify.AreNotEqual(result.AccessToken, result2.AccessToken); }
internal static void MultiUserCacheTest(Sts sts) { Log.Comment("Acquire token for user1 interactively"); AuthenticationContextProxy.SetCredentials(null, sts.ValidPassword); var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); AuthenticationResultProxy result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifySuccessResultAndTokenContent(sts, result); Verify.AreEqual(sts.ValidUserName, result.UserInfo.DisplayableId); Log.Comment("Acquire token for user1 returning cached token"); AuthenticationContextProxy.SetCredentials(null, null); result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifySuccessResultAndTokenContent(sts, result); Verify.AreEqual(sts.ValidUserName, result.UserInfo.DisplayableId); Log.Comment("Clear cookie and acquire token for user2 interactively"); EndBrowserDialogSession(); AuthenticationContextProxy.SetCredentials(null, sts.ValidPassword2); AuthenticationResultProxy result2 = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidRequiredUserId2); VerifySuccessResultAndTokenContent(sts, result2); Verify.AreEqual(sts.ValidUserName2, result2.UserInfo.DisplayableId); Log.Comment("Acquire token for user1 returning cached token"); AuthenticationContextProxy.SetCredentials(null, null); result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifySuccessResultAndTokenContent(sts, result); Verify.AreEqual(sts.ValidUserName, result.UserInfo.DisplayableId); Log.Comment("Acquire token for user2 returning cached token"); AuthenticationContextProxy.SetCredentials(null, null); result2 = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidRequiredUserId2); VerifySuccessResultAndTokenContent(sts, result2); Verify.AreEqual(sts.ValidUserName2, result2.UserInfo.DisplayableId); Log.Comment("Acquire token for user1 and resource2 using cached multi resource refresh token"); AuthenticationContextProxy.SetCredentials(null, null); result = context.AcquireToken(sts.ValidResource2, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifySuccessResultAndTokenContent(sts, result); Verify.AreEqual(sts.ValidUserName, result.UserInfo.DisplayableId); Log.Comment("Acquire token for user2 and resource2 using cached multi resource refresh token"); AuthenticationContextProxy.SetCredentials(null, null); result2 = context.AcquireToken(sts.ValidResource2, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidRequiredUserId2); VerifySuccessResultAndTokenContent(sts, result2); Verify.AreEqual(sts.ValidUserName2, result2.UserInfo.DisplayableId); }
public static void AcquireTokenPositiveWithoutRedirectUriOrUserIdTest(Sts sts) { AuthenticationContextProxy.SetCredentials(sts.ValidUserName, sts.ValidPassword); var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); AuthenticationResultProxy result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri); VerifySuccessResult(sts, result); result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, null); VerifyErrorResult(result, Sts.InvalidArgumentError, "userId"); VerifyErrorResult(result, Sts.InvalidArgumentError, "UserIdentifier.AnyUser"); result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, UserIdentifier.AnyUser); VerifySuccessResult(sts, result); }
public static async Task ConfidentialClientWithX509TestAsync(Sts sts) { SetCredential(sts); var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority, TokenCacheType.Null); string authorizationCode = context.AcquireAccessCode(sts.ValidResource, sts.ValidConfidentialClientId, sts.ValidRedirectUriForConfidentialClient, sts.ValidUserId); var certificate = new ClientAssertionCertificate(sts.ValidConfidentialClientId, new X509Certificate2(sts.ConfidentialClientCertificateName, sts.ConfidentialClientCertificatePassword)); RecorderJwtId.JwtIdIndex = 1; AuthenticationResultProxy result = await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode, sts.ValidRedirectUriForConfidentialClient, certificate, sts.ValidResource); VerifySuccessResult(sts, result); result = await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode, sts.ValidRedirectUriForConfidentialClient, certificate); VerifySuccessResult(sts, result); result = await context.AcquireTokenByRefreshTokenAsync(result.RefreshToken, certificate, sts.ValidResource); VerifySuccessResult(sts, result, true, false); result = await context.AcquireTokenByRefreshTokenAsync(result.RefreshToken, sts.ValidConfidentialClientId, sts.ValidResource); VerifyErrorResult(result, Sts.InvalidRequest, null, 400, "90014"); // The request body must contain the following parameter: 'client_secret or client_assertion'. result = await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode, sts.ValidRedirectUriForConfidentialClient, certificate, null); VerifySuccessResult(sts, result); result = await context.AcquireTokenByAuthorizationCodeAsync(null, sts.ValidRedirectUriForConfidentialClient, certificate, sts.ValidResource); VerifyErrorResult(result, Sts.InvalidArgumentError, "authorizationCode"); result = await context.AcquireTokenByAuthorizationCodeAsync(string.Empty, sts.ValidRedirectUriForConfidentialClient, certificate, sts.ValidResource); VerifyErrorResult(result, Sts.InvalidArgumentError, "authorizationCode"); // Send null for redirect result = await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode, null, certificate, sts.ValidResource); VerifyErrorResult(result, Sts.InvalidArgumentError, "redirectUri"); result = await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode, sts.ValidRedirectUriForConfidentialClient, (ClientAssertionCertificate)null, sts.ValidResource); VerifyErrorResult(result, Sts.InvalidArgumentError, "clientCertificate"); }
private static void VerifyTokenContent(AuthenticationResultProxy result) { // Verify the token content confirms the user in AuthenticationResult.UserInfo var token = new System.IdentityModel.Tokens.JwtSecurityToken(result.AccessToken); foreach (var claim in token.Claims) { if (claim.Type == "oid") { Verify.AreEqual(result.UserInfo.UniqueId, claim.Value); } if (claim.Type == "upn") { Verify.AreEqual(result.UserInfo.DisplayableId, claim.Value); } } }
public static async Task AcquireTokenPositiveWithDefaultCacheTestAsync(Sts sts) { AuthenticationContextProxy.ClearDefaultCache(); SetCredential(sts); var context = new AuthenticationContextProxy(TestConstants.DefaultAuthorityCommonTenant, sts.ValidateAuthority); List <AuthenticationResultProxy> results = await AcquireTokenPositiveWithCacheAsync(sts, context); VerifyExpiresOnAreEqual(results[0], results[1]); EndBrowserDialogSession(); Log.Comment("Waiting 2 seconds before next token request..."); AuthenticationContextProxy.Delay(2000); // 2 seconds delay AuthenticationResultProxy resultWithoutUser = await context.AcquireTokenAsync(TestConstants.DefaultResource, TestConstants.DefaultClientId, TestConstants.DefaultResource, PlatformParameters, UserIdentifier.AnyUser, SecondCallExtraQueryParameter); VerifyExpiresOnAreEqual(results[0], resultWithoutUser); context.VerifySingleItemInCache(results[0], sts.Type); }
public static void AcquireTokenWithInvalidResourceTest(Sts sts) { SetCredential(sts); var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); AuthenticationResultProxy result = context.AcquireToken(sts.InvalidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifyErrorResult(result, Sts.InvalidResourceError, "resource"); result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifySuccessResult(sts, result); result = context.AcquireToken(sts.ValidResource.ToUpper(), sts.ValidClientId.ToUpper(), sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, (sts.Type == StsType.AAD) ? new UserIdentifier(sts.ValidUserName, UserIdentifierType.RequiredDisplayableId) : UserIdentifier.AnyUser); VerifySuccessResult(sts, result); result = context.AcquireToken(sts.ValidResource.ToUpper(), sts.ValidClientId.ToUpper(), sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, (result.UserInfo != null) ? new UserIdentifier(result.UserInfo.UniqueId, UserIdentifierType.UniqueId) : UserIdentifier.AnyUser); VerifySuccessResult(sts, result); }
public static async Task AcquireTokenNonInteractivePositiveTestAsync(Sts sts) { var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); UserCredentialProxy credential = new UserCredentialProxy(sts.ValidUserName, sts.ValidPassword); AuthenticationResultProxy result = await context.AcquireTokenAsync(sts.ValidResource, sts.ValidClientId, credential); VerifySuccessResult(sts, result); Verify.IsNotNull(result.UserInfo); Verify.IsNotNullOrEmptyString(result.UserInfo.UniqueId); Verify.IsNotNullOrEmptyString(result.UserInfo.DisplayableId); AuthenticationContextProxy.Delay(2000); // Test token cache AuthenticationResultProxy result2 = await context.AcquireTokenAsync(sts.ValidResource, sts.ValidClientId, credential); VerifySuccessResult(sts, result2); VerifyExpiresOnAreEqual(result, result2); }
public static void AcquireTokenPositiveWithDefaultCacheTest(Sts sts) { AuthenticationContextProxy.ClearDefaultCache(); SetCredential(sts); var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); List <AuthenticationResultProxy> results = AcquireTokenPositiveWithCache(sts, context); VerifyExpiresOnAreEqual(results[0], results[1]); EndBrowserDialogSession(); Log.Comment("Waiting 2 seconds before next token request..."); AuthenticationContextProxy.Delay(2000); // 2 seconds delay AuthenticationResultProxy resultWithoutUser = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, UserIdentifier.AnyUser, SecondCallExtraQueryParameter); VerifyExpiresOnAreEqual(results[0], resultWithoutUser); context.VerifySingleItemInCache(results[0], sts.Type); }
public static async Task WebExceptionAccessTestAsync(Sts sts) { SetCredential(sts); var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); AuthenticationResultProxy result = context.AcquireToken(sts.ValidResource, sts.ValidClientId, sts.ValidDefaultRedirectUri, PromptBehaviorProxy.Auto, sts.ValidUserId); VerifySuccessResult(sts, result); result = await context.AcquireTokenByRefreshTokenAsync(result.RefreshToken, sts.InvalidClientId); VerifyErrorResult(result, "unauthorized_client", "AADSTS70001"); Verify.IsNotNull(result.Exception); Verify.IsNotNull(result.Exception.InnerException); Verify.IsTrue(result.Exception.InnerException is WebException); using (StreamReader sr = new StreamReader(((WebException)(result.Exception.InnerException)).Response.GetResponseStream())) { string streamBody = sr.ReadToEnd(); Verify.IsTrue(streamBody.Contains("AADSTS70001")); } }
public static void VerifySuccessResult(Sts sts, AuthenticationResultProxy result, bool supportRefreshToken = true, bool supportUserInfo = true) { Log.Comment("Verifying success result..."); if (result.Status != AuthenticationStatusProxy.Success) { Log.Comment(string.Format("Unexpected '{0}' error from service: {1}", result.Error, result.ErrorDescription)); } Verify.AreEqual(AuthenticationStatusProxy.Success, result.Status, "AuthenticationResult.Status"); Verify.IsNotNullOrEmptyString(result.AccessToken, "AuthenticationResult.AccessToken"); if (supportRefreshToken) { Verify.IsNotNullOrEmptyString(result.RefreshToken, "AuthenticationResult.RefreshToken"); } else { Verify.IsNullOrEmptyString(result.RefreshToken, "AuthenticationResult.RefreshToken"); } Verify.IsNullOrEmptyString(result.Error, "AuthenticationResult.Error"); Verify.IsNullOrEmptyString(result.ErrorDescription, "AuthenticationResult.ErrorDescription"); if (sts.Type != StsType.ADFS && supportUserInfo) { Action<string, string, bool> ValidateUserInfo = (string field, string caption, bool required) => { if (string.IsNullOrEmpty(field)) { if (required) { Log.Error("No " + caption); } else { Log.Warning("No " + caption); } } else { Log.Comment(field, caption); } }; ValidateUserInfo(result.TenantId, "tenant id", true); ValidateUserInfo(result.UserInfo.UniqueId, "user unique id", true); ValidateUserInfo(result.UserInfo.DisplayableId, "user displayable id", true); ValidateUserInfo(result.UserInfo.IdentityProvider, "identity provider", true); ValidateUserInfo(result.UserInfo.GivenName, "given name", false); ValidateUserInfo(result.UserInfo.FamilyName, "family name", false); } long expiresIn = (long)(result.ExpiresOn - DateTime.UtcNow).TotalSeconds; Log.Comment("Verifying token expiration..."); Verify.IsGreaterThanOrEqual(expiresIn, (long)0, "Token ExpiresOn"); }
public static void VerifyErrorResult(AuthenticationResultProxy result, string error, string errorDescriptionKeyword, int statusCode = 0, string serviceErrorCode = null) { Log.Comment(string.Format("Verifying error result '{0}':'{1}'...", result.Error, result.ErrorDescription)); Verify.AreNotEqual(AuthenticationStatusProxy.Success, result.Status); Verify.IsNullOrEmptyString(result.AccessToken); Verify.IsNotNullOrEmptyString(result.Error); Verify.IsNotNullOrEmptyString(result.ErrorDescription); Verify.IsFalse(result.ErrorDescription.Contains("+"), "Error description should not be in URL form encoding!"); Verify.IsFalse(result.ErrorDescription.Contains("%2"), "Error description should not be in URL encoding!"); if (!string.IsNullOrEmpty(error)) { Verify.AreEqual(error, result.Error); } if (!string.IsNullOrEmpty(errorDescriptionKeyword)) { VerifyErrorDescriptionContains(result.ErrorDescription, errorDescriptionKeyword); } if (statusCode != 0) { Verify.AreEqual(statusCode, result.ExceptionStatusCode); } if (serviceErrorCode != null) { Verify.IsTrue(result.ExceptionServiceErrorCodes.Contains(serviceErrorCode)); } }
internal void VerifySingleItemInCache(AuthenticationResultProxy result, StsType stsType) { }
internal static async Task MultiThreadedClientAssertionWithX509TestAsync(Sts sts) { var context = new AuthenticationContextProxy(sts.Authority, sts.ValidateAuthority); const int ParallelCount = 20; AuthenticationResultProxy[] result = new AuthenticationResultProxy[ParallelCount]; var certificate = new ClientAssertionCertificate(sts.ValidConfidentialClientId, ExportX509Certificate(sts.ConfidentialClientCertificateName, sts.ConfidentialClientCertificatePassword), sts.ConfidentialClientCertificatePassword); RecorderJwtId.JwtIdIndex = 8; Parallel.For(0, ParallelCount, async (i) => { result[i] = await context.AcquireTokenAsync(sts.ValidResource, certificate); Log.Comment("Error: " + result[i].Error); Log.Comment("Error Description: " + result[i].ErrorDescription); Verify.IsNotNullOrEmptyString(result[i].AccessToken); }); result[0] = await context.AcquireTokenAsync(sts.ValidResource, certificate); Log.Comment("Error: " + result[0].Error); Log.Comment("Error Description: " + result[0].ErrorDescription); Verify.IsNotNullOrEmptyString(result[0].AccessToken); }
public static async Task<AuthenticationResultProxy> ExecuteAsync(CommandProxy proxy) { AuthenticationResultProxy resultProxy = null; AuthenticationResult result = null; foreach (var command in proxy.Commands) { var arg = command.Arguments; switch (command.CommandType) { case CommandType.ClearDefaultTokenCache: { var dummyContext = new AuthenticationContext("https://dummy/dummy", false); dummyContext.TokenCache.Clear(); break; } case CommandType.SetEnvironmentVariable: { var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings; localSettings.Values[arg.EnvironmentVariable] = arg.EnvironmentVariableValue; break; } case CommandType.SetCorrelationId: { context.CorrelationId = arg.CorrelationId; break; } case CommandType.CreateContextA: { context = new AuthenticationContext(arg.Authority); break; } case CommandType.CreateContextAV: { context = new AuthenticationContext(arg.Authority, arg.ValidateAuthority); break; } case CommandType.CreateContextAVT: { TokenCache tokenCache = null; if (arg.TokenCacheType == TokenCacheType.InMemory) { tokenCache = new TokenCache() { // The default token cache in ADAL WinRT is persistent. This is how to make it in-memory only cache. BeforeAccess = delegate { }, AfterAccess = delegate { } }; } context = new AuthenticationContext(arg.Authority, arg.ValidateAuthority, tokenCache); break; } case CommandType.ClearUseCorporateNetwork: { //context.UseCorporateNetwork = false; break; } case CommandType.SetUseCorporateNetwork: { //context.UseCorporateNetwork = true; break; } case CommandType.AquireTokenAsyncRC: { result = await context.AcquireTokenAsync(arg.Resource, arg.ClientId); break; } case CommandType.AquireTokenAsyncRCUPa: { UserCredential credential = new UserCredential(arg.UserName); result = await context.AcquireTokenAsync(arg.Resource, arg.ClientId, credential); break; } case CommandType.AquireTokenAsyncRCRe: { result = await context.AcquireTokenAsync(arg.Resource, arg.ClientId, arg.RedirectUri); break; } case CommandType.AquireTokenAsyncRCRePUX: { result = await context.AcquireTokenAsync(arg.Resource, arg.ClientId, arg.RedirectUri, (arg.PromptBehavior == PromptBehaviorProxy.Always) ? PromptBehavior.Always : (arg.PromptBehavior == PromptBehaviorProxy.Never) ? PromptBehavior.Never : PromptBehavior.Auto, (arg.UserName != null) ? new UserIdentifier(arg.UserName, UserIdentifierType.OptionalDisplayableId) : UserIdentifier.AnyUser, arg.Extra); break; } case CommandType.AquireTokenAsyncRCReP: { result = await context.AcquireTokenAsync(arg.Resource, arg.ClientId, arg.RedirectUri, (arg.PromptBehavior == PromptBehaviorProxy.Always) ? PromptBehavior.Always : (arg.PromptBehavior == PromptBehaviorProxy.Never) ? PromptBehavior.Never : PromptBehavior.Auto); break; } case CommandType.AquireTokenAsyncRCRePU: { result = await context.AcquireTokenAsync(arg.Resource, arg.ClientId, arg.RedirectUri, (arg.PromptBehavior == PromptBehaviorProxy.Always) ? PromptBehavior.Always : (arg.PromptBehavior == PromptBehaviorProxy.Never) ? PromptBehavior.Never : PromptBehavior.Auto, (arg.UserName != null) ? new UserIdentifier(arg.UserName, UserIdentifierType.OptionalDisplayableId) : UserIdentifier.AnyUser); break; } case CommandType.AquireTokenAsyncRCP: { result = await context.AcquireTokenAsync(arg.Resource, arg.ClientId, (arg.PromptBehavior == PromptBehaviorProxy.Always) ? PromptBehavior.Always : (arg.PromptBehavior == PromptBehaviorProxy.Never) ? PromptBehavior.Never : PromptBehavior.Auto); break; } case CommandType.AcquireTokenByRefreshTokenAsyncRC: { result = await context.AcquireTokenByRefreshTokenAsync(arg.RefreshToken, arg.ClientId); break; } case CommandType.AcquireTokenByRefreshTokenAsyncRCRe: { result = await context.AcquireTokenByRefreshTokenAsync(arg.RefreshToken, arg.ClientId, arg.Resource); break; } case CommandType.CreateFromResourceUrlAsync: { var parameters = await AuthenticationParameters.CreateFromResourceUrlAsync(new Uri(arg.Extra)); resultProxy = new AuthenticationResultProxy { AuthenticationParametersAuthority = parameters.Authority, AuthenticationParametersResource = parameters.Resource }; break; } case CommandType.CreateFromResponseAuthenticateHeader: { var parameters = AuthenticationParameters.CreateFromResponseAuthenticateHeader(arg.Extra); resultProxy = new AuthenticationResultProxy { AuthenticationParametersAuthority = parameters.Authority, AuthenticationParametersResource = parameters.Resource }; break; } /*case CommandType.AcquireTokenByRefreshTokenAsyncRCC: { result = await context.AcquireTokenByRefreshTokenAsync(arg.RefreshToken, arg.ClientId, (arg.ClientId != null && arg.ClientSecret != null) ? new ClientCredential(arg.ClientId, arg.ClientSecret) : null); break; }*/ default: throw new Exception("Unknown command"); } } return resultProxy ?? new AuthenticationResultProxy { AccessToken = result.AccessToken, AccessTokenType = result.AccessTokenType, ExpiresOn = result.ExpiresOn, IsMultipleResourceRefreshToken = result.IsMultipleResourceRefreshToken, RefreshToken = result.RefreshToken, IdToken = result.IdToken, TenantId = result.TenantId, UserInfo = result.UserInfo, Error = result.Error, ErrorDescription = result.ErrorDescription, Status = (result.Status == AuthenticationStatus.Success) ? AuthenticationStatusProxy.Success : ((result.Status == AuthenticationStatus.ClientError) ? AuthenticationStatusProxy.ClientError : AuthenticationStatusProxy.ServiceError) }; }
private static AuthenticationResultProxy GetAuthenticationResultProxy(Exception ex) { var output = new AuthenticationResultProxy { ErrorDescription = ex.Message, }; output.Status = AuthenticationStatusProxy.ClientError; if (ex is ArgumentNullException) { output.Error = AdalError.InvalidArgument; } else if (ex is ArgumentException) { output.Error = AdalError.InvalidArgument; } else if (ex is AdalServiceException) { output.Error = ((AdalServiceException)ex).ErrorCode; output.ExceptionStatusCode = ((AdalServiceException)ex).StatusCode; output.Status = AuthenticationStatusProxy.ServiceError; } else if (ex is AdalException) { output.Error = ((AdalException)ex).ErrorCode; } else { output.Error = AdalError.AuthenticationFailed; } output.Exception = ex; return output; }