private async Task <IActionResult> ResponseUpPartyAsync(string upPartyName, PartyTypes upPartyType) { logger.ScopeTrace(() => $"Single Logout response, Up type {upPartyType}."); var partyId = await UpParty.IdFormatAsync(RouteBinding, upPartyName); logger.SetScopeProperty(Constants.Logs.UpPartyId, partyId); switch (upPartyType) { case PartyTypes.Login: return(HttpContext.GetUpPartyUrl(upPartyName, Constants.Routes.LoginController, Constants.Endpoints.SingleLogoutDone, includeSequence: true).ToRedirectResult()); case PartyTypes.Oidc: var oidcUpParty = await tenantRepository.GetAsync <UpParty>(partyId); return(HttpContext.GetUpPartyUrl(upPartyName, Constants.Routes.OAuthController, Constants.Endpoints.SingleLogoutDone, includeSequence: true, partyBindingPattern: oidcUpParty.PartyBindingPattern).ToRedirectResult()); case PartyTypes.Saml2: var samlUpParty = await tenantRepository.GetAsync <UpParty>(partyId); return(HttpContext.GetUpPartyUrl(upPartyName, Constants.Routes.SamlController, Constants.Endpoints.SingleLogoutDone, includeSequence: true, partyBindingPattern: samlUpParty.PartyBindingPattern).ToRedirectResult()); default: throw new NotSupportedException(); } }
private void Save(UpParty party, TMessage message, DateTimeOffset?persistentCookieExpires) { CheckRouteBinding(); if (message == null) { new ArgumentNullException(nameof(message)); } logger.ScopeTrace(() => $"Save Cookie '{typeof(TMessage).Name}', Route '{RouteBinding.Route}'."); var cookieOptions = new CookieOptions { Secure = true, HttpOnly = true, SameSite = message.SameSite, IsEssential = true, Path = GetPath(party), }; if (persistentCookieExpires != null) { cookieOptions.Expires = persistentCookieExpires; } httpContextAccessor.HttpContext.Response.Cookies.Append( CookieName(), new CookieEnvelope <TMessage> { Message = message, }.ToCookieString(CreateProtector()), cookieOptions); }
public async Task <IActionResult> AuthnRequestAsync(UpPartyLink partyLink, LoginRequest loginRequest) { logger.ScopeTrace("Up, SAML Authn request."); var partyId = await UpParty.IdFormat(RouteBinding, partyLink.Name); logger.SetScopeProperty("upPartyId", partyId); await loginRequest.ValidateObjectAsync(); await sequenceLogic.SaveSequenceDataAsync(new SamlUpSequenceData { DownPartyId = loginRequest.DownParty.Id, DownPartyType = loginRequest.DownParty.Type, }); var party = await tenantRepository.GetAsync <SamlUpParty>(partyId); switch (party.AuthnBinding.RequestBinding) { case SamlBindingType.Redirect: return(await AuthnRequestAsync(party, new Saml2RedirectBinding(), loginRequest)); case SamlBindingType.Post: return(await AuthnRequestAsync(party, new Saml2PostBinding(), loginRequest)); default: throw new NotSupportedException($"Binding '{party.AuthnBinding.RequestBinding}' not supported."); } }
public async Task <bool> ValidateModelAllowUpPartiesAsync(ModelStateDictionary modelState, string propertyName, DownParty downParty) { var isValid = true; if (downParty.AllowUpParties?.Count() > 0) { foreach (var upPartyLink in downParty.AllowUpParties) { try { var upParty = await tenantService.GetAsync <UpParty>(await UpParty.IdFormatAsync(RouteBinding, upPartyLink.Name)); upPartyLink.Type = upParty.Type; } catch (CosmosDataException ex) { if (ex.StatusCode == HttpStatusCode.NotFound) { isValid = false; var errorMessage = $"Allow up-party '{upPartyLink.Name}' not found."; logger.Warning(ex, errorMessage); modelState.TryAddModelError(propertyName.ToCamelCase(), errorMessage); } else { throw; } } } } return(isValid); }
public async Task <UpParty> GetUpPartyByNameAsync(Party.IdKey idKey, bool required = true) { if (idKey == null) { new ArgumentNullException(nameof(idKey)); } return(await ReadItemAsync <UpParty>(await UpParty.IdFormatAsync(idKey), DataDocument.PartitionIdFormat(idKey), required)); }
private void UpMapping() { CreateMap <LoginUpParty, Api.LoginUpParty>() .ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name)) .ReverseMap() .ForMember(d => d.Id, opt => opt.MapFrom(s => UpParty.IdFormat(RouteBinding, s.Name).GetAwaiter().GetResult())); CreateMap <SamlUpParty, Api.SamlUpParty>() .ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name)) .ReverseMap() .ForMember(d => d.Id, opt => opt.MapFrom(s => UpParty.IdFormat(RouteBinding, s.Name).GetAwaiter().GetResult())); }
private void Delete(UpParty party, bool tryDelete = false) { if (tryDelete && RouteBindingDoNotExists()) { return; } CheckRouteBinding(); logger.ScopeTrace(() => $"Delete Cookie '{typeof(TMessage).Name}', Route '{RouteBinding.Route}'."); DeleteByName(party, CookieName()); }
private void DeleteByName(UpParty party, string name) { httpContextAccessor.HttpContext.Response.Cookies.Append( name, string.Empty, new CookieOptions { Expires = DateTimeOffset.UtcNow.AddMonths(-1), Secure = true, HttpOnly = true, SameSite = new TMessage().SameSite, IsEssential = true, Path = GetPath(party), }); }
private Task <string> GetId(string name) { if (EqualsBaseType(0, typeof(MParty), (typeof(UpParty)))) { return(UpParty.IdFormat(RouteBinding, name)); } else if (EqualsBaseType(0, typeof(MParty), (typeof(DownParty)))) { return(DownParty.IdFormat(RouteBinding, name)); } else { throw new NotSupportedException($"{typeof(MParty)} type not supported."); } }
protected DateTimeOffset?GetPersistentCookieExpires(UpParty upParty, long created) { if (upParty.PersistentSessionLifetimeUnlimited) { return(DateTimeOffset.FromUnixTimeSeconds(created).AddYears(settings.PersistentSessionMaxUnlimitedLifetimeYears)); } else if (upParty.PersistentSessionAbsoluteLifetime > 0) { return(DateTimeOffset.FromUnixTimeSeconds(created).AddSeconds(upParty.PersistentSessionAbsoluteLifetime)); } else { return(null); } }
private TMessage Get(UpParty party, bool delete, bool tryGet = false) { if (tryGet && RouteBindingDoNotExists()) { return(null); } CheckRouteBinding(); logger.ScopeTrace(() => $"Get Cookie '{typeof(TMessage).Name}', Route '{RouteBinding.Route}', Delete '{delete}'."); var cookie = httpContextAccessor.HttpContext.Request.Cookies[CookieName()]; if (!cookie.IsNullOrWhiteSpace()) { try { var envelope = CookieEnvelope <TMessage> .FromCookieString(CreateProtector(), cookie); if (delete) { logger.ScopeTrace(() => $"Delete Cookie, '{typeof(TMessage).Name}', Route '{RouteBinding.Route}'."); DeleteByName(party, CookieName()); } return(envelope.Message); } catch (CryptographicException ex) { logger.Warning(ex, $"Unable to Unprotect Cookie '{typeof(TMessage).Name}', deleting cookie."); DeleteByName(party, CookieName()); return(null); } catch (Exception ex) { throw new Exception($"Unable to Read Cookie '{typeof(TMessage).Name}'.", ex); } } else { return(null); } }
public async Task <IActionResult> EndSessionRequestRedirectAsync(UpPartyLink partyLink, LogoutRequest logoutRequest) { logger.ScopeTrace("Up, OIDC End session request redirect."); var partyId = await UpParty.IdFormatAsync(RouteBinding, partyLink.Name); logger.SetScopeProperty("upPartyId", partyId); await logoutRequest.ValidateObjectAsync(); await sequenceLogic.SaveSequenceDataAsync(new OidcUpSequenceData { DownPartyLink = logoutRequest.DownPartyLink, UpPartyId = partyId, SessionId = logoutRequest.SessionId, RequireLogoutConsent = logoutRequest.RequireLogoutConsent, PostLogoutRedirect = logoutRequest.PostLogoutRedirect, }); return(HttpContext.GetUpPartyUrl(partyLink.Name, Constants.Routes.OAuthUpJumpController, Constants.Endpoints.UpJump.EndSessionRequest, includeSequence: true).ToRedirectResult()); }
public async Task <IActionResult> AuthnRequestRedirectAsync(UpPartyLink partyLink, LoginRequest loginRequest) { logger.ScopeTrace("Up, SAML Authn request redirect."); var partyId = await UpParty.IdFormatAsync(RouteBinding, partyLink.Name); logger.SetScopeProperty("upPartyId", partyId); await loginRequest.ValidateObjectAsync(); await sequenceLogic.SaveSequenceDataAsync(new SamlUpSequenceData { DownPartyLink = loginRequest.DownPartyLink, UpPartyId = partyId, LoginAction = loginRequest.LoginAction, UserId = loginRequest.UserId, MaxAge = loginRequest.MaxAge }); return(HttpContext.GetUpPartyUrl(partyLink.Name, Constants.Routes.SamlUpJumpController, Constants.Endpoints.UpJump.AuthnRequest, includeSequence: true).ToRedirectResult()); }
public async Task <IActionResult> LogoutRedirect(UpPartyLink partyLink, LogoutRequest logoutRequest) { logger.ScopeTrace("Down, Logout redirect."); var partyId = await UpParty.IdFormat(RouteBinding, partyLink.Name); logger.SetScopeProperty("upPartyId", partyId); await logoutRequest.ValidateObjectAsync(); await sequenceLogic.SaveSequenceDataAsync(new LoginUpSequenceData { DownPartyId = logoutRequest.DownParty.Id, DownPartyType = logoutRequest.DownParty.Type, UpPartyId = partyId, SessionId = logoutRequest.SessionId, RequireLogoutConsent = logoutRequest.RequireLogoutConsent, PostLogoutRedirect = logoutRequest.PostLogoutRedirect }); return(new RedirectResult($"~/{RouteBinding.TenantName}/{RouteBinding.TrackName}/({partyLink.Name})/login/logout/_{HttpContext.GetSequenceString()}")); }
private void UpPartyMapping() { CreateMap <LoginUpParty, Api.LoginUpParty>() .ReverseMap() .ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name.ToLower())) .ForMember(d => d.Id, opt => opt.MapFrom(s => UpParty.IdFormatAsync(RouteBinding, s.Name.ToLower()).GetAwaiter().GetResult())); CreateMap <OidcUpParty, Api.OidcUpParty>() .ReverseMap() .ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name.ToLower())) .ForMember(d => d.Id, opt => opt.MapFrom(s => UpParty.IdFormatAsync(RouteBinding, s.Name.ToLower()).GetAwaiter().GetResult())); CreateMap <OidcUpClient, Api.OidcUpClient>() .ReverseMap() .ForMember(d => d.Scopes, opt => opt.MapFrom(s => s.Scopes.OrderBy(s => s))) .ForMember(d => d.Claims, opt => opt.MapFrom(s => s.Claims.OrderBy(c => c))); CreateMap <SamlUpParty, Api.SamlUpParty>() .ForMember(d => d.AuthnRequestBinding, opt => opt.MapFrom(s => s.AuthnBinding.RequestBinding)) .ForMember(d => d.AuthnResponseBinding, opt => opt.MapFrom(s => s.AuthnBinding.ResponseBinding)) .ForMember(d => d.LogoutRequestBinding, opt => opt.MapFrom(s => s.LogoutBinding != null ? (Api.SamlBindingTypes?)s.LogoutBinding.RequestBinding: null)) .ForMember(d => d.LogoutResponseBinding, opt => opt.MapFrom(s => s.LogoutBinding != null ? (Api.SamlBindingTypes?)s.LogoutBinding.ResponseBinding: null)) .ReverseMap() .ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name.ToLower())) .ForMember(d => d.Id, opt => opt.MapFrom(s => UpParty.IdFormatAsync(RouteBinding, s.Name.ToLower()).GetAwaiter().GetResult())) .ForMember(d => d.Claims, opt => opt.MapFrom(s => s.Claims.OrderBy(c => c))) .ForMember(d => d.AuthnBinding, opt => opt.MapFrom(s => new SamlBinding { RequestBinding = s.AuthnRequestBinding.HasValue ? (SamlBindingTypes)s.AuthnRequestBinding.Value : SamlBindingTypes.Post, ResponseBinding = s.AuthnResponseBinding.HasValue ? (SamlBindingTypes)s.AuthnResponseBinding.Value : SamlBindingTypes.Post, })) .ForMember(d => d.LogoutBinding, opt => opt.MapFrom(s => new SamlBinding { RequestBinding = s.LogoutRequestBinding.HasValue ? (SamlBindingTypes)s.LogoutRequestBinding.Value : SamlBindingTypes.Post, ResponseBinding = s.LogoutResponseBinding.HasValue ? (SamlBindingTypes)s.LogoutResponseBinding.Value : SamlBindingTypes.Post, })) .ForMember(d => d.AuthnContextClassReferences, opt => opt.MapFrom(s => s.AuthnContextClassReferences.OrderBy(c => c))) .ForMember(d => d.MetadataNameIdFormats, opt => opt.MapFrom(s => s.MetadataNameIdFormats.OrderBy(f => f))) .ForMember(d => d.MetadataAttributeConsumingServices, opt => opt.MapFrom(s => s.MetadataAttributeConsumingServices.OrderBy(a => a.ServiceName.Name))) .ForMember(d => d.MetadataContactPersons, opt => opt.MapFrom(s => s.MetadataContactPersons.OrderBy(c => c.ContactType))); }
public async Task <IActionResult> LogoutRedirect(UpPartyLink partyLink, LogoutRequest logoutRequest) { logger.ScopeTrace(() => "Down, Logout redirect."); var partyId = await UpParty.IdFormatAsync(RouteBinding, partyLink.Name); logger.SetScopeProperty(Constants.Logs.UpPartyId, partyId); await logoutRequest.ValidateObjectAsync(); await sequenceLogic.SetUiUpPartyIdAsync(partyId); await sequenceLogic.SaveSequenceDataAsync(new LoginUpSequenceData { DownPartyLink = logoutRequest.DownPartyLink, UpPartyId = partyId, SessionId = logoutRequest.SessionId, RequireLogoutConsent = logoutRequest.RequireLogoutConsent, PostLogoutRedirect = logoutRequest.PostLogoutRedirect }); return(HttpContext.GetUpPartyUrl(partyLink.Name, Constants.Routes.LoginController, Constants.Endpoints.Logout, includeSequence: true).ToRedirectResult()); }
private void UpPartyMapping() { CreateMap <LoginUpParty, Api.LoginUpParty>() .ReverseMap() .ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name.ToLower())) .ForMember(d => d.Id, opt => opt.MapFrom(s => UpParty.IdFormatAsync(RouteBinding, s.Name.ToLower()).GetAwaiter().GetResult())); CreateMap <OidcUpParty, Api.OidcUpParty>() .ReverseMap() .ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name.ToLower())) .ForMember(d => d.Id, opt => opt.MapFrom(s => UpParty.IdFormatAsync(RouteBinding, s.Name.ToLower()).GetAwaiter().GetResult())); CreateMap <OidcUpClient, Api.OidcUpClient>() .ForMember(d => d.Scopes, opt => opt.MapFrom(s => s.Scopes.OrderBy(s => s))) .ForMember(d => d.Claims, opt => opt.MapFrom(s => s.Claims.OrderBy(c => c))) .ReverseMap(); CreateMap <SamlUpParty, Api.SamlUpParty>() .ForMember(d => d.Claims, opt => opt.MapFrom(s => s.Claims.OrderBy(c => c))) .ReverseMap() .ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name.ToLower())) .ForMember(d => d.Id, opt => opt.MapFrom(s => UpParty.IdFormatAsync(RouteBinding, s.Name.ToLower()).GetAwaiter().GetResult())); }
public async Task <IActionResult> AuthenticationRequestRedirectAsync(UpPartyLink partyLink, LoginRequest loginRequest) { logger.ScopeTrace(() => "Up, OIDC Authentication request redirect."); var partyId = await UpParty.IdFormatAsync(RouteBinding, partyLink.Name); logger.SetScopeProperty(Constants.Logs.UpPartyId, partyId); await loginRequest.ValidateObjectAsync(); var party = await tenantRepository.GetAsync <TParty>(partyId); var oidcUpSequenceData = new OidcUpSequenceData { DownPartyLink = loginRequest.DownPartyLink, UpPartyId = partyId, LoginAction = loginRequest.LoginAction, UserId = loginRequest.UserId, MaxAge = loginRequest.MaxAge }; await sequenceLogic.SaveSequenceDataAsync(oidcUpSequenceData); return(HttpContext.GetUpPartyUrl(partyLink.Name, Constants.Routes.OAuthUpJumpController, Constants.Endpoints.UpJump.AuthenticationRequest, includeSequence: true, partyBindingPattern: party.PartyBindingPattern).ToRedirectResult()); }
public async Task <IActionResult> LogoutRequestRedirectAsync(UpPartyLink partyLink, LogoutRequest logoutRequest) { logger.ScopeTrace(() => "Up, SAML Logout request."); var partyId = await UpParty.IdFormatAsync(RouteBinding, partyLink.Name); logger.SetScopeProperty(Constants.Logs.UpPartyId, partyId); await logoutRequest.ValidateObjectAsync(); var party = await tenantRepository.GetAsync <SamlUpParty>(partyId); await sequenceLogic.SaveSequenceDataAsync(new SamlUpSequenceData { DownPartyLink = logoutRequest.DownPartyLink, UpPartyId = partyId, SessionId = logoutRequest.SessionId, RequireLogoutConsent = logoutRequest.RequireLogoutConsent, PostLogoutRedirect = logoutRequest.PostLogoutRedirect, Claims = logoutRequest.Claims.ToClaimAndValues() }); return(HttpContext.GetUpPartyUrl(partyLink.Name, Constants.Routes.SamlUpJumpController, Constants.Endpoints.UpJump.LogoutRequest, includeSequence: true, partyBindingPattern: party.PartyBindingPattern).ToRedirectResult()); }
public async Task <IActionResult> LoginRedirectAsync(UpPartyLink partyLink, LoginRequest loginRequest) { logger.ScopeTrace("Up, Login redirect."); var partyId = await UpParty.IdFormat(RouteBinding, partyLink.Name); logger.SetScopeProperty("upPartyId", partyId); await loginRequest.ValidateObjectAsync(); await sequenceLogic.SaveSequenceDataAsync(new LoginUpSequenceData { DownPartyId = loginRequest.DownParty.Id, DownPartyType = loginRequest.DownParty.Type, UpPartyId = partyId, LoginAction = loginRequest.LoginAction, UserId = loginRequest.UserId, MaxAge = loginRequest.MaxAge, EmailHint = loginRequest.EmailHint, Culture = loginRequest.Culture }); return(new RedirectResult($"~/{RouteBinding.TenantName}/{RouteBinding.TrackName}/({partyLink.Name})/login/_{SequenceString}")); }
protected bool SessionValid(UpParty upParty, SessionBaseCookie session) { var created = DateTimeOffset.FromUnixTimeSeconds(session.CreateTime); var lastUpdated = DateTimeOffset.FromUnixTimeSeconds(session.LastUpdated); var now = DateTimeOffset.UtcNow; if (upParty.PersistentSessionLifetimeUnlimited) { return(true); } else if (created.AddSeconds(upParty.PersistentSessionAbsoluteLifetime) >= now) { return(true); } else if (lastUpdated.AddSeconds(upParty.SessionLifetime) >= now && (upParty.SessionAbsoluteLifetime <= 0 || created.AddSeconds(upParty.SessionAbsoluteLifetime) >= now)) { return(true); } else { return(false); } }
public async Task <IActionResult> LoginRedirectAsync(UpPartyLink partyLink, LoginRequest loginRequest) { logger.ScopeTrace(() => "Up, Login redirect."); var partyId = await UpParty.IdFormatAsync(RouteBinding, partyLink.Name); logger.SetScopeProperty(Constants.Logs.UpPartyId, partyId); await loginRequest.ValidateObjectAsync(); await sequenceLogic.SetUiUpPartyIdAsync(partyId); await sequenceLogic.SaveSequenceDataAsync(new LoginUpSequenceData { DownPartyLink = loginRequest.DownPartyLink, UpPartyId = partyId, LoginAction = loginRequest.LoginAction, UserId = loginRequest.UserId, MaxAge = loginRequest.MaxAge, Email = loginRequest.EmailHint, Acr = GetSupportedAcr(loginRequest), }); return(HttpContext.GetUpPartyUrl(partyLink.Name, Constants.Routes.LoginController, includeSequence: true).ToRedirectResult()); }
public Task SaveAsync(UpParty party, TMessage message, DateTimeOffset?persistentCookieExpires) { Save(party, message, persistentCookieExpires); return(Task.FromResult(0)); }
protected bool SessionEnabled(UpParty upParty) { return(upParty.SessionLifetime > 0 || upParty.PersistentSessionAbsoluteLifetime > 0 || upParty.PersistentSessionLifetimeUnlimited); }
public GeneralSamlUpPartyViewModel(UpParty upParty) : base(upParty) { }
public GeneralLoginUpPartyViewModel(UpParty upParty) : base(upParty) { }
private DownPartySessionLink GetDownPartyLink(UpParty upParty, LoginUpSequenceData sequenceData) => upParty.DisableSingleLogout ? null : sequenceData.DownPartyLink;
public GeneralUpPartyViewModel(UpParty upParty) { Name = upParty.Name; Type = upParty.Type; }
public GeneralOidcUpPartyViewModel(UpParty upParty) : base(upParty) { }
public Task DeleteAsync(UpParty party, bool tryDelete = false) { Delete(party, tryDelete); return(Task.FromResult(0)); }