.Net5 using a centralized web applications for login - jwt

I'm building a platform on .Net5 that will consist of at least 3 MVC web applications: User, Admin, Product. Authentication is performed on the User application where we can take a Username/Password to log the user in. The User Application also has the Forgot Password/Reset Password, etc functionality on it. Authorization is claims based. Based on this document I believe I would fall into Figure 9-2 Authentication by identity microservice, where my other microservices are web applications rather than APIs.
The issue I'm running into is trying to figure out the proper way to implement this.
Do I use JWT or Cookies for this? The article above does have a link for cookie sharing but wouldn't JWT be appropriate?
If I did use JWT, how do I pass it back to the server if I used something like #Html.ActionLink? Or is it expected that I would be using a front end framework like React and thus making any calls back to the server manually?
Again, if I'm using JWT, how would I pass it from the User application to the other applications?

Related

Separate one module from JSF application

We have big JSF monolithic application. We want to change the architecture of this application. Currently, my goal - change one module in our application. I need to move the logic from one module to another application which will be implemented on another stack of technologies (it will be rest-service with some js-framework on frontend).
The application should work in the same way. We should have the link to the page as it was earlier but this page should be rendered by another service. We should have the same session between these 2 applications. The user should be able to go throw the pages without an additional step of authentification.
We are planning to move also other modules, not only this one. I need a help. Do you have any thoughts how it should be implemented? any examples?
The ideal way to do this for me is using a SSO service like keycloak, as your Identity Provider. That involves porting your authentication logic to it and decouple it from your monolith. But once you rely on it as your IdP, you only share tokens between your applications and IdP. Keycloak has many adapters, for Java, Javascript, NodeJs clients.. and so on. That has the huge advantage that you can keep decoupling logic from your monolith and you don't even need new modules to be written in Java. You could even integrate it with services not written by you, it's enough for them to have Open Id Connect or SAML integrations.
KC supports both SAML and OIDC Auth protocols. With OIDC (the way to go with brand new applications), the adapter located in each of the apps checks wether the user has a valid web session or not. If not, it gets redirected to KC login page. The result of a valid login is a code which you can use to obtain an access token (a valid token to obtain resources from your app). Apart from that, the adapter ties that access token to a browser web session, which is stored in KC too. So if you try to access the other web page, the adapter checks for your web session, which finds to be valid.
You can use it to access your apps from a mobile device too, taking care of the access token management/renewal in the mobile app yourself.
See also:
The OpenId Connect protocol

Symfony 3 authenticate user against remote API

I've got an application where back-end and front-end are served from different hosts and are two different applications (both Symfony 3 based).
One of them (back-end ofc) handles business logic and keeps users and their roles in it's DB. Back-end provides REST API to be used by front-end. I have no possibility to modify back-end code as it's not my project - I just want to create a front-end for it.
Currently, I'm trying to create front-end app in Symfony 3 but I'm not sure how to make the front-end app authenticate against a remote API and keep no user data (or as little as possible) on its side.
After passing credentials to the backend via REST API a token is sent to front-end application and following API requests (e.g. data the front-end app would present to the user are to be sent with token received after successful authentication).
My question again: How can I authenticate against remote custom (non-OAuth) API from Symfony 3?
And additionally: How to handle token properly later? (it has to be used while making every request after successful authentication). What is the easiest way to achieve this?
I've been struggling to find decent info (maybe a tutorial?) I'm a noob in Symfony :(
Most articles describe providing an API which allows clients to connect to it, not making a client app in Symfony.
What I found:
Symfony2 authentication via 3rd Party REST API - most relevant, though it describes a flow for Symfony 2 and the accepted answer describes what should be done only briefly
https://blog.vandenbrand.org/2012/06/19/symfony2-authentication-provider-authenticate-against-webservice/ - concerning Symfony 2
http://symfony.com/doc/current/security/custom_authentication_provider.html - probably the most on topic, however, I don't understand where will app keep it's users (is writing a custom user provider necessary in this example?)
You've already found the answer on your question. That's custom authentication provider. You can keep the tokens in your frontend app storage, and just authenticate them. On login, you should create the token via request to backend app, save it in your token storage and that's all. Then you only need to authenticate the token (just see an example of auth provider).
Regarding keeping user data in your frontend app, it's up to you. You don't have to keep any data, therefore if you'd like to show some details (i.e. user name and so on) you have to store that details too (or retrieve it each request - but that will impact the performance). At least you can use caching for that.
So the possible approach is:
On login(with login form or elsewhere), just authenticate user in login handler (create your own auth provider as described there - don't worry about Symfony 2, security component is almost the same - there are some incompatibilities, but the direction is correct). After successful authentication, store token in your frontend storage (also you can store some user details you need like name and so on).
On each request, authenticate the user using the token that's kept in your frontend app storage (that's another auth provider) - you don't need to send request to your backend app.

Symfony Restful API authentication and OAuth2

I am building a RESTful API application with Symfony2.
The app will consist of two parts.
JavaScript front-end - everything the user will ever be able to see and do will reside here.
Symfony2 back-end API - every resource and data the user will be able to reach from front-end will be served in standard JSON via endpoints.
I have never built a fully RESTful application before. My main concern is how to authenticate users.
I imagine REST authentication like this:
A user enters his credentials in a form generated in the front end, then the request is sent to the server where authentication logic happens and if the user is authenticated, a response with "token" is sent back to user, that he will add that token to every request url or authorization header (I don't know which of these options is preferable).
Then with every request, the server will check if the user token is valid and if the user is authorized to access that data (roles) and if so serves request data. (I don't want to allow users login with Google, Facebook or anything like that. I want my users logging in to other application using my app)
Now this seems quite simple, but then there's OAuth2 that got me confused because I jumped into developing without research. I downloaded FOSOAuthServerBundle and started messing around when I started to get a feeling that something is not right.
What I would like to know is the difference between RESTful authentication and OAuth.
What are the recommendations for implementing the described login mechanism?
You've got it pretty spot on. You use OAuth just for the authentication and all the following requests will have to provide that HTTP-Authorization header. You would need to create your custom authentication provider to handle that. Also use something like FOSRestBundle to create your resources.

REST API and client on same server, need API authentication?

First, let me describe the application: we are working on a web-based software which is some kind of custom help desk application. It requires the user to login (we use FOSUserBundle). After login the user is redirected to the dashboard. From the dashboard there is no more page reload, the frontend is build on Angularjs and the user can get anywhere within the application without page reload. You could speak of a single page application.
So the data that is presented to the user, is fetched from a rest api (we use FOSRestBundle). This works quite well at this point.
There is some kind of dilemma. Only our staff will access this application (for now). So a staff member needs to login to access the helpdesk. The data that is pushed to the frontend via angularjs is called via api, so the user that has just logged in needs to authenticate again on every request because of rest.
Problem: Since the backend runs on symfony2 let us just try to get the user object of the currently logged in user when an api call is made:
$this->get('security.context')->getToken()->getUser()
returns anon. that stands for anonymous, or
$this->getUser();
returns just null.
So the authenticated context seems to be gone when using the rest api. However when I call an action directly without rest, I can get user information.
So what we need is to secure our rest api and get user information on every api call. We don't want third party people to access our application, just staff. I am not familar with OAuth, but the user will be redirected to a third party page to Allow/Deny access to his data? This would not be an option for us.
Based on that information, do you have any suggestions or ideas how to secure the api and transport the user data so that getUser does not return null or anon. but the actuall logged in user?
there's another way to resolve your problem.
It's by using Certificates.
you can generate certificates then use Http tunneling (https obviousley), the server will ask for a certificate (you've to configure Apache for that but it's not a big challenge).
with this in place, you've to add a CertificateManageron the server side to ensure that the certificate is valid and to know who's calling the service (to be able to authenticate the user at each request), the CertificateManager(or what ever you'll call it) will probably have to be configured within you filters chaine (as known in the java world), et voilĂ 
Hop that help you,
Abderrazak
REST is stateless so you will have to send some kind of authentication/authorization in each request. You can use HTTP BASIC AUTH or something like OAuth.
Have a look at https://github.com/FriendsOfSymfony/FOSOAuthServerBundle
I'm kind of building our application in exactly the same architecture (RESTful API with Symfony2 back-end and AngularJS frontend.
Another way is to duplicate the api routes, so that you have the api routes protected by OAUTH and the api routes protected by the session, both of them pointing to the same controllers. The method was explained here: https://stackoverflow.com/a/22964736/435026

How to eliminate authentication on my MVC app that is called from asp.net forms app

Curious what recommendations anyone has.
I have an existing asp.net forms application that does a Forms Authentication and has identity impersonate turned on.
The application has a link to a questionnaire that I would like to develop separately in an asp.net MVC application, but I don't want the users to click on the link and be prompted for a username and password, I would like them to be able seamless start filling out the questionnaire.
Is there a way to somehow transfer authentication from one .net app to another? I would like to be able to pass stuff like UserRole.
What's the best way to do this?
If you use the same MachineKey in both applications and the MVC application is on the same server, I think that it will reuse the auth cookie and simply consider them logged in. See this MSDN article on configuring the MachineKey, especially the section on sharing authentication tickets across applications. Note this assumes that both applications are on the same server. If they are on different servers then you'll need to investigate some other mechanisms -- say generating a single-use ticket for the URL that can be used by the remote system via a web call back to the originating server who the user is. It might not need to be a full-up implementation of a central authentication system, but along those lines. Just be sure that you're using SSL to encrypt the relevant bits to help avoid man-in-the-middle attacks.
Using Windows Identity Foundation (WIF) you can achieve Single Sign-On.
In WIF, a service called a Security Token Service (STS), issues a token with claims, which can be anything you want to declare about the authenticated user, for instance his roles. In your apps you can use the Page.User, Controller.Page or Thread.Current.Principal properties to check the User claims (though if you'll only be using role claims you can use the IsInRole method for simplicity).
You can easily create a STS using the tools for VS included in WIF's SDK. The Forms authentication will be done in the STS instead of in the Web Forms site and both sites should have a trust relationship with the STS.