diff --git a/src/Yavsc.Abstract/Streaming/ILiveFlow.cs b/src/Yavsc.Abstract/Streaming/ILiveFlow.cs index 9a1bdd39..3835cc42 100644 --- a/src/Yavsc.Abstract/Streaming/ILiveFlow.cs +++ b/src/Yavsc.Abstract/Streaming/ILiveFlow.cs @@ -23,6 +23,8 @@ namespace Yavsc.Abstract.Streaming // A name where to save this stream, relative to user's files root string DifferedFileName { get; set; } + int SequenceNumber { get; set; } + [Required] string OwnerId {get; set; } diff --git a/src/Yavsc.Server/Constants.cs b/src/Yavsc.Server/Constants.cs index 3266a470..aae4a2b0 100644 --- a/src/Yavsc.Server/Constants.cs +++ b/src/Yavsc.Server/Constants.cs @@ -11,6 +11,9 @@ namespace Yavsc TokenPath = "~/token", LoginPath = "~/signin", LogoutPath = "~/signout", UserInfoPath = "~/api/me", + + SignalRPath = "/api/signalr", + ApplicationAuthenticationSheme = "ServerCookie", ExternalAuthenticationSheme= "ExternalCookie", CompanyInfoUrl = " https://societeinfo.com/app/rest/api/v1/company/json?registration_number={0}&key={1}", diff --git a/src/Yavsc.Server/Models/Messaging/LiveFlow.cs b/src/Yavsc.Server/Models/Messaging/LiveFlow.cs index 5dda4efd..64c25705 100644 --- a/src/Yavsc.Server/Models/Messaging/LiveFlow.cs +++ b/src/Yavsc.Server/Models/Messaging/LiveFlow.cs @@ -13,17 +13,26 @@ namespace Yavsc.Models.Streaming // set by the server, unique public long Id { get; set; } - // a title for this flow + // + /// + /// a title for this flow + /// + /// + [StringLength(255)] public string Title { get; set; } // a little description + [StringLength(1023)] public string Pitch { get; set; } // The stream type + [StringLength(127)] public string MediaType { get; set; } // A name where to save this stream, relative to user's files root + [StringLength(255)] public string DifferedFileName { get; set; } + public int SequenceNumber { get; set; } [Required] public string OwnerId {get; set; } diff --git a/src/Yavsc/ApiControllers/Streaming/LiveApiController.cs b/src/Yavsc/ApiControllers/Streaming/LiveApiController.cs index 20f351e4..4fadac2d 100644 --- a/src/Yavsc/ApiControllers/Streaming/LiveApiController.cs +++ b/src/Yavsc/ApiControllers/Streaming/LiveApiController.cs @@ -8,15 +8,17 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNet.Http; using Microsoft.AspNet.Mvc; +using Microsoft.AspNet.SignalR; using Microsoft.Data.Entity; using Microsoft.Extensions.Logging; +using Yavsc.Helpers; using Yavsc.Models; using Yavsc.Models.Streaming; using Yavsc.ViewModels.Streaming; namespace Yavsc.Controllers { - [Route("api/LiveApi")] + [Route("api/live")] public class LiveApiController : Controller { public static ConcurrentDictionary Casters = new ConcurrentDictionary(); @@ -37,7 +39,10 @@ namespace Yavsc.Controllers _dbContext = context; _logger = loggerFactory.CreateLogger(); } - + public async Task GetFileNameHint(string id) + { + return await _dbContext.Tags.Where( t=> t.Name.StartsWith(id)).Select(t=>t.Name).Take(25).ToArrayAsync(); + } public async Task GetLive(string id) { @@ -69,7 +74,7 @@ namespace Yavsc.Controllers } var uid = User.GetUserId(); // get some setup from user - var flow = _dbContext.LiveFlow.SingleOrDefault(f=> (f.OwnerId==uid && f.Id == id)); + var flow = _dbContext.LiveFlow.Include(f=>f.Owner).SingleOrDefault(f=> (f.OwnerId==uid && f.Id == id)); if (flow == null) { ModelState.AddModelError("error",$"You don't own any flow with the id {id}"); @@ -92,6 +97,11 @@ namespace Yavsc.Controllers WebSocketReceiveResult received = await meta.Socket.ReceiveAsync (new ArraySegment(buffer), CancellationToken.None); + var hubContext = GlobalHost.ConnectionManager.GetHubContext(); + + hubContext.Clients.All.addPublicStream(new { id = flow.Id, sender = flow.Owner.UserName, title = flow.Title, url = flow.GetFileUrl(), + mediaType = flow.MediaType }, $"{flow.Owner.UserName} is starting a stream!"); + // FIXME do we really need to close those one in invalid state ? Stack ToClose = new Stack(); @@ -148,7 +158,6 @@ namespace Yavsc.Controllers } - // GET: api/LiveApi/5 [HttpGet("{id}", Name = "GetLiveFlow")] public async Task GetLiveFlow([FromRoute] long id) { @@ -167,7 +176,6 @@ namespace Yavsc.Controllers return Ok(liveFlow); } - // PUT: api/LiveApi/5 [HttpPut("{id}")] public async Task PutLiveFlow([FromRoute] long id, [FromBody] LiveFlow liveFlow) { @@ -208,7 +216,6 @@ namespace Yavsc.Controllers return new HttpStatusCodeResult(StatusCodes.Status204NoContent); } - // POST: api/LiveApi [HttpPost] public async Task PostLiveFlow([FromBody] LiveFlow liveFlow) { diff --git a/src/Yavsc/Extensions/SignalRBuilderExtension.cs b/src/Yavsc/Extensions/SignalRBuilderExtension.cs index aa224739..00e8151d 100644 --- a/src/Yavsc/Extensions/SignalRBuilderExtension.cs +++ b/src/Yavsc/Extensions/SignalRBuilderExtension.cs @@ -37,8 +37,9 @@ namespace Yavsc app.UseAppBuilder(appBuilder => appBuilder.MapSignalR( path, new HubConfiguration() { - EnableDetailedErrors = false, - EnableJSONP = false + EnableDetailedErrors = true, + EnableJSONP = true, + EnableJavaScriptProxies = true } )); } diff --git a/src/Yavsc/Helpers/FileSystemHelpers.cs b/src/Yavsc/Helpers/FileSystemHelpers.cs index 1d09541f..5fdfb07e 100644 --- a/src/Yavsc/Helpers/FileSystemHelpers.cs +++ b/src/Yavsc/Helpers/FileSystemHelpers.cs @@ -12,6 +12,7 @@ using Yavsc.Abstract.FileSystem; using Yavsc.Exceptions; using Yavsc.Models; using Yavsc.Models.FileSystem; +using Yavsc.Models.Streaming; using Yavsc.ViewModels; namespace Yavsc.Helpers @@ -188,6 +189,16 @@ public static FileRecievedInfo ReceiveProSignature(this ClaimsPrincipal user, st return item; } - + public static string GetFileUrl (this LiveFlow flow) + { + if (flow.DifferedFileName==null) + // no server-side backup for this stream + return null; + var fileInfo = new FileInfo(flow.DifferedFileName); + var ext = fileInfo.Extension; + var namelen = flow.DifferedFileName.Length - ext.Length; + var basename = flow.DifferedFileName.Substring(0,namelen); + return $"{Startup.UserFilesOptions.RequestPath}/{flow.Owner.UserName}/live/{basename}-{flow.SequenceNumber}{ext}"; + } } } diff --git a/src/Yavsc/Hubs/ChatHub.cs b/src/Yavsc/Hubs/ChatHub.cs index ef9aebb7..fa08ace6 100644 --- a/src/Yavsc/Hubs/ChatHub.cs +++ b/src/Yavsc/Hubs/ChatHub.cs @@ -22,19 +22,16 @@ using Microsoft.AspNet.SignalR; using System.Threading.Tasks; using System.Collections.Generic; using System.Linq; -using System.Security.Claims; namespace Yavsc { using System; - using System.Threading; using Microsoft.AspNet.Authorization; using Microsoft.Data.Entity; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Models; using Models.Chat; - using Yavsc.ViewModels.Auth; public class ChatHub : Hub, IDisposable { @@ -49,7 +46,7 @@ namespace Yavsc _logger = loggerFactory.CreateLogger(); } - public override Task OnConnected() + public override async Task OnConnected() { bool isAuth = false; string userName = null; @@ -60,27 +57,35 @@ namespace Yavsc var group = isAuth ? "authenticated" : "anonymous"; // Log ("Cx: " + group); - Groups.Add(Context.ConnectionId, group); + await Groups.Add(Context.ConnectionId, group); if (isAuth) { - - var user = _dbContext.Users.Single(u => u.UserName == userName); + /* + var user = _dbContext.Users.Include(u=>u.Connections).Single(u => u.UserName == userName); if (user.Connections==null) user.Connections = new List(); - user.Connections.Add(new ChatConnection - { - ConnectionId = Context.ConnectionId, - UserAgent = Context.Request.Headers["User-Agent"], - Connected = true - }); - _dbContext.SaveChanges(); + var ucx = user.Connections.FirstOrDefault(c=>c.ConnectionId == Context.ConnectionId); + if (ucx==null) + user.Connections.Add(new ChatConnection + { + ConnectionId = Context.ConnectionId, + UserAgent = Context.Request.Headers["User-Agent"], + Connected = true + }); + else { + ucx.Connected = true; + } + _dbContext.SaveChanges(); + + Clients.CallerState.BlackListedBy = await _dbContext.BlackListed.Where(r=>r.UserId == user.Id).Select(r=>r.OwnerId).ToArrayAsync(); + */ } } - else Groups.Add(Context.ConnectionId, "anonymous"); + else await Groups.Add(Context.ConnectionId, "anonymous"); Clients.Group("authenticated").notify("connected", Context.ConnectionId, userName); - return base.OnConnected(); + await OnConnected(); } public override Task OnDisconnected(bool stopCalled) @@ -140,7 +145,7 @@ namespace Yavsc { string uname = (Context.User != null) ? $"[{Context.User.Identity.Name}]" : - $"({name})"; + $"?{name}"; Clients.All.addMessage(uname, message); } @@ -149,22 +154,18 @@ namespace Yavsc [Authorize] public async void SendPV(string connectionId, string message) { - // TODO personal black|white list + - // Contact list allowed only + - // only pro - string destUserId = (await _dbContext.ChatConnection.SingleAsync (c=>c.ConnectionId == connectionId)).ApplicationUserId; - - var sender = Context.User.Identity.Name; - var allow = await AllowPv(connectionId); - if (!allow) { - Clients.Caller.addPV(sender, "[private message was refused]"); - return; + if (Clients.CallerState.BlackListedBy!=null) + foreach (string destId in Clients.CallerState.BlackListedBy) + { + if (_dbContext.ChatConnection.Any(c => c.ConnectionId == connectionId && c.ApplicationUserId == destId )) + { + _logger.LogInformation($"PV aborted by black list"); + Clients.Caller.send("denied"); + return ; + } } - - var hubCxContext = Clients.User(connectionId); - var cli = Clients.Client(connectionId); - cli.addPV(sender, message); + cli.addPV(Context.User.Identity.Name, message); } private async Task AllowPv(string destConnectionId) diff --git a/src/Yavsc/Startup/Startup.OAuth.cs b/src/Yavsc/Startup/Startup.OAuth.cs index 3dda30a4..4c4941f5 100644 --- a/src/Yavsc/Startup/Startup.OAuth.cs +++ b/src/Yavsc/Startup/Startup.OAuth.cs @@ -1,33 +1,31 @@ using System; using System.Security.Claims; +using Google.Apis.Auth.OAuth2.Responses; +using Google.Apis.Util.Store; using Microsoft.AspNet.Authentication; using Microsoft.AspNet.Authentication.Cookies; using Microsoft.AspNet.Authentication.Facebook; -using Microsoft.AspNet.Authentication.Twitter; using Microsoft.AspNet.Authentication.JwtBearer; using Microsoft.AspNet.Authentication.OAuth; +using Microsoft.AspNet.Authentication.Twitter; using Microsoft.AspNet.Builder; using Microsoft.AspNet.Http; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.EntityFramework; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.OptionsModel; using Microsoft.Extensions.WebEncoders; using OAuth.AspNet.AuthServer; using OAuth.AspNet.Tokens; -using Google.Apis.Util.Store; -using Microsoft.Extensions.Logging; -using Google.Apis.Auth.OAuth2.Responses; -namespace Yavsc -{ +namespace Yavsc { using Auth; using Extensions; - using Models; using Helpers.Google; + using Models; - public partial class Startup - { + public partial class Startup { public static CookieAuthenticationOptions ExternalCookieAppOptions { get; private set; } public static IdentityOptions IdentityAppOptions { get; set; } @@ -36,194 +34,174 @@ namespace Yavsc public static TwitterOptions TwitterAppOptions { get; private set; } public static OAuthAuthorizationServerOptions OAuthServerAppOptions { get; private set; } - public static YavscGoogleOptions YavscGoogleAppOptions { get; private set; } public static MonoDataProtectionProvider ProtectionProvider { get; private set; } // public static CookieAuthenticationOptions BearerCookieOptions { get; private set; } - private void ConfigureOAuthServices(IServiceCollection services) + private void ConfigureOAuthServices (IServiceCollection services) { - services.Configure(options => options.SignInScheme = Constants.ApplicationAuthenticationSheme); + services.Configure (options => options.SignInScheme = Constants.ApplicationAuthenticationSheme); - services.Add(ServiceDescriptor.Singleton(typeof(IOptions), typeof(OptionsManager))); + services.Add (ServiceDescriptor.Singleton (typeof (IOptions), typeof (OptionsManager))); // used by the YavscGoogleOAuth middelware (TODO drop it) - services.AddTransient(); - - services.AddAuthentication(options => - { + services.AddTransient (); + + services.AddAuthentication (options => { options.SignInScheme = Constants.ExternalAuthenticationSheme; }); - ProtectionProvider = new MonoDataProtectionProvider(Configuration["Site:Title"]); ; + ProtectionProvider = new MonoDataProtectionProvider (Configuration["Site:Title"]);; services.AddInstance - (ProtectionProvider); - - services.AddIdentity( - option => - { - IdentityAppOptions = option; - option.User.AllowedUserNameCharacters += " "; - option.User.RequireUniqueEmail = true; - // option.Cookies.ApplicationCookieAuthenticationScheme = Constants.ApplicationAuthenticationSheme; - option.Cookies.ApplicationCookie.LoginPath = "/signin"; - // option.Cookies.ApplicationCookie.AuthenticationScheme = Constants.ApplicationAuthenticationSheme; - /* - option.Cookies.ApplicationCookie.DataProtectionProvider = protector; - option.Cookies.ApplicationCookie.LoginPath = new PathString(Constants.LoginPath.Substring(1)); - option.Cookies.ApplicationCookie.AccessDeniedPath = new PathString(Constants.AccessDeniedPath.Substring(1)); - option.Cookies.ApplicationCookie.AutomaticAuthenticate = true; - option.Cookies.ApplicationCookie.AuthenticationScheme = Constants.ApplicationAuthenticationSheme; - option.Cookies.ApplicationCookieAuthenticationScheme = Constants.ApplicationAuthenticationSheme; - option.Cookies.TwoFactorRememberMeCookie.ExpireTimeSpan = TimeSpan.FromDays(30); - option.Cookies.TwoFactorRememberMeCookie.DataProtectionProvider = protector; - option.Cookies.ExternalCookieAuthenticationScheme = Constants.ExternalAuthenticationSheme; - option.Cookies.ExternalCookie.AutomaticAuthenticate = true; - option.Cookies.ExternalCookie.AuthenticationScheme = Constants.ExternalAuthenticationSheme; - option.Cookies.ExternalCookie.DataProtectionProvider = protector; - */ - } - ).AddEntityFrameworkStores() - .AddTokenProvider>(Constants.DefaultFactor) - // .AddTokenProvider(Constants.DefaultFactor) + (ProtectionProvider); + + services.AddIdentity ( + option => { + IdentityAppOptions = option; + option.User.AllowedUserNameCharacters += " "; + option.User.RequireUniqueEmail = true; + // option.Cookies.ApplicationCookieAuthenticationScheme = Constants.ApplicationAuthenticationSheme; + option.Cookies.ApplicationCookie.LoginPath = "/signin"; + // option.Cookies.ApplicationCookie.AuthenticationScheme = Constants.ApplicationAuthenticationSheme; + /* + option.Cookies.ApplicationCookie.DataProtectionProvider = protector; + option.Cookies.ApplicationCookie.LoginPath = new PathString(Constants.LoginPath.Substring(1)); + option.Cookies.ApplicationCookie.AccessDeniedPath = new PathString(Constants.AccessDeniedPath.Substring(1)); + option.Cookies.ApplicationCookie.AutomaticAuthenticate = true; + option.Cookies.ApplicationCookie.AuthenticationScheme = Constants.ApplicationAuthenticationSheme; + option.Cookies.ApplicationCookieAuthenticationScheme = Constants.ApplicationAuthenticationSheme; + option.Cookies.TwoFactorRememberMeCookie.ExpireTimeSpan = TimeSpan.FromDays(30); + option.Cookies.TwoFactorRememberMeCookie.DataProtectionProvider = protector; + option.Cookies.ExternalCookieAuthenticationScheme = Constants.ExternalAuthenticationSheme; + option.Cookies.ExternalCookie.AutomaticAuthenticate = true; + option.Cookies.ExternalCookie.AuthenticationScheme = Constants.ExternalAuthenticationSheme; + option.Cookies.ExternalCookie.DataProtectionProvider = protector; + */ + } + ).AddEntityFrameworkStores () + .AddTokenProvider> (Constants.DefaultFactor) + // .AddTokenProvider(Constants.DefaultFactor) // .AddTokenProvider(Constants.SMSFactor) // .AddTokenProvider(Constants.EMailFactor) // .AddTokenProvider(Constants.AppFactor) // .AddDefaultTokenProviders() ; } - private void ConfigureOAuthApp(IApplicationBuilder app, - SiteSettings settingsOptions, ILogger logger) - { - - app.UseIdentity(); - app.UseWhen(context => context.Request.Path.StartsWithSegments("/api"), - branch => - { - branch.UseJwtBearerAuthentication( - options => - { - options.AuthenticationScheme = JwtBearerDefaults.AuthenticationScheme; - options.AutomaticAuthenticate = true; - options.SecurityTokenValidators.Clear(); - options.SecurityTokenValidators.Add(new TicketDataFormatTokenValidator( - ProtectionProvider - )); - } - ); - - }); - app.UseWhen(context => !context.Request.Path.StartsWithSegments("/api"), - branch => - { - // External authentication shared cookie: - branch.UseCookieAuthentication(options => - { - ExternalCookieAppOptions = options; - options.AuthenticationScheme = Constants.ExternalAuthenticationSheme; - options.AutomaticAuthenticate = true; - options.ExpireTimeSpan = TimeSpan.FromMinutes(5); - options.LoginPath = new PathString(Constants.LoginPath.Substring(1)); - // TODO implement an access denied page - options.AccessDeniedPath = new PathString(Constants.LoginPath.Substring(1)); - }); - - - - YavscGoogleAppOptions = new YavscGoogleOptions - { - ClientId = GoogleWebClientConfiguration ["web:client_id"], - ClientSecret = GoogleWebClientConfiguration ["web:client_secret"], - AccessType = "offline", - Scope = { "profile", "https://www.googleapis.com/auth/plus.login", - "https://www.googleapis.com/auth/admin.directory.resource.calendar", - "https://www.googleapis.com/auth/calendar", - "https://www.googleapis.com/auth/calendar.events"}, - SaveTokensAsClaims = true, - UserInformationEndpoint = "https://www.googleapis.com/plus/v1/people/me", - Events = new OAuthEvents - { - OnCreatingTicket = async context => - { - using (var serviceScope = app.ApplicationServices.GetRequiredService() - .CreateScope()) - { - var gcontext = context as GoogleOAuthCreatingTicketContext; - context.Identity.AddClaim(new Claim(YavscClaimTypes.GoogleUserId, gcontext.GoogleUserId)); - var dbContext = serviceScope.ServiceProvider.GetService(); - - var store = serviceScope.ServiceProvider.GetService(); - await store.StoreAsync(gcontext.GoogleUserId, new TokenResponse { - AccessToken = gcontext.TokenResponse.AccessToken, - RefreshToken = gcontext.TokenResponse.RefreshToken, - TokenType = gcontext.TokenResponse.TokenType, - ExpiresInSeconds = int.Parse(gcontext.TokenResponse.ExpiresIn), - IssuedUtc = DateTime.Now - }); - await dbContext.StoreTokenAsync (gcontext.GoogleUserId, - gcontext.TokenResponse.Response, - gcontext.TokenResponse.AccessToken, - gcontext.TokenResponse.TokenType, - gcontext.TokenResponse.RefreshToken, - gcontext.TokenResponse.ExpiresIn); - - } - } - } - }; - - branch.UseMiddleware(YavscGoogleAppOptions); -/* FIXME 403 - - branch.UseTwitterAuthentication(options=> - { - TwitterAppOptions = options; - options.ConsumerKey = Configuration["Authentication:Twitter:ClientId"]; - options.ConsumerSecret = Configuration["Authentication:Twitter:ClientSecret"]; - }); */ - - - branch.UseOAuthAuthorizationServer( - - options => - { - OAuthServerAppOptions = options; - options.AuthorizeEndpointPath = new PathString(Constants.AuthorizePath.Substring(1)); - options.TokenEndpointPath = new PathString(Constants.TokenPath.Substring(1)); - options.ApplicationCanDisplayErrors = true; - options.AllowInsecureHttp = true; - options.AuthenticationScheme = OAuthDefaults.AuthenticationType; - options.TokenDataProtector = ProtectionProvider.CreateProtector("Bearer protection"); - - options.Provider = new OAuthAuthorizationServerProvider - { - OnValidateClientRedirectUri = ValidateClientRedirectUri, - OnValidateClientAuthentication = ValidateClientAuthentication, - OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials, - OnGrantClientCredentials = GrantClientCredetails - }; - - options.AuthorizationCodeProvider = new AuthenticationTokenProvider - { - OnCreate = CreateAuthenticationCode, - OnReceive = ReceiveAuthenticationCode, - }; - - options.RefreshTokenProvider = new AuthenticationTokenProvider - { - OnCreate = CreateRefreshToken, - OnReceive = ReceiveRefreshToken, - }; - - options.AutomaticAuthenticate = true; - options.AutomaticChallenge = true; - } - ); - }); - - Environment.SetEnvironmentVariable ("GOOGLE_APPLICATION_CREDENTIALS", "google-secret.json"); - + private void ConfigureOAuthApp (IApplicationBuilder app, + SiteSettings settingsOptions, ILogger logger) { + + app.UseIdentity (); + app.UseWhen (context => context.Request.Path.StartsWithSegments ("/api"), + branch => { + branch.UseJwtBearerAuthentication ( + options => { + options.AuthenticationScheme = JwtBearerDefaults.AuthenticationScheme; + options.AutomaticAuthenticate = true; + options.SecurityTokenValidators.Clear (); + options.SecurityTokenValidators.Add (new TicketDataFormatTokenValidator ( + ProtectionProvider + )); + } + ); + + // External authentication shared cookie: + branch.UseCookieAuthentication (options => { + ExternalCookieAppOptions = options; + options.AuthenticationScheme = Constants.ExternalAuthenticationSheme; + options.AutomaticAuthenticate = true; + options.ExpireTimeSpan = TimeSpan.FromMinutes (5); + options.LoginPath = new PathString (Constants.LoginPath.Substring (1)); + // TODO implement an access denied page + options.AccessDeniedPath = new PathString (Constants.LoginPath.Substring (1)); + }); + + YavscGoogleAppOptions = new YavscGoogleOptions { + ClientId = GoogleWebClientConfiguration["web:client_id"], + ClientSecret = GoogleWebClientConfiguration["web:client_secret"], + AccessType = "offline", + Scope = { + "profile", + "https://www.googleapis.com/auth/plus.login", + "https://www.googleapis.com/auth/admin.directory.resource.calendar", + "https://www.googleapis.com/auth/calendar", + "https://www.googleapis.com/auth/calendar.events" + }, + SaveTokensAsClaims = true, + UserInformationEndpoint = "https://www.googleapis.com/plus/v1/people/me", + Events = new OAuthEvents { + OnCreatingTicket = async context => { + using (var serviceScope = app.ApplicationServices.GetRequiredService () + .CreateScope ()) { + var gcontext = context as GoogleOAuthCreatingTicketContext; + context.Identity.AddClaim (new Claim (YavscClaimTypes.GoogleUserId, gcontext.GoogleUserId)); + var dbContext = serviceScope.ServiceProvider.GetService (); + + var store = serviceScope.ServiceProvider.GetService (); + await store.StoreAsync (gcontext.GoogleUserId, new TokenResponse { + AccessToken = gcontext.TokenResponse.AccessToken, + RefreshToken = gcontext.TokenResponse.RefreshToken, + TokenType = gcontext.TokenResponse.TokenType, + ExpiresInSeconds = int.Parse (gcontext.TokenResponse.ExpiresIn), + IssuedUtc = DateTime.Now + }); + await dbContext.StoreTokenAsync (gcontext.GoogleUserId, + gcontext.TokenResponse.Response, + gcontext.TokenResponse.AccessToken, + gcontext.TokenResponse.TokenType, + gcontext.TokenResponse.RefreshToken, + gcontext.TokenResponse.ExpiresIn); + + } + } + } + }; + + branch.UseMiddleware (YavscGoogleAppOptions); + /* FIXME 403 + + branch.UseTwitterAuthentication(options=> + { + TwitterAppOptions = options; + options.ConsumerKey = Configuration["Authentication:Twitter:ClientId"]; + options.ConsumerSecret = Configuration["Authentication:Twitter:ClientSecret"]; + }); */ + + branch.UseOAuthAuthorizationServer ( + + options => { + OAuthServerAppOptions = options; + options.AuthorizeEndpointPath = new PathString (Constants.AuthorizePath.Substring (1)); + options.TokenEndpointPath = new PathString (Constants.TokenPath.Substring (1)); + options.ApplicationCanDisplayErrors = true; + options.AllowInsecureHttp = true; + options.AuthenticationScheme = OAuthDefaults.AuthenticationType; + options.TokenDataProtector = ProtectionProvider.CreateProtector ("Bearer protection"); + + options.Provider = new OAuthAuthorizationServerProvider { + OnValidateClientRedirectUri = ValidateClientRedirectUri, + OnValidateClientAuthentication = ValidateClientAuthentication, + OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials, + OnGrantClientCredentials = GrantClientCredetails + }; + + options.AuthorizationCodeProvider = new AuthenticationTokenProvider { + OnCreate = CreateAuthenticationCode, + OnReceive = ReceiveAuthenticationCode, + }; + + options.RefreshTokenProvider = new AuthenticationTokenProvider { + OnCreate = CreateRefreshToken, + OnReceive = ReceiveRefreshToken, + }; + + options.AutomaticAuthenticate = true; + options.AutomaticChallenge = true; + } + ); + }); + + Environment.SetEnvironmentVariable ("GOOGLE_APPLICATION_CREDENTIALS", "google-secret.json"); } } -} +} \ No newline at end of file diff --git a/src/Yavsc/Startup/Startup.WebSockets.cs b/src/Yavsc/Startup/Startup.WebSockets.cs index 0c5d746f..6cc0fae3 100644 --- a/src/Yavsc/Startup/Startup.WebSockets.cs +++ b/src/Yavsc/Startup/Startup.WebSockets.cs @@ -9,7 +9,7 @@ namespace Yavsc SiteSettings siteSettings, IHostingEnvironment env) { app.UseWebSockets(); - app.UseSignalR("/api/signalr"); + app.UseSignalR(Constants.SignalRPath); } } } \ No newline at end of file diff --git a/src/Yavsc/Startup/Startup.cs b/src/Yavsc/Startup/Startup.cs index b00a085a..8be7b5f7 100755 --- a/src/Yavsc/Startup/Startup.cs +++ b/src/Yavsc/Startup/Startup.cs @@ -392,14 +392,15 @@ namespace Yavsc { options.AuthenticationDescriptions.Clear(); options.AutomaticAuthentication = false; - }); + }); + app.UseSession(); ConfigureOAuthApp(app, SiteSetup, logger); ConfigureFileServerApp(app, SiteSetup, env, authorizationService); ConfigureWebSocketsApp(app, SiteSetup, env); ConfigureWorkflow(app, SiteSetup, logger); app.UseRequestLocalization(localizationOptions.Value, (RequestCulture) new RequestCulture((string)"en-US")); - app.UseSession(); + app.UseMvc(routes => { diff --git a/src/Yavsc/Views/Home/Chat.cshtml b/src/Yavsc/Views/Home/Chat.cshtml index 32183918..2379344c 100644 --- a/src/Yavsc/Views/Home/Chat.cshtml +++ b/src/Yavsc/Views/Home/Chat.cshtml @@ -44,7 +44,7 @@ @section scripts { - + @if (!ViewBag.IsAuthenticated) { // Get the user name and store it to prepend to messages. diff --git a/src/Yavsc/project.json b/src/Yavsc/project.json index cc3cd286..c25ed6b9 100644 --- a/src/Yavsc/project.json +++ b/src/Yavsc/project.json @@ -90,8 +90,8 @@ "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-*", "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final", "Microsoft.AspNet.Server.WebListener": "1.0.0-rc1-final", - "Microsoft.AspNet.SignalR.Core": "2.3.0", - "Microsoft.AspNet.SignalR.JS": "2.3.0", + "Microsoft.AspNet.SignalR.Core": "2.2.1", + "Microsoft.AspNet.SignalR.JS": "2.2.1", "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-*", "Microsoft.AspNet.Tooling.Razor": "1.0.0-rc1-*", "Microsoft.AspNet.WebSockets.Server": "1.0.0-rc1-*",