From e4d00b415755cfa2822584611012892532179042 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Sat, 4 Aug 2018 09:42:23 -0500 Subject: [PATCH] config/build work Still not pulling JWT payloads; validates and returns 404 :/ --- .gitignore | 6 +-- src/api/MyPrayerJournal.Api/Handlers.fs | 25 +++++++++-- .../MyPrayerJournal.Api.fsproj | 4 ++ src/api/MyPrayerJournal.Api/Program.fs | 41 +++++++++++++------ src/api/MyPrayerJournal.Api/appsettings.json | 9 ++++ src/app/config/index.js | 4 +- src/app/package.json | 6 +-- 7 files changed, 71 insertions(+), 24 deletions(-) create mode 100644 src/api/MyPrayerJournal.Api/appsettings.json diff --git a/.gitignore b/.gitignore index 4e63cca..b40b050 100644 --- a/.gitignore +++ b/.gitignore @@ -254,8 +254,8 @@ paket-files/ # Compiled files / application src/api/build -src/public/index.html -src/public/static -src/config.json +src/api/MyPrayerJournal.Api/wwwroot/index.html +src/api/MyPrayerJournal.Api/wwwroot/static +src/api/MyPrayerJournal.Api/appsettings.development.json /build src/*.exe diff --git a/src/api/MyPrayerJournal.Api/Handlers.fs b/src/api/MyPrayerJournal.Api/Handlers.fs index a8ed088..986478e 100644 --- a/src/api/MyPrayerJournal.Api/Handlers.fs +++ b/src/api/MyPrayerJournal.Api/Handlers.fs @@ -1,8 +1,9 @@ /// HTTP handlers for the myPrayerJournal API [] -module MyPrayerJournal.Handlers +module MyPrayerJournal.Api.Handlers open Giraffe +open MyPrayerJournal open System module Error = @@ -17,7 +18,7 @@ module Error = /// Handle 404s from the API, sending known URL paths to the Vue app so that they can be handled there let notFound : HttpHandler = fun next ctx -> - let vueApp () = htmlFile "/index.html" next ctx + let vueApp () = htmlFile "wwwroot/index.html" next ctx match true with | _ when ctx.Request.Path.Value.StartsWith "/answered" -> vueApp () | _ when ctx.Request.Path.Value.StartsWith "/journal" -> vueApp () @@ -31,6 +32,8 @@ module Error = module private Helpers = open Microsoft.AspNetCore.Http + open Microsoft.AspNetCore.Authorization + open System.Threading.Tasks /// Get the database context from DI let db (ctx : HttpContext) = @@ -47,6 +50,21 @@ module private Helpers = /// The "now" time in JavaScript let jsNow () = DateTime.Now.Subtract(DateTime (1970, 1, 1)).TotalSeconds |> int64 |> (*) 1000L + + let notAuthorized : HttpHandler = + setStatusCode 403 >=> fun _ _ -> Task.FromResult None + + /// Handler to require authorization + let authorize : HttpHandler = + fun next ctx -> + task { + let auth = ctx.GetService() + let! result = auth.AuthorizeAsync (ctx.User, "LoggedOn") + Console.WriteLine (sprintf "*** Auth succeeded = %b" result.Succeeded) + match result.Succeeded with + | true -> return! next ctx + | false -> return! notAuthorized next ctx + } /// Strongly-typed models for post requests @@ -87,7 +105,8 @@ module Journal = /// GET /api/journal let journal : HttpHandler = - fun next ctx -> + authorize + >=> fun next ctx -> match user ctx with | Some u -> json ((db ctx).JournalByUserId u.Value) next ctx | None -> Error.notFound next ctx diff --git a/src/api/MyPrayerJournal.Api/MyPrayerJournal.Api.fsproj b/src/api/MyPrayerJournal.Api/MyPrayerJournal.Api.fsproj index 57ea803..66b438d 100644 --- a/src/api/MyPrayerJournal.Api/MyPrayerJournal.Api.fsproj +++ b/src/api/MyPrayerJournal.Api/MyPrayerJournal.Api.fsproj @@ -22,4 +22,8 @@ + + + + diff --git a/src/api/MyPrayerJournal.Api/Program.fs b/src/api/MyPrayerJournal.Api/Program.fs index 4b425e9..7cf8951 100644 --- a/src/api/MyPrayerJournal.Api/Program.fs +++ b/src/api/MyPrayerJournal.Api/Program.fs @@ -1,36 +1,50 @@ namespace MyPrayerJournal.Api -open System -open Microsoft.AspNetCore open Microsoft.AspNetCore.Builder open Microsoft.AspNetCore.Hosting -open Microsoft.Extensions.Configuration -open Microsoft.Extensions.Logging + /// Configuration functions for the application module Configure = + open Microsoft.AspNetCore.Authentication.JwtBearer + open Microsoft.AspNetCore.Server.Kestrel.Core + open Microsoft.Extensions.Configuration open Microsoft.Extensions.DependencyInjection + open Microsoft.Extensions.Logging open Giraffe open Giraffe.TokenRouter - open MyPrayerJournal /// Set up the configuration for the app let configuration (ctx : WebHostBuilderContext) (cfg : IConfigurationBuilder) = cfg.SetBasePath(ctx.HostingEnvironment.ContentRootPath) .AddJsonFile("appsettings.json", optional = true, reloadOnChange = true) - .AddJsonFile(sprintf "appsettings.%s.json" ctx.HostingEnvironment.EnvironmentName, optional = true) + .AddJsonFile(sprintf "appsettings.%s.json" ctx.HostingEnvironment.EnvironmentName) .AddEnvironmentVariables() |> ignore + /// Configure Kestrel from appsettings.json + let kestrel (ctx : WebHostBuilderContext) (opts : KestrelServerOptions) = + (ctx.Configuration.GetSection >> opts.Configure >> ignore) "Kestrel" + /// Configure dependency injection let services (sc : IServiceCollection) = - sc.AddAuthentication() - .AddJwtBearer("Auth0", - fun opt -> - opt.Audience <- "") + sc.AddGiraffe () |> ignore + // mad props to Andrea Chiarelli @ https://auth0.com/blog/securing-asp-dot-net-core-2-applications-with-jwts/ + use sp = sc.BuildServiceProvider() + let cfg = sp.GetRequiredService().GetSection "Auth0" + sc.AddAuthentication( + fun opts -> + opts.DefaultAuthenticateScheme <- JwtBearerDefaults.AuthenticationScheme + opts.DefaultChallengeScheme <- JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer ( + fun opts -> + opts.Authority <- sprintf "https://%s/" cfg.["Domain"] + opts.Audience <- cfg.["Audience"] + opts.TokenValidationParameters.ValidateAudience <- false) + |> ignore + sc.AddAuthorization (fun opts -> opts.AddPolicy ("LoggedOn", fun p -> p.RequireClaim "sub" |> ignore)) |> ignore - () /// Routes for the available URLs within myPrayerJournal let webApp = @@ -82,6 +96,7 @@ module Configure = module Program = + open System open System.IO let exitCode = 0 @@ -89,10 +104,10 @@ module Program = let CreateWebHostBuilder args = let contentRoot = Directory.GetCurrentDirectory () WebHostBuilder() - .UseKestrel() .UseContentRoot(contentRoot) + .ConfigureAppConfiguration(Configure.configuration) + .UseKestrel(Configure.kestrel) .UseWebRoot(Path.Combine (contentRoot, "wwwroot")) - .ConfigureAppConfiguration(Action Configure.configuration) .ConfigureServices(Configure.services) .ConfigureLogging(Configure.logging) .Configure(Action Configure.application) diff --git a/src/api/MyPrayerJournal.Api/appsettings.json b/src/api/MyPrayerJournal.Api/appsettings.json new file mode 100644 index 0000000..9d278ae --- /dev/null +++ b/src/api/MyPrayerJournal.Api/appsettings.json @@ -0,0 +1,9 @@ +{ + "Kestrel": { + "EndPoints": { + "Http": { + "Url": "http://localhost:3000" + } + } + } +} diff --git a/src/app/config/index.js b/src/app/config/index.js index c6e5523..8ee05a1 100644 --- a/src/app/config/index.js +++ b/src/app/config/index.js @@ -4,8 +4,8 @@ var path = require('path') module.exports = { build: { env: require('./prod.env'), - index: path.resolve(__dirname, '../../public/index.html'), - assetsRoot: path.resolve(__dirname, '../../public'), + index: path.resolve(__dirname, '../../api/MyPrayerJournal.Api/wwwroot/index.html'), + assetsRoot: path.resolve(__dirname, '../../api/MyPrayerJournal.Api/wwwroot'), assetsSubDirectory: 'static', assetsPublicPath: '/', productionSourceMap: true, diff --git a/src/app/package.json b/src/app/package.json index 03fa3c1..4ece02c 100644 --- a/src/app/package.json +++ b/src/app/package.json @@ -1,6 +1,6 @@ { "name": "my-prayer-journal", - "version": "0.9.6", + "version": "0.9.7", "description": "myPrayerJournal - Front End", "author": "Daniel J. Summers ", "private": true, @@ -12,8 +12,8 @@ "e2e": "node test/e2e/runner.js", "test": "npm run unit && npm run e2e", "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs", - "apistart": "cd .. && go build -o mpj-api.exe && mpj-api.exe", - "vue": "node build/build.js prod && cd .. && go build -o mpj-api.exe && mpj-api.exe" + "apistart": "cd ../api/MyPrayerJournal.Api && dotnet run", + "vue": "node build/build.js prod && cd ../api/MyPrayerJournal.Api && dotnet run" }, "dependencies": { "auth0-js": "^9.3.3",