Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation for integrating different authentication and authorization techniques #229

Open
Zaid-Ajaj opened this issue Mar 18, 2021 · 10 comments

Comments

@Zaid-Ajaj
Copy link
Owner

Based on feedback from users, it can be really tricky to secure a remoting API, whether that deals with an internal security system or one that integrates a third-party into the mix such as Azure active directory or Auth0.

Currently the documentation only scratches the surface where you can see that you the remoting building has access to the HttpContext which in turn has access to the context of the currently authorized user or other security services injected by means of DI. Still, the issue remains of how to go from this to a full integration along with handling authentication on the client side as well

I would like to compile a series of guides into the documentation website for integrating these 3rd party systems and what things there are to consider.

Help needed from people who actively have worked and implemented some of the integrations or built their own layer on top.

@kerams
Copy link
Collaborator

kerams commented Mar 18, 2021

I'm rolling my own dead simple, cookie-based, internal system.

I have an auth Remoting handler with a login method that takes credentials as input and sets the session cookies if authentication succeeds. Then each Remoting method that needs to be secured uses a higher order function that checks the validation. It looks something like this:

// I use this return type for every method
type Response<'a> =
    | Unauthenticated
    | Unauthorized
    | OldVersion of 'a option
    | Fine of 'a

let requireAuthentication (ctx: HttpContext) (handler: _ -> _ -> Async<_>) = async {
    // authOk extracts cookies from the context, validates the session,
    // and passes the corresponding user into the handler if successful
    match! authOk ctx with
    | Some user -> return! handler request user
    | _ ->
        CookieAuth.deleteAuthCookies ctx.Response
        return Unauthenticated })

type AdministrationApi = {
    removeAttribute: Request<AttributeDefinitionId> -> Async<Response<Result<unit, unit>>>
}

let administrationApi (ctx: HttpContext) = {
    removeAttribute = requireAuthentication ctx (fun req user -> async {
        let! res = CompositionRoot.setAttributeDefinitionDeleted req true
        return Fine res
    })
}

Because this system is cookie-based, the browser takes care of cookie sending on every request as well as invalidation. The only thing the client needs to do is login (obviously) and handling the return types.

@JamesRandall
Copy link

I've integrated it with Saturn and "raw" ASP.Net Core both with a Fable client. I've got an end of March deadline but once that's clear happy to have a go at some write ups.

@Dzoukr
Copy link
Contributor

Dzoukr commented Mar 18, 2021

I can provide examples of:
Fable.Remoting on Frontend
Fable.Remoting on Backend (using Giraffe)
ASP.NET auth using JWT token (custom generated)

Is that what you would appreciate?

@Dzoukr
Copy link
Contributor

Dzoukr commented Mar 18, 2021

@Zaid-Ajaj Can I pull request to (newly created) "Examples" folder? Or how do you want to have it?

@Zaid-Ajaj
Copy link
Owner Author

@kerams This is a great example of a simple implementation. I think it is the same of what @Dzoukr is suggesting?

@JamesRandall That would be super awesome! Many people are using Saturn ootb so an example integration is certainly more than welcome. No hurry of course

As for the actual guides, I am really hoping for guides that walk people through the different criteria and choices:

  • Criteria: start with where users are stored: in memory list / in a database / managed by Auth0 / managed by Azure active directory / etc.
  • Choice: how the JWT is created? using defaults from Asp net core is preferred
  • Choice: using JWT stored in cookie (sent automatically per request by the browser)
  • Choice: using JWT sent in each request as part of the payload / sent via the authorization header
  • An example of backend setup: integrating into the Giraffe layer or Saturn's application CE
  • An example a login request (anonymous) + an authorized request from the client
  • (Maybe how an authorization error is handled? redirecting to login the page?)
  • Example code

This is of course the ideal situation, you don't have to every small detail. I will help you extend what you come up with 😄 just keep in mind that the docs are targeted at beginners

Contributing is a matter of adding a new markdown file in ./{repo}/documentation/src/{your-auth-implementation}.md` and I will handle the rest. You can run the the documentation website locally as follows

cd documentation
npm install 
npm start

This should start the gitbook in localhost

I am here for any question, thanks a lot for helping out ❤️

@Dzoukr
Copy link
Contributor

Dzoukr commented Mar 18, 2021

@Zaid-Ajaj would you like some more advanced example with sending errors as HTTP 4xx errors, custom Fable.Remoting error handler, using local storage for tokens, etc... ?

@Zaid-Ajaj
Copy link
Owner Author

@Dzoukr The more docs, the better IMO so it is really up to you 😉

@absolutejam
Copy link

absolutejam commented Mar 18, 2021

I'm weirdly excited about this 😄

I've been implementing JWT auth in Saturn with Fable Remoting and it's been a big learning curve, but I think I now have it in a good place... However, I'm going to wait and see what comes from this before I settle on that opinion or release any code 😅

Zaid-Ajaj added a commit that referenced this issue Mar 18, 2021
@zelenij
Copy link

zelenij commented Apr 7, 2021

I'm weirdly excited about this smile

I've been implementing JWT auth in Saturn with Fable Remoting and it's been a big learning curve, but I think I now have it in a good place... However, I'm going to wait and see what comes from this before I settle on that opinion or release any code sweat_smile

This example seems like a great starting point, but I don't think it would compile in real life. At least there is an inconsistency in onSecuredAPI usage, as it seems to me. Maybe a better option is to create a self contained sample project?

@teknikal-wizard
Copy link

teknikal-wizard commented May 20, 2021

I have two blogs up where I integrate AD with a SAFE app if they are any use https://www.compositional-it.com/news-blog/tag/safe-ad-auth/

Edit - I should say that I am just updating an app to SAFE V3 / .NET 5 and things didn't quite work the same so I will update those blogs once I have sussed it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants