I currently have an app on aws that uses spring boot microservices for back-end and ReactJS for front-end.
The way it currently works is that a user logs in using username and password and a fetch call is made to an account microservice. There I do a basic username and pw check with db and send back a True or False response.
If True, the user gets logged in and redirected to products page where a fetch call is made to product service to get list of all products.
I now want to introduce JWT authorisation, so that calls to product service can only be made by logged in users.
My question is - can I introduce it in my current account service or do I have to put something in front of both services (currently they share a load balancer). Or maybe I need to direct product service traffic through account service?
Also, if I can introduce it in my current account service, how do I share the required key to product service so it can validate the request when it comes in?
Cheers, Kris
For this purpose the generic approach is to have an API Gateway layer i.e. a Microservice only which has to take care of following things -
Do the task of authentication and generate a JWT token for the user
Read the roles and responsibilities after decoding the token, every time a call is made by a user for authorization purpose
Once you get the role of user from here, you can create routes in API Gateway for each service to check like whether he can access that functionality or not, in your case let's say user's role is "warehouse Admin" and he is eligible to take care of product and related info, then he can access product service, for this you can do a role check at API Gateway layer only, when the request comes to access from routes related to product service (let's say its "/products" ). Hence you are maintaining the authenticity checks at API Gateway layer only.
Or in the otherwise case if you want to maintain an account service as well to take care of doing the authentication and authorization, then you have to direct the calls from API Gateway to account service and route the request to related backend services, once the response arrives from account service carrying the roles and permissions for the user.
Related
I wants to communicate between different microservices, but the problem that is arising is microservices are secured with jwt token and I am not able to find a way to send a secured call to the other microservice from first microservice. Is there is a way I can communicate with the service method directly because if I make my api open it will be misused.
Or I have to go through api gateway to send every request through api gate way and make a secure communication from there.
It all depends on what are the exact requirements of your project.
Gateway API usually is used to hide the complexity of microservice from external users that usually have 1 endpoint to talk to.
Also the gateway can handle the security and Authenticate the user (which many companies do indeed).
Now when you pass the gateway and your authenticated request reaches the client, usually you already have a user identity on the request (what was put onto the request by the gateway).
So you know that user "John Smith" has triggered the request.
And now if you need to call another microservice you should decide (and again its your decision):
Whether you need an authentication at all there (maybe internal communication doesn't have to be secured between microservices(
If you do need an authentication between microservices, who authenticates the request?
If its a gateway, all authentication logic is there, but you have to make an additional hop for each request that might be costy
Alternatively If its a direct call, each microservice must implement an authenticat logic. Sure, there is stuff like spring security, other languages/ecosystem have similar solutions, but in general this can be difficult to implement.
If you do make an authenticated call from microservice A to microservice B and the flow was originated by user John Smith that triggered a request to service A, you should decide whether the semantics of the call is:
User "John Smith" contacts the service B, or...
Service A contacts Service B on behalf of user John Smith.
This is really important for authorization if you have any kind of permissions system.
In term of technical implementation usually you can add a JWT header to the request with the required token. If the request was already authenticated and you need to generate user identity, you can merely put a couple of headers on the request.
You can have two api gateway:
one exposed outside
and another one for microservices communication within container.
The one which is exposed outside does the validation of tokens and send claims to the microservices where those claims are used for validation of route protection.
Between microservices communication, send claims that you already have with the second gateway. Hope this helps. If you have found any alternative way let us know.
My apologies for my bad english.
I have the tool Apereo CAS using as login SSO. When i'm using with application statefuls this works very well. But i wanna call a API REST (stateless) for specific scenario and validate the logged user (and using your informations on the service). My backend API is developed with Spring Boot. Someone needed a similar situation?
Ps: This API will acess by frontend and services without frontend therefore I'll not be able to use cookies.
Sequence Diagram to exemplify my idea:
enter image description here
Thank's.
Your front-end application needs to ask the CAS server for proxy authentication.
One of the more common use cases of proxy authentication is the ability to obtain a ticket for a back-end [REST-based] service that is also protected by CAS. The scenario usually is:
User is faced with application A which is protected by CAS.
Application A on the backend needs to contact a service S to produce data.
Service S itself is protected by CAS itself.
Because frontend contacts service in the back-end via a server-to-service method where no browser is involved, the backend would not be able to recognize that an SSO session already exists. In these cases, front-end needs to exercise proxying in order to obtain a proxy ticket for the backend. The proxy ticket is passed to the relevant endpoint of the backend so it can retrieve and validate it via CAS and finally produce a response.
The trace route may look like this:
Browser navigates to front-end.
Front-end redirects to CAS.
CAS authenticates and redirects back to front-end with an ST.
Front-end attempts to validate the ST, and asks for a PGT.
CAS confirms ST validation, and issues a proxy-granting ticket PGT.
Front-end asks CAS to produce a PT for back-end API, supplying the PGT in its request.
CAS produces a PT for backend API.
Front-end contacts the service S endpoint, passing along PT in the request.
backend API attempts to validate the PT via CAS.
CAS validates the PT and produces a successful response.
Backend API receives the response, and produces data for front-end.
A receives and displays the data in the browser.
See this for details.
What I'm trying to do
Right now I'm working on a Java Spring Backend for a Both which manages the request he gets from a NLP from api.ai and gives back corresponding information. Now I'd like to interact with different services that use OAuth2 to get information/data from there as well.
What I did so far
I have added my credentials for the service in my application.properties file. But only found a solution that a user can for example log-in with his facebook credentials on my service.
But I need to have my service to authenticate on the other service (with the given credentials from my properties file), to gather data from there.
Do you guys know a solution, tipps, tricks for that?
As I understand the logic should be following.
As you have SSO (OAuth2 based) you need to login just once and get token(s) from OAuth2 service (access token and refresh token). The access token is included in the request headers when you call any of your services.
Now Service1 must call Service2 using the same auth info.
In the Service1 you call OAuth2 service to check whether the token is valid. If yes all you need is to use the same token to call Service2.
So just extract the token from request headers and add to the headers of request you send to Service2. Could be done e.g. by adding a Filter and storing the auth info in a ThreadLocal variable (or inheritable ThreadLocal if you generate new threads by e.g. running Jobs).
Service2 in turn also checks the token by calling OAuth2 service but the token is valid.
For me that's all you need.
I have a web application that provides several rest services (Jersey). Most of the endpoints are secured by BASIC authentification. Further more I use SSL for transport and demand POSTs for every call.
The clients/consumers are android apps.
So far so good. The only service that seems to be vulnerable is the registration. It's the 'first' service to call and a user does not exist yet. So I cannot use OAuth, etc. I also have to keep the endpoint easy accessible to enable the user to regster.
How do I secure this service, so it's not spammed by a bot flooding my database?
How about these?
Use a registration link with a token in the request parameter. Ensure that the tokens expire after sometime. You could create a token endpoint url as well for a client to get a valid token.
Use a custom header or a dynamic custom header in your request. Additionally, you could check for a dynamic custom header to validate the request's authenticity.
Use registration confirmation workflows, such as an email / text verification as soon the registration is done. Run a process every day to delete any user accounts, which are not validated in say x days.
I do not think you can really secure the registration URL in a HTTP way. IMHO, anyone who has the registration url can be a right guy trying to register. So if you ask me, option 3 is better than others.
Overview
I am building a RESTful API application as mobile\web backend (let's call it MyBackendApp) and I'm looking for a contemporary solution for both Authentication AND Authorization of app users. Primary language for backend is Java. Looking at other apps, many of them offer several auth methods to user: using external to app account (e.g. Facebook, Google, Yahoo, OpenId etc.) or internal (email\password). Something like Stackoverflow has on its sign-up\sign-in. I read many sources about OAuth2, I also used to use Spring Security to implement internal user accounts and session management. But I'm having hard time putting both methods together.
Requirements
I want user to be logged in using either of following methods
with external (possibly OAuth2) Facebook-like account
using email\password
Role Based Access Control to the API methods. The MyBackendApp will have following roles: app admin, content admin, content user, content creator, developer (for other apps to use MyBackendApp API)
Like all modern mobile apps I want user stayed logged in until expiration or session revocation (if to go as described below in Current implementation thoughts, then it can be done with token revocation). And I don't want him to get to login screen everytime he opens up MyApp's mobile app
Current implementation thoughts
OAuth2
For simplicity I use here Facebook term, but assuming more general meaning: the authentication with external to MyBackendApp account from any external Provider.
My understanding is that if user already have authToken from Facebook (he has already logged in with his Facebook app) stored somewhere in his mobile device, then just get the authToken (I believe I saw method in Android SDK, please correct me if I'm wrong). Otherwise, need to go through the standard OAuth procedure to receive the authToken from the provider (Facebook). Now, having the authToken and secret key from the provider MyBackendApp can retrieve a user unique ID AND email from the token and:
if the uniqueId is already in MyBackendApp DB, then user is authenticated
and MyBackendApp allow or don't allow access to a requested REST endpoint,
based on users (defined by its uniqueId and email) Role.
if uniqueId is not in the MyBackendApp DB, then user is going through MyBackendApp
registration process, which is similar to Stackoverflow sign-up. His info gets stored in the DB
user gets assigned some role
email\password auth
Sign-Up. If user is not registered, then he goes through registration process: MyBackendApp stores email and hash of password in DB. It also assigns a Role (lets say Content Creator)
Sign-In. If user is registered and want to log in
he enters email and password in a client app (WebUI JavaScript\Android\iOS)
client app (lets call it MyClientApp) gets hash out of password (please correct me if it's not a right way) and POST it along with email to MyBackendApp over https. Edit: there is no sense to hash the password on client side. Rather than that the password will be sent as is over SSL. After that Server (MyBackendApp) will generate a hash and compare it with stored hash in DB.
having email and password MyBackendApp authentifies the user and issue authToken (possibly JWT) with userUniqueId (UUID), some expiration date.
the authToken is to be sent on every REST API request
Next time MyBackendApp receives request to some of REST endpoints it retrieves the userUniqueId, expirationDate and based on Role allow\disallow the call.
Summary
Does the approach described in the "implementation thoughts" section above make sense? Any security threats?
Some posts says that OAuth cannot be used for user authentication, e.g. here, but I didn't get why? And if not then how to provide users login using facebook\google\others account?
I definitely don't want to reinvent a bicycle, so I'm wondering is there any framework which make this task easier? I believe that Spring Security with its OAuth2 support can help a lot for implementation of OAuth2. But how does it work for both types of login (OAuth2+email\password)?
This post suggests [Apache Shiro] - is it good for the described purposes? Can it be combined with Spring Security OAuth2?
I wrote above that having the authToken and secret key from the provider MyBackendApp can retrieve a user unique ID AND email - but is it the case? Do providers include this information in the authToken?
If user of mobile device or web browser has already got the authToken (e.g. he logged in in facebook mobile app OR desktop browser stored his password) and he's already allowed MyApp in Facebook once - can he open my app being already logged in with his facebook account skipping the login procedure? How?