public override async Task <CreateLdapCredentialReply> CreateLdapCredential(CreateLdapCredentialRequest request, ServerCallContext context) { Guid appId = new Guid(request.Id); Guid userId = new Guid(_userManager.GetUserId(context.GetHttpContext().User)); LdapAppSettings ldapAppSettings = await _authDbContext.LdapAppSettings .Where(a => a.AuthApp.UserGroups.Any(u => u.Members.Any(m => m.Id == userId))) .SingleAsync(l => l.AuthApp.Id == appId); AppUser user = await _userManager.GetUserAsync(context.GetHttpContext().User); string plainTextPassword = _secureRandom.GetRandomString(16); string hashedPassword = _hasher.Hash(plainTextPassword); LdapAppUserCredentials credentials = new LdapAppUserCredentials { HashedPassword = hashedPassword, LdapAppSettings = ldapAppSettings, User = user, }; _authDbContext.Add(credentials); await _authDbContext.SaveChangesAsync(); return(new CreateLdapCredentialReply { Password = plainTextPassword }); }
public override async Task <StartSetupReply> StartSetup(Empty request, ServerCallContext context) { bool isInstalled = await IsAlreadyInstalled(); string?existingAuthKey = await GetSetupAuthKey(); if (isInstalled || existingAuthKey != null) { return(new StartSetupReply { Success = false, }); } string newAuthKey = _secureRandom.GetRandomString(16); SystemSetting authKeySetting = new SystemSetting { Name = AUTH_KEY, Value = newAuthKey, }; _authDbContext.Add(authKeySetting); await _authDbContext.SaveChangesAsync(); return(new StartSetupReply { Success = true, AuthToken = newAuthKey, }); }
private async Task <string> SetNewAuthToken() { SystemSetting?authKeySetting = await _authDbContext.SystemSettings .SingleOrDefaultAsync(s => s.Name == AUTH_KEY); string newAuthKey = _secureRandom.GetRandomString(16); if (authKeySetting == null) { authKeySetting = new SystemSetting { Name = AUTH_KEY, }; _authDbContext.Add(authKeySetting); } authKeySetting.Value = newAuthKey; await _authDbContext.SaveChangesAsync(); return(newAuthKey); }
public override async Task <AddNewAppReply> AddNewApp(AddNewAppRequest request, ServerCallContext context) { AuthApp app = new AuthApp { Name = request.Name, Url = request.Url, Description = request.Description, }; _authDbContext.Add(app); switch (request.HostingType) { case HostingType.NonWeb: app.HostingType = AuthApp.HostingTypeEnum.NON_WEB; break; case HostingType.WebGatekeeperProxy: app.HostingType = AuthApp.HostingTypeEnum.WEB_GATEKEEPER_PROXY; break; case HostingType.WebGeneric: app.HostingType = AuthApp.HostingTypeEnum.WEB_GENERIC; break; default: throw new NotImplementedException("Auth mode is not implemented"); } switch (request.DirectoryChoice) { case AddNewAppRequest.Types.DirectoryChoice.NoneDirectory: app.DirectoryMethod = AuthApp.DirectoryMethodEnum.NONE; break; case AddNewAppRequest.Types.DirectoryChoice.LdapDirectory: app.DirectoryMethod = AuthApp.DirectoryMethodEnum.LDAP; break; case AddNewAppRequest.Types.DirectoryChoice.ScimDirectory: app.DirectoryMethod = AuthApp.DirectoryMethodEnum.SCIM; break; } switch (request.AuthChoice) { case AddNewAppRequest.Types.AuthChoice.LdapAuth: app.AuthMethod = AuthApp.AuthMethodEnum.LDAP; break; case AddNewAppRequest.Types.AuthChoice.OidcAuth: app.AuthMethod = AuthApp.AuthMethodEnum.OIDC; break; } if (app.AuthMethod == AuthApp.AuthMethodEnum.LDAP || app.DirectoryMethod == AuthApp.DirectoryMethodEnum.LDAP) { string assembledBaseDn = "dc=" + app.Id; string bindUserPassword = _ldapSettingsDataProtector.Protect(_secureRandom.GetRandomString(16)); string bindUser = "******" + assembledBaseDn; LdapAppSettings ldapAppSettings = new LdapAppSettings { AuthApp = app, UseForAuthentication = (app.AuthMethod == AuthApp.AuthMethodEnum.LDAP), UseForIdentity = (app.DirectoryMethod == AuthApp.DirectoryMethodEnum.LDAP), BaseDn = assembledBaseDn, BindUser = bindUser, BindUserPassword = bindUserPassword, }; _authDbContext.Add(ldapAppSettings); app.LdapAppSettings = ldapAppSettings; } if (app.HostingType == AuthApp.HostingTypeEnum.WEB_GATEKEEPER_PROXY) { ProxyAppSettings proxyAppSettings = new ProxyAppSettings { AuthApp = app, InternalHostname = request.ProxySetting.InternalHostname, PublicHostname = request.ProxySetting.PublicHostname, }; _authDbContext.Add(proxyAppSettings); app.ProxyAppSettings = proxyAppSettings; _configurationProvider.TryGet("tls.acme.support", out string isAcmeSupported); if (isAcmeSupported == "true") { // FIXME: Passing an empty email is a hack here. The email is already passed in InstallService. Could be refactored. BackgroundJob.Enqueue <IRequestAcmeCertificateJob>(job => job.Request("", request.ProxySetting.PublicHostname)); } } if (app.AuthMethod == AuthApp.AuthMethodEnum.OIDC) { OIDCAppSettings oidcAppSettings = new OIDCAppSettings { RedirectUrl = request.OidcSetting.RedirectUri, AuthApp = app, ClientId = Guid.NewGuid().ToString(), ClientSecret = _secureRandom.GetRandomString(32), Audience = "FIX_ME", }; _authDbContext.Add(oidcAppSettings); app.OidcAppSettings = oidcAppSettings; } if (app.DirectoryMethod == AuthApp.DirectoryMethodEnum.SCIM) { SCIMAppSettings scimAppSettings = new SCIMAppSettings { AuthApp = app, Endpoint = request.ScimSetting.Endpoint, Credentials = request.ScimSetting.Credentials, }; _authDbContext.Add(scimAppSettings); app.ScimAppSettings = scimAppSettings; } foreach (string groupId in request.GroupIds) { Guid groupIdGuid = new Guid(groupId); UserGroup group = await _authDbContext.UserGroup .Include(g => g.AuthApps) .SingleAsync(g => g.Id == groupIdGuid); group.AuthApps.Add(app); } await _authDbContext.SaveChangesAsync(); // fixme: this should be done outside a service await _memoryPopulator.PopulateFromDatabase(); return(new AddNewAppReply { Success = true, }); }
public async Task Invoke( HttpContext context, AuthenticationManager authenticationManager, SingleSignOnHandler singleSignOnHandler, ConfigurationProvider configurationProvider, SecureRandom secureRandom ) { MemorySingletonProxyConfigProvider.Route?route = GetMatchingRoute(context); if (route != null) { bool shouldHandle = true; PathString requestPath = context.Request.Path; if (requestPath.StartsWithSegments("/.well-known/acme-challenge")) { string challenge = ((string)requestPath).Split('/').Last(); if (_acmeChallengeSingleton.Challenges.ContainsKey(challenge)) { shouldHandle = false; } } if (shouldHandle) { configurationProvider.TryGet(AuthServer.Server.GRPC.InstallService.PRIMARY_DOMAIN_KEY, out string primaryDomain); bool isAuthRequest = singleSignOnHandler.IsAuthRequest(context); if (isAuthRequest) { singleSignOnHandler.Handle(context); return; } bool isPublicEndpoint = route.PublicRoutes.Contains(context.Request.Path); if (!isPublicEndpoint) { bool isAuthenticated = authenticationManager.IsAuthenticated(context, out Guid? sessionId); if (!isAuthenticated) { string csrf = secureRandom.GetRandomString(16); context.Response.Cookies.Append("gatekeeper.csrf", csrf); Dictionary <string, string> queryDictionary = new Dictionary <string, string>() { { "id", route.ProxySettingId.ToString() }, { "csrf", csrf }, }; UriBuilder uriBuilder = new UriBuilder(); uriBuilder.Scheme = "https"; uriBuilder.Host = primaryDomain; uriBuilder.Path = "/auth/sso-connect"; uriBuilder.Query = await((new System.Net.Http.FormUrlEncodedContent(queryDictionary)).ReadAsStringAsync()); context.Response.Redirect(uriBuilder.ToString(), false); return; } else { if (sessionId == null) { // This should never happen return; } bool isAuthorized = await authenticationManager.IsAuthorizedAsync((Guid)sessionId, route); if (!isAuthorized) { context.Response.Redirect("https://" + primaryDomain + "/auth/403"); return; } } } Dictionary <string, RequestHeaderTransform> requestHeaderTransforms = new Dictionary <string, RequestHeaderTransform>() { { "X-Forwarded-For", new RequestHeaderValueTransform(context.Connection.RemoteIpAddress.ToString(), append: false) }, { "X-Forwarded-Host", new RequestHeaderValueTransform(route.PublicHostname, append: false) }, { HeaderNames.Host, new RequestHeaderValueTransform(String.Empty, append: false) } }; if (context.Request.Cookies.TryGetValue(AuthenticationManager.AUTH_COOKIE, out string?authCookieValue)) { // FIXME: This is currently also sent as cookie. Remove this and only send it as header. requestHeaderTransforms.Add( "X-Gatekeeper-Jwt-Assertion", new RequestHeaderValueTransform(authCookieValue, append: false) ); } RequestProxyOptions proxyOptions = new RequestProxyOptions() { RequestTimeout = TimeSpan.FromSeconds(100), Transforms = new Transforms( copyRequestHeaders: true, requestTransforms: Array.Empty <RequestParametersTransform>(), requestHeaderTransforms: requestHeaderTransforms, responseHeaderTransforms: new Dictionary <string, ResponseHeaderTransform>(), responseTrailerTransforms: new Dictionary <string, ResponseHeaderTransform>() ) }; await _httpProxy.ProxyAsync(context, route.InternalHostname, _httpClient, proxyOptions); return; } } await _nextMiddleware(context); }
public void TestGetRandomString() { SecureRandom random = new SecureRandom(); Assert.Equal(23, random.GetRandomString(23).Length); }
public async Task Invoke( HttpContext context, AuthenticationManager authenticationManager, SingleSignOnHandler singleSignOnHandler, ConfigurationProvider configurationProvider, SecureRandom secureRandom ) { MemorySingletonProxyConfigProvider.Route?route = GetMatchingRoute(context); if (route != null) { bool shouldHandle = true; PathString requestPath = context.Request.Path; if (requestPath.StartsWithSegments("/.well-known/acme-challenge")) { string challenge = ((string)requestPath).Split('/').Last(); if (_acmeChallengeSingleton.Challenges.ContainsKey(challenge)) { shouldHandle = false; } } if (shouldHandle) { configurationProvider.TryGet(AuthServer.Server.GRPC.InstallService.PRIMARY_DOMAIN_KEY, out string primaryDomain); bool isAuthRequest = singleSignOnHandler.IsAuthRequest(context); if (isAuthRequest) { singleSignOnHandler.Handle(context); return; } bool isPublicEndpoint = route.PublicRoutes.Contains(context.Request.Path); if (!isPublicEndpoint) { bool isAuthenticated = authenticationManager.IsAuthenticated(context, out Guid? sessionId); if (!isAuthenticated) { string csrf = secureRandom.GetRandomString(16); context.Response.Cookies.Append("gatekeeper.csrf", csrf); Dictionary <string, string> queryDictionary = new Dictionary <string, string>() { { "id", route.ProxySettingId.ToString() }, { "csrf", csrf }, }; UriBuilder uriBuilder = new UriBuilder(); uriBuilder.Scheme = "https"; uriBuilder.Host = primaryDomain; uriBuilder.Path = "/auth/sso-connect"; uriBuilder.Query = await((new System.Net.Http.FormUrlEncodedContent(queryDictionary)).ReadAsStringAsync()); context.Response.Redirect(uriBuilder.ToString(), false); return; } else { if (sessionId == null) { // This should never happen return; } bool isAuthorized = await authenticationManager.IsAuthorizedAsync((Guid)sessionId, route); if (!isAuthorized) { context.Response.Redirect("https://" + primaryDomain + "/auth/403"); return; } } } RequestProxyOptions proxyOptions = new RequestProxyOptions( TimeSpan.FromSeconds(100), null ); await _httpProxy.ProxyAsync( context, route.InternalHostname, _httpClient, proxyOptions, new Gatekeeper.Server.Web.Services.ReverseProxy.Transformer.RequestTransformer(route) ); return; } } await _nextMiddleware(context); }