public void Test_IdentifierNotInOpenIdCache() { SecuredAttribute securedAttribute; HttpActionContext httpActionContext; HttpCookie authCookie; HttpCookie xsrfCookie; CookieHelper.CreateAuthenticationAndXsrfCookies( RequestContext.TenantId, WellKnownAliases.CurrentTenant.ReadiNowIdentityProviderInstance, Guid.NewGuid().ToString(), 1234, true, // Persistent null, // Create new XSRF token, DateTime.Now, // Issue date DateTime.Now.AddMinutes(10), // Expiry out authCookie, out xsrfCookie); httpActionContext = BuildHttpActionContext(); httpActionContext.Request.Headers.Add( "Cookie", string.Format( "{0}={1};{2}={3}", authCookie.Name, authCookie.Value, xsrfCookie.Name, xsrfCookie.Value)); httpActionContext.Request.Headers.Add( LoginConstants.Headers.AngularJsXsrfToken, xsrfCookie.Value); httpActionContext.Request.RequestUri = new Uri( string.Format( "http://a?{0}={1}", LoginConstants.QueryString.XsrfToken, xsrfCookie.Value), UriKind.Absolute); HttpContext.Current = BuildHttpContext(); securedAttribute = new SecuredAttribute(); Assert.That(() => securedAttribute.OnAuthorization(httpActionContext), Throws.TypeOf <InvalidCredentialException>().And.Property("Message").EqualTo(UserAccountValidator.InvalidUserNameOrPasswordMessage)); }
public void Test_CreateAuthenticationAndXsrfCookies(long tenantId, long identityProviderId, string identityProviderUserName, long userAccountId, string xsrfToken, bool persistent) { HttpCookie authCookie; HttpCookie xsrfCookie; FormsAuthenticationTicket ticket; AuthenticationToken authTicket; HttpContext.Current = new HttpContext(new HttpRequest("", "http://tempuri.org", ""), new HttpResponse(new StringWriter())); CookieHelper.CreateAuthenticationAndXsrfCookies(tenantId, identityProviderId, identityProviderUserName, userAccountId, persistent, xsrfToken); authCookie = HttpContext.Current.Response.Cookies[FormsAuthentication.FormsCookieName]; Assert.That(authCookie, Is.Not.Null, "Null auth cookie"); Assert.That(authCookie, Has.Property("Values").Count.EqualTo(1), "Incorrect auth cookie values"); // ReSharper disable once PossibleNullReferenceException ticket = FormsAuthentication.Decrypt(authCookie.Value); Assert.That(ticket, Has.Property("Version").EqualTo(1)); Assert.That(ticket, Has.Property("Name").EqualTo(LoginConstants.Cookie.CookieName)); Assert.That(ticket, Has.Property("IssueDate").EqualTo(DateTime.Now).Within(TimeSpan.FromSeconds(10))); Assert.That(ticket, Has.Property("Expiration").EqualTo(DateTime.Now.AddMinutes(LoginConstants.Cookie.Timeout)).Within(TimeSpan.FromSeconds(10))); Assert.That(ticket, Has.Property("IsPersistent").EqualTo(persistent)); // ReSharper disable once PossibleNullReferenceException authTicket = JSON.Deserialize <AuthenticationToken>(ticket.UserData); Assert.That(authTicket, Has.Property("TenantId").EqualTo(tenantId)); Assert.That(authTicket, Has.Property("IdentityProviderId").EqualTo(identityProviderId)); Assert.That(authTicket, Has.Property("IdentityProviderUserName").EqualTo(identityProviderUserName)); Assert.That(authTicket, Has.Property("UserAccountId").EqualTo(userAccountId)); Assert.That(authTicket, Has.Property("XsrfToken").EqualTo(xsrfToken)); Assert.That(authTicket, Has.Property("Persist").EqualTo(persistent)); xsrfCookie = HttpContext.Current.Response.Cookies[LoginConstants.Cookie.AngularDefaultXsrfCookieName]; Assert.That(xsrfCookie, Is.Not.Null, "Null xsrf cookie"); Assert.That(xsrfCookie, Has.Property("Values").Count.EqualTo(1), "Incorrect xsrf cookie values"); Assert.That(xsrfCookie, Has.Property("Value").EqualTo(xsrfToken)); }
public void Test_ExpiredAuthCookie() { SecuredAttribute securedAttribute; HttpActionContext httpActionContext; HttpCookie authCookie; HttpCookie xsrfCookie; var requestContext = RequestContext.GetContext(); CookieHelper.CreateAuthenticationAndXsrfCookies( RequestContext.TenantId, WellKnownAliases.CurrentTenant.ReadiNowIdentityProviderInstance, requestContext.Identity.Name, requestContext.Identity.Id, true, // Persistent null, // Create new XSRF token, DateTime.Now.AddMinutes(-10), // Issue date DateTime.Now.AddMinutes(-1), // Expiry out authCookie, out xsrfCookie); httpActionContext = BuildHttpActionContext(); httpActionContext.Request.Headers.Add( "Cookie", string.Format( "{0}={1};{2}={3}", authCookie.Name, authCookie.Value, xsrfCookie.Name, xsrfCookie.Value)); HttpContext.Current = BuildHttpContext(); securedAttribute = new SecuredAttribute(); Assert.That(() => securedAttribute.OnAuthorization(httpActionContext), Throws.TypeOf <AuthenticationTokenExpiredException>()); }
public void Test_ExtendWindow(string requestPath, double offset, bool expectExtension) { SecuredAttribute securedAttribute; HttpActionContext httpActionContext; HttpCookie authCookie; HttpCookie xsrfCookie; DateTime issueDate; DateTime expiryDate; // Ensure the ticket is over half way through its window issueDate = DateTime.Now.AddMinutes(-(LoginConstants.Cookie.Timeout / 2) + offset); expiryDate = issueDate.AddMinutes(LoginConstants.Cookie.Timeout); var requestContext = RequestContext.GetContext(); CookieHelper.CreateAuthenticationAndXsrfCookies( RequestContext.TenantId, WellKnownAliases.CurrentTenant.ReadiNowIdentityProviderInstance, requestContext.Identity.Name, requestContext.Identity.Id, true, // Persistent null, // Create new XSRF token, issueDate, expiryDate, out authCookie, out xsrfCookie); httpActionContext = BuildHttpActionContext(); httpActionContext.Request.Headers.Add( "Cookie", string.Format( "{0}={1};{2}={3}", authCookie.Name, authCookie.Value, xsrfCookie.Name, xsrfCookie.Value)); httpActionContext.Request.Headers.Add( LoginConstants.Headers.AngularJsXsrfToken, xsrfCookie.Value); httpActionContext.Request.RequestUri = new Uri( string.Format( "http://host{0}?{1}={2}", requestPath, LoginConstants.QueryString.XsrfToken, xsrfCookie.Value), UriKind.Absolute); HttpContext.Current = BuildHttpContext(); securedAttribute = new SecuredAttribute(); securedAttribute.OnAuthorization(httpActionContext); if (expectExtension) { Assert.That(HttpContext.Current.Response.Cookies.AllKeys, Is.EquivalentTo(new[] { FormsAuthentication.FormsCookieName, LoginConstants.Cookie.AngularDefaultXsrfCookieName })); } else { Assert.That(HttpContext.Current.Response.Cookies.AllKeys, Is.Empty); } }
private static void AddFakeLoginTokens(HttpWebRequest request, string host, UserAccount userAccount) { var context = RequestContext.GetContext( ); string userName; long userId; if (userAccount == null) { userName = context.Identity.Name; userId = context.Identity.Id; } else { userName = userAccount.Name; userId = userAccount.Id; } string key = userName; long readiNowIdentityProvider = WellKnownAliases.CurrentTenant.ReadiNowIdentityProviderInstance; Func <string, CookieInfo> getCookie = key1 => { HttpCookie authCookie; HttpCookie xsrfCookie; CookieHelper.CreateAuthenticationAndXsrfCookies( context.Tenant.Id, readiNowIdentityProvider, userName, userId, false, // Not persistent null, // Create new XSRF token, DateTime.Now, // Issue date DateTime.Now.AddMinutes(LoginConstants.Cookie.Timeout), // Expiry out authCookie, out xsrfCookie); Cookie authCookie2 = ToCookie(authCookie); Cookie xsrfCookie2 = ToCookie(xsrfCookie); var cookieInfo = new CookieInfo { AuthCookie = authCookie2, XsrfCookie = xsrfCookie2, Expires = authCookie2.Expires }; return(cookieInfo); }; // Get the cookieData if (key != null) { CookieInfo cookieData = Cookies.GetOrAdd(key, getCookie); if (cookieData.Expires < DateTime.Now.AddSeconds(10)) { // Refetch if expired cookieData = Cookies.AddOrUpdate(key, getCookie, (key2, old) => getCookie(key2)); } var uri = new Uri(host); request.CookieContainer = new CookieContainer( ); request.CookieContainer.Add(uri, cookieData.AuthCookie); request.CookieContainer.Add(uri, cookieData.XsrfCookie); request.Headers.Add(LoginConstants.Headers.AngularJsXsrfToken, cookieData.XsrfCookie.Value); } }
public void Test_CreateAuthenticationAndXsrfCookies_InvalidUserId() { Assert.That(() => CookieHelper.CreateAuthenticationAndXsrfCookies(5, 5, "name", 0, true, "a"), Throws.TypeOf <ArgumentOutOfRangeException>().And.Property("ParamName").EqualTo("userAccountId")); }
public void Test_CreateAuthenticationAndXsrfCookies_EmptyIdentityProviderUser() { Assert.That(() => CookieHelper.CreateAuthenticationAndXsrfCookies(5, 5, "", 0, true, "a"), Throws.TypeOf <ArgumentNullException>().And.Property("ParamName").EqualTo("identityProviderUser")); }
// ReSharper disable once InconsistentNaming public async Task <IHttpActionResult> OidcAuthResponseCallback(string tenant, string code = null, string state = null, string error = null, string error_description = null) { OpenIdConnectAuthorizationState authState = null; try { if (!string.IsNullOrWhiteSpace(error)) { return(BadRequest($"An error occurred during authorization. Error:{error}. Description:{error_description}")); } if (string.IsNullOrWhiteSpace(tenant)) { throw new WebArgumentNullException("tenant", "The tenant was not specified"); } if (string.IsNullOrWhiteSpace(code)) { throw new WebArgumentNullException("code", "The code was not specified"); } if (string.IsNullOrWhiteSpace(state)) { throw new WebArgumentNullException("state", "The state was not specified"); } // For some reason ADFS is replacing the + signs (even the encoded ones) with spaces, so we undo it. // State is Base64 encoded so it should not contain spaces. if (!string.IsNullOrWhiteSpace(state)) { state = state.Replace(' ', '+'); } var oidcLoginHandler = new OpenIdConnectLoginHandler(OpenIdConnectConfigurationManager); if (oidcLoginHandler.IsTokenValidationDisabled) { EventLog.Application.WriteError("OpenIdConnectLoginHandler has token validation disabled. This is not be used in production."); throw new AuthenticationException(); } // Validate the state. authState = oidcLoginHandler.ValidateAuthState(state); using (var httpClient = new BasicHttpClient()) { // Process the authorization response. var result = await oidcLoginHandler.ProcessOidcAuthorizationResponse(tenant, code, authState, new Uri(Request.RequestUri.GetLeftPart(UriPartial.Authority)), httpClient); CookieHelper.CreateAuthenticationAndXsrfCookies(authState.TenantId, authState.IdentityProviderId, result.IdentityProviderUserName, result.RequestContextData.Identity.Id, true); } return(Redirect(authState.RedirectUrl)); } catch (Exception exception) { var oidcConfigException = exception as OidcProviderInvalidConfigurationException; EventLog.Application.WriteError("Failed to process oidc authorization response. Error: {0}", exception.ToString()); CookieHelper.DeleteAuthenticationAndXsrfCookies(); if (!string.IsNullOrWhiteSpace(authState?.RedirectUrl)) { string delimiter = authState.RedirectUrl.Contains("?") ? "&" : "?"; string errorType = oidcConfigException != null ? "idpconfigerror" : "autherror"; return(Redirect(authState.RedirectUrl + delimiter + "error=" + errorType)); } return(Unauthorized()); } }
/// <summary> /// Signs a software platform user into the system. /// </summary> /// <param name="jsonLoginCredential">The json login credential.</param> /// <returns></returns> private HttpResponseMessage <LoginResult> SigninSoftwarePlatform(JsonLoginCredential jsonLoginCredential) { var userAgent = Request?.Headers?.UserAgent?.ToString(); try { using (new SecurityBypassContext( )) { try { UserAccountValidator.Authenticate(jsonLoginCredential.Username, jsonLoginCredential.Password, jsonLoginCredential.Tenant, true); } catch (ArgumentException ex) { throw new InvalidCredentialException("Invalid user name, password or tenant", ex); } RequestContext context = ReadiNow.IO.RequestContext.GetContext( ); RequestContextData contextData; UserAccount account = ReadiNow.Model.Entity.Get <UserAccount>(context.Identity.Id, true); if (account != null) { ///// // If we are in integration test mode, update the test authorization info. ///// if (TestAuthorization.IsEnabled) { TestAuthorization.Instance.SetTokenIdentifier(context.Tenant.Id, WellKnownAliases.CurrentTenant.ReadiNowIdentityProviderInstance, account.Name); } // Update cache contextData = Factory.IdentityProviderRequestContextCache.GetRequestContextData(ReadiNow.IO.RequestContext.TenantId, WellKnownAliases.CurrentTenant.ReadiNowIdentityProviderInstance, jsonLoginCredential.Username, true); } else { throw new InvalidOperationException("No UserAccount found."); } ReadiNowIdentityProvider identityProvider = ReadiNow.Model.Entity.Get <ReadiNowIdentityProvider>(WellKnownAliases.CurrentTenant.ReadiNowIdentityProviderInstance); if (!(identityProvider.IsProviderEnabled ?? true)) { throw new AuthenticationException("The identity provider is not enabled."); } contextData.Identity.IdentityProviderTypeAlias = LoginConstants.ReadiNowIdentityProviderTypeAlias; CookieHelper.CreateAuthenticationAndXsrfCookies(ReadiNow.IO.RequestContext.TenantId, WellKnownAliases.CurrentTenant.ReadiNowIdentityProviderInstance, jsonLoginCredential.Username, account.Id, jsonLoginCredential.Persistent); AuditLogInstance.Get().OnLogon(true, jsonLoginCredential.Username, userAgent); return(new HttpResponseMessage <LoginResult>(GetSuccessfulLoginResult(contextData, account.Id), HttpStatusCode.OK)); } } catch (Exception exc) { if (ReadiNow.IO.RequestContext.IsSet) { AuditLogInstance.Get().OnLogon(false, jsonLoginCredential.Username, userAgent); } EventLog.Application.WriteWarning("Software Platform login error. Username: {0}, Tenant: {1}. {2}", jsonLoginCredential.Username ?? "<null>", jsonLoginCredential.Tenant ?? "<null>", exc.Message); throw; // rely on the ExceptionFilter to handle it. } }