I have 3 services (in the real much more):
Authorization service (uses OAuth 2.0)
Frontend service
Resource service
and client (web-browser).
I store session_id, access_token and refersh_token in cookies of the user's web-browser. The user goes to Auth service, signs in and gets these tokens. After his web-browser is redirected to Frontend.
Frontend and Resource services can't validate tokens because they know a nothing about it, so they must make a request to Auth service.
The current scenarios:
The user (web-browser) sends a request to Frontend service, the Frontend sends a request to Auth service to validate access_token. If it's invalid the Frontend sends a request to refresh token using refresh_token.
If the Frontend needs an access to Resource service to process a request then the Frontend sends its client_id and access_token to Resource service. The Resource service sends a request to the Auth service to validate an access_token too.
Are my thoughts right? Or it has simpler schema?
P.S. All services use RESTful architecture.
OAuth talks about how the tokens be exchanged. What you have mentioned it seem liek you are talking about using implicit grant, which is little less secure and you may think of opting for authorisation flow.
Other than that, in microservices when you have many services and one user request pass through many downstream services, verifying the token with auth provider at each and every step might become a bottleneck.
There are ways out there by which you can skip this call to auth server and still validate the sanctity of the token without making an explicit call.
One way is to make use of JWT. These tokens are signed by the Auth provider and your services have keys which can help you validate if the token is modified on it way, and token itself has all the information you need to ensure validity of it, like expiry time, intended audience, clients, roles etc.
On login you get AT and RT. AT could be passed along to downstream for authentication and authorization and RT could be used when AT is expired.
You only need to talk to auth provider at the time of login and when you need to refresh the token.
You can read more about the JWT OAuth2.0 with JWT and OIDC to get more information around it
Related
I am building an application that spans over several parts of infrastructure.
An end-user can sign in to a portal using OAuth 2.0 authorization code flow. When calling different APIs, the portal requests tokens on-behalf-of the signed in user and attaches those to outgoing requests. The tokens received to call external APIs have an aud claim matching the target API.
When a call to an external API is fired, it first passes through an API Gateway. This API Gateway validates the token and ensures the aud claim is actually intended for this endpoint. It also verifies roles and a few other claims.
When the gateway checks pass, the request is forwarded to the actual implementation. Now the actual implementation also verifies the token, but only that the token is valid (e.g. not looking at specific claims). That is not to say that the claims aren't used internally in the application after the token is validated, roles are very much part of the application logic.
So to summarize this as bullet points:
User signs in to portal
User performs some action that causes an API call
Portal attaches token to outgoing request
Request hits gateway for 1..n claims are validated
Request is forwarded to actual implementation
Implementation again validates token is valid, not looking at claims
All endpoints are public, e.g. I could call any of these from anywhere as long as I have a token.
In the above outlined scenario, I'm handling the token properly?
In general, what is the recommendation for tokens passing through several layers of an application? Should every layer validate the token? If yes, are there exceptions to the rule?
Typically, JWT tokens are validated when are sent from the client-side to the server-side. As these tokens are signed, if anyone tries to tamper with the token before sending it to the server-side endpoint, the token verification will fail, therefore these tokens are a secure way of sending the session of an authenticated user to an API or a server endpoint.
These JWTs can be also transferred between servers or different application layers, and it always would be a good practice to verify the token before processing it. It is adding a layer of security to avoid anyone sending tokens to that layer directly and skipping the validation.
I'm new to keycloak and would like to check what is the common design on the said architecture.
I have 1 backend(quarkus) 1 frontend (angular) and 1 flutter.
I would like to see if I could leverage the features of client. My idea is to have a separate client within the realm. For example
REALM = MyAppRealm
Client = backend-client and front-endclient
Is it possible that the token i got from front-endclient can be use to access the api from the backend?
Reason I have this setup is that the front-endclient has a public accesstype while the backend has confidential
to sum up. I would like to see if i can reuse the token i got from front-endclient to my backend-client
Yes of course you can do that.
The purpose of openid is to share authentication and authorization between a diversity of clients without needing to share credentials (no password is known by any of the clients). A trusted third party (here Keycloak) will give back a signed token in exchange for credentials. And this token will be a proof of who the user is and what he is allowed to do in the communications between the frontend and backend.
To sum up :
Your angular frontend authenticates an user using a public client and an implicit flow. When successfully authenticated, the frontend obtains an access token and a refresh token.
When making a REST call to the backend, your frontend needs to set the header Authorization using the access token as a bearer token ('Authorization: Bearer insert access token here'). You can automate this by using an interceptor (example)
Finally, when your backend receive an API request it can check the Authorization header to ensure the request is authenticated and authorized. For how to do that with Quarkus, everything is explained in this documentation page : https://quarkus.io/guides/security-openid-connect
When a user logs out (sign out) of the application, how does the gateway communicate to all services that the user has logged out?
In other words, what happens when a user logs out in microservice architecture application?
This is generic question, I will give my personal thoughts.
Let's take a Single page application, talking to bunch of Microservices and secured by a Gateway that validates the token.
When user logs in, token given by auth server is stored within browser storage(ex: localstorage).
When user log out, no communication is sent to Gateway or auth server, tokens will simply be deleted from browser storage.
So, if someone gets hold of access tokens, they can be used to call services as long as access tokens doesn't expire.
This is typically why there are two tokens given by auth server, an access token and a refresh token. Access token which is used to secure apis expires pretty quickly and a refresh token which has much longer expiry time can be used to get new access token.
As you've included the JWT tag, so I'm trying to give the response by considering that only. The JWT token is a self-sufficient encoded token that contained certain attributes including an expiration period. The sole purpose is to provide stateless authentication. Authentication service usually returns two token, access_token and refresh_token. Client store both of them in some storage on their end. Access token usually issued for a very short span of time and so the client can use the refresh_token in order to get a new access_token on the expiration of the latter. One can access the services until refresh_token get expired. After that client has to go through the authentication process to get new tokens. In case when user logout from the system client should remove both of the tokens from its storage. Because as there is no state maintain in the case of JWT, the server can still accept the old token until they're not expired.
Validation of token for expiration and integrity should be done at the gateway level.
One can avoid the use of the token for service to service communications as those are internal services and running in a private network although one can do the same validation at this level too.
So in case of user sign out, the user's auth token should be removed from the client-side and the gateway should not communicate to other services. There are other special cases where token revoke is a particular case that could be handled by taking the help of distributed cached store in scaleable authentication systems.
A token-based service can generally infer the following from a token -
Who made a request?
Upto what time this token is considered valid?
Which actions are allowed when using this token?
A token based service just accepts or rejects a request depending on provided token, regardless of whether it is a user or a machine making the request. A logged-in user is just someone who can perform actions which this user is authorized to do. A token is a limited representation of such a user.
My point being, it is the application telling the user that they are logged in (have a token it can still use), or logged out (no token yet, or expired). Such a token is obtained by authenticating to the service using ones username and password.
Answer is based on my knowledge, so everyone, please do point out mistakes if any. I don't know in detail about aws api gateway stuff, so maybe someone else can brief you on it in case it works differently.
I'm struggling with setting up reliable and performant solution to communicate frontend with different microservices. I do not really now how to maintain (maybe not need) CSRF between my frontend and end services
Solutions stack: PHP, Laravel Passport, JWT, oAuth 2.0, Axios
Current approach:
Actually I've started up with approach from Laravel's passport
https://laravel.com/docs/5.4/passport#consuming-your-api-with-javascript
Using oAuth 2.0 to authorize user from website A to service B.
JWT token is returned for further communication.
Token is saved in cookie within website A
Once user is authorized website A uses JWT token to manage requests without additional to oAuth server, by sending JWT token as cookie using HTTP headers (withCredentials) to authorize user.
For each website A's request there was CSRF token created from service B since user is authorized and cookie could be applied by another unauthorized website to access service B. That was killing my performance since it has to retrieve CSRF for each request made. (that what I actually assume from laravel passport approach and need to create CSRF with JWT token - maybe that was mistake)
My concerns:
Regarding to of James Ward post:
http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
The easiest way to do authentication without risking CSRF
vulnerabilities is to simply avoid using cookies to identify the user.
Cookies themselves are not the cause of CSRF vulnerabilities. It’s
using the cookies on the server to validate a user that is the cause
of CSRF. Just putting an authentication token into a cookie doesn’t
mean it must be used as the mechanism to identify the user.
From my understanding setting JWT with website A's cookie with its domain set could not be accessed via any other site from outside. Since that there is no possible way to make request to service B without accessing JWT.
So do we really need CSRF then to secure potential attack to service B while using JWT?
If so, how could I achieve the best (in term of performant) way to generate CSRF through different services to be sure that communication would not be vulnerable for attack from different sites?
Any advice will be appreciated!
I'm developing an Android app that consumes a REST service that uses OAuth protocol. In the first activity, app shows a login screen. This is the flow:
1) User puts her username and password.
2) App makes a request to REST service, providing username and password.
3) REST service check the credentials and if are correct, ask for an access_token to my OAuth2 provider server.
4) REST service answers to the app providing the access_token and the refresh_token
5) In the next requests to the REST server (to get data like people, articles...) app will provide the access_token and the refresh_token.
6) When REST service process a request, will validate the access_token (using an token info endpoint of my OAuth server).
7) If the access_token is correct and has not expired, REST service will return the data that the app were asking for.
When REST service detects that access_token has expired, asks for another with using the refresh_roken.
Now, my questions:
When REST service retrieve a new access_token after the old one expires, has the REST service send it to the app in that response?
If so, has the app check, in each request/response, if new a new access_token has been sent from the REST service?
I don't know if I'm in the right way, I'm trying to understand the flow.
Thanks.
Assuming there's no browser involved and the app (aka. Client) uses what is called the Resource Owner Password Credentials grant, the flow is:
the User (aka. Resource Owner) provides his/her username and password to the Client
the Client makes a Token Request to the Authorization Server, providing username and password
the Authorization Server checks the credentials and if they are correct, it provides an access token and optionally a refresh token to the Client in the response
in the requests to the REST server (to get data like people, articles...) the Client will provide the access token
when the REST service process a request, it will validate the access token calling the token validation endpoint of the Authorization Server or by validating the token locally (e.g. if the access token is a JWT).
if the access token is correct, has not expired and has the right permissions (aka. "scopes"), the REST service will return the data that the Client was asking for
when the Client detects that access_token has expired (e.g. because the REST server returns an error), it asks the Authorization Server for another access token using the refresh token using the so-called Refresh Token grant/flow
OAuth 2.0 flows:
An application registers with the auth provider e.g. Facebook, Google, etc with app name, website and callback/postback URL
The application receives the client id and secret from the auth provider
The application user accesses the auth provider for authentication and user approves the resource permissions
The auth provider returns the auth token with respect to the user permissions to the application
The application accesses the resource provider using the auth tokens
The resource provider returns the protected resources after validating the auth tokens to the application
Do comment if you need more understanding!