oauthf#fable-f#saturn-frameworksafe-stack

SAFE-stack with github authorization


I am trying to hide my whole application behind a authentication (I'll deal with authorization when this works), and for now I want to every url to require github login. I am not getting the github login page up.

I have tried to combine the SAFE-stack template and "Using OAuth with Saturn", but I do not get the github login page (which I do get when following only the Saturn guide), I just get the normal todo page. If I click the Add button, the server prints

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 POST http://localhost:8085/api/ITodosApi/addTodo application/json; charset=UTF-8 68
info: Microsoft.AspNetCore.Authentication.OAuth.OAuthHandler`1[[Microsoft.AspNetCore.Authentication.OAuth.OAuthOptions, Microsoft.AspNetCore.Authentication.OAuth, Version=3.1.11.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]][12]
      AuthenticationScheme: GitHub was challenged.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 10.8057ms 302 

And the item is not added to the list of todos.

I have tried shaving off everything except the authentication bit, and compared to a clean safe template, the only changes I have made is

  1. dotnet paket add Saturn.Extensions.Authorization --project src/Server/Server.fsproj
  2. Manually downgrade two dependencies in paket.lock that otherwise created an error: Microsoft.AspNetCore.Authentication.Google to (3.1.11) and Microsoft.AspNetCore.Authentication.OpenIdConnect to (3.1.11)
  3. Change the app value in Server/Server.fs to the following (I created a new github auth app for this issue):
let loggedInPipeline = pipeline {
    requires_authentication (Giraffe.Auth.challenge "GitHub")
}

let loggedInView = router {
    pipe_through loggedInPipeline
    get "/" webApp
}

let appRouter = router {
    forward "" loggedInView
}

let app =
    application {
        use_router appRouter
        url "http://0.0.0.0:8085/"
        memory_cache
        use_static "public"
        use_gzip
        use_github_oauth "8cde657dfd1d3a41b9ed" "0b245e12900ff8486ade076aae07aa0deb0fd83d" "/signin-github" [("login", "githubUsername"); ("name", "fullName")]
    }

run app

My gitHub app config auth callback url: http://localhost:8080/signin-github


Solution

  • I got help on solving this, just for AzureAD. A blog post can be found here https://www.compositional-it.com/news-blog/safe-stack-authentication-with-active-directory-part-2/. Should be the same for github. What I needed to do was to make some changes to webpack.config.js, Server.fs and build.fsx

    webpack.config.js

    devServerProxy: {
        // redirect all requests to the server on port 8085
        '**': {
    //...
    
    var CONFIG = {
        appHtmlTemplate: './src/Client/app.html',
    //...
    
    var commonPlugins = [
        new HtmlWebpackPlugin({
            filename: 'app.html',
    //...
    
    var CONFIG = {
        // ... other webpack config settings
        outputDir: './src/Server/public',
         // ...
    
        devServer: {
            // ...other dev server config settings
            writeToDisk: true
        },
    

    Server.fs:

    let authScheme = "AzureAD"
    
    let isDevelopment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") = Environments.Development;
    
    let noAuthenticationRequired nxt ctx = task { return! nxt ctx }
    
    let authChallenge : HttpFunc -> HttpContext -> HttpFuncResult =
        requiresAuthentication (Auth.challenge authScheme)
    
    let routes =
        choose [
            route "/" >=> authChallenge >=>  htmlFile "public/app.html"
        ]
    

    build.fsx:

    let serverPublicPath = Path.getFullName "./src/Server/public"
    let clientPublicPath = Path.getFullName "./src/Client/public"
    
    Target.create "Clean" (fun _ ->
        Shell.cleanDir deployDir
        Shell.cleanDir serverPublicPath)
    
    Target.create "Run" (fun _ ->
        Shell.copyDir serverPublicPath clientPublicPath FileFilter.allFiles
        //... other commands
    

    You will need to use a non-Chrome browser if you are working locally, such as Firefox, due to the cookie issue mentioned earlier.

    It is a good idea to open a private browsing window, to make sure that you don't already have a logged in account etc.

    If you are having issues, check that you have