I have the following scenario, in my vertx application I have an endpoint /login that after receiving correct credentials is issuing a JWT with 30 minutes validity.
I use this token to protect all routes under /api/* endpoints.
All of this is working as expected.
My problem is that I want to be able to intercept those /api/* requests and just before doing the token authentication to inspect the token and if it is about to expire to generate a new one that can be returned in the headers of the response so the client can use it on consequent requests.
What I want to achieve is:
avoid issuing forever valid tokens as if leaked I have no way to prevent access to the application
avoid maintaining a token blacklist of anykind
avoid having to issue very short living tokens and reissue those on every request
In general any kind of strategy is welcome.
Thanks
In order to handle a request before the JWT validation all you need to do is add your custom handler before the Auth handler e.g.:
Router router = Router.router(vertx);
// Create a JWT Auth Provider
JWTAuth jwt = JWTAuth.create(vertx, new JsonObject()
.put("keyStore", new JsonObject()
.put("type", "jceks")
.put("path", "keystore.jceks")
.put("password", "secret")));
router.route("/api/*").handler(ctx -> {
// here do what you're planning to achieve, and the call
ctx.next();
});
// protect the API
router.route("/api/*").handler(JWTAuthHandler.create(jwt, "/api/newToken"));
Related
I have Single Page Application(SPA) with multiple endpoints using Singe Sing On(SSO) with JWT token. I try to figure out how to initialize a CSRF token while still keeping my frontend and backend logic as simple as possible.
My question is: Is there a way to avoid generating a CSRF token for every endpoint? So can I, for example, generate CSRF token during my login process (first fetch CSRF token and rotate the token in every login request) and then verify that one CSRF token in every backend? How could this be implemented if it is somehow possible?
I use X-CSRF tokens, so on the server side the token is set to cookies, then the client duplicates it to request headers and finally server verifies that cookie and header value match. I use django csrf middleware which also does some extra validation to avoid client self generated tokens. This extra validation is something I do not really understand
In my opinion, what you have in mind is not possible. But you could communicate with a proxy that knows the other endpoints. That would make the most sense from my point of view. So you only need the CSRF token for this one endpoint. And on the server side from the proxy to your other servers you don't need CSRF anymore. But this solution means you need an additional endpoint.
What would be the recommended way (simple, and secure) to initialize CSRF token when working with Single Page Applications?
I have figured out some possible solutions but all of them have some downsides:
a) Before login or any request, create CSRF request to obtain a token.
Downside: The Client/frontend should implement logic to request CSRF if it is missing
b) Exempt login request from CSRF protection and initialize token on every login
Downside: Is it safe to exempt login from CSRF protection?
If using multiple endpoints and Single Sing On, we still need to init CSRF token in every endpoint
c) Init CSRF token when the client request a frontend code (on SPA load / refresh)
Downside: Complex logic and extra request to backend needed in frontend providing endpoint
If we use multiple endpoints and can not validate the same CSRF tokens in every endpoint we do not know where to init the token
The current solution/answer to this problem is the following:
Client sends a CSRF token request
Server adds CSRF token into client cookies
Client sends a login request with his credentials and copies the CSRF token from cookies into headers
Server checks the cookie & header match and processes a login request. The server sets a session cookie and rotates a CSRF token.
Other (login required) endpoints check header & cookie match AND validate session cookie.
When working with multiple endpoints
Implement BFF or proxy server which handles the CSRF protection. Allow connections to the server endpoints only from the proxy/BFF server. The endpoints does not need CSRF protection anymore.
All requests from Client / browser is routed through the CSRF protected BFF/proxy server.
Pros
Login requests are now protected with CSRF
If multiple endpoints are needed, only one CSRF token init request must be done.
CSRF token is rotated and unique in every new session.
Cons
Client/frontend should implement CSRF request logic and missing CSRF token error handling thus increasing the complexity. CSRF token init can not be done silently for example during the login request.
When working with multiple endpoints, separate BFF/proxy server is needed.
I am trying to understand this access_token, refresh_token feature. And this is what I understood:
-- LOGIN:
CREATES access_token;
CREATES refresh_token, sends to DB;
SENDS refresh_token + access_token to client;
access_token expired:
API automatically CREATES a new access_token, using refresh_token;
refresh_token expired: API DENIES all requests, forcing the client to login again.
And i heard that you need to save the refresh_token on a 'sessions' table of database, or smth like it. But i can't understant why, since the client will/may send the refresh_token on all requests. Making it useless to save to DB.
I don't know if i got anything wrong, i hope you can help me out!
What is a little bit awkward (or unclear) in your example - which system creates access and refresh tokens, and sends them to the customers?
Based on the description, I would conclude that this is the identity provider - the client authenticated themselves and got those tokens as a result.
Now when the client calls an API (on a resource provider), they have to include the access token with each request. The resource provider would take the access token and validate it. If the access token is not valid, the API just have to return "access denied".
The client has to use the refresh token to get the new access token from the identity provider and repeat the call to the API on the resource provider.
This would be the typical usage of the flow.
The other common use case is to allow a backend system to do api calls on behalf of the client - in those cases, the backend system has both access token and refresh token; so it can maintain the logged in state even if the client is not around.
It might be that your example is some kind of hybrid solution - both customer and the backend do some calls to IDP.
I am setting up auth using access tokens and refresh tokens. I am largely there, but I am having trouble understanding how to refresh the access token. From what I have seen from here and other resources, most people seem to set up route handlers to refresh the token like so:
#UseGuards(JwtRefreshGuard)
#Get('/refresh')
refresh(#GetUser() user: User) {
return this.authService.getAccessToken(user.username);
I am using a custom guard using a passport strategy to validate the refresh token:
async validate(request: Request, payload: JwtPayload) {
const { username } = payload;
const refreshToken = request.cookies?.Refresh;
return this.userService.getUserIfRefreshTokenMatches(
refreshToken,
username,
);
What I am not understanding is how to implement making a request to this handler without interrupting the app user's normal operations, and how to check if this handler needs to be called when an access token expires.
how to check if this handler needs to be called when an access token expires.
When you make a call with jwt token from the client to the server if it is expired(which is the case that we use refresh token) with jsonwebtoken npm package we can send a callback to the client with the message "Jwt expired"(since you are validating the jwt you can identify if it an expired token). Then the client can send another request to your /refresh endpoint on the server requesting a new jwt token. Then you can send the new jwt token from the server to the client and the client can use the newly created jwt to send requests to the protected routes on the server.
On client side you can control access token expires. So, if the access token has 5 minutes of life, and was born 3 minutes ago, then only the access token can be transferred to the backend. But if 10 minutes have passed since the birth of the access token, then the client must first send a refresh token to the backend, and continue to process the current request only after receiving a new access token.
Folks,
What is a simplest way to track consumer applications accessing RESTful API services inside department.
We do not restrict access - no authentication/authorization - open for invocation, trusted environment.
No tools like OAuth AuthZ servers or API management yet... but might be heading there at some point.
For now we thought to request consumers just to include some custom HTTP Header like X-Client-Id and log it on the server side for stats etc..
But knowing that in the future we might want to switch to more standard ways of doing things ... what would be best alternative to have to change less code in the future ?
Have the "clientId" in the Authorization: OAuth token (like access token)
Have JWT token in the Authorization header (looks too much - signing,base 64 etc for simple client id tracking ...)
Any ideas would be appreciated
We recently implemented this for one of our REST platforms and we used a combination of BOTH the points you mentioned, meaning Authorization header & JWT token. Although, JWT is ONLY for authentication and GETTING an access_token (oauth token) which is later used with calling actual resource apis. I will discuss how we handled this situation and you can decide on how you want to implement it.
1) Authentication
Client sends a JWT to your authentication service (/api/oauth2/auth). (If you want more reading on JWT, you can read here and here of how JWT is implemented by google and how you can use spring-security-jwt libary to handle all the signing and encrypting/decrypting). You get the "clientId" out of JWT after decrypting and verifying the signature and after server does all the authentication, you respond back with a 'refresh_token' and an 'access_token'. Server will save the access_token as well and map it to the clientId so that when client makes requests using access_token, you can know which client is making the request. The access_token expires in some time (ideally in an hour) and when it expires, the client uses the 'refresh_token' to get a new access token by posting refresh_token to some refresh token url (/api/oauth2/auth/token)
2) Authorization
Client takes the 'access_token' and uses the access token to make all the subsequent requests on all other apis (/api/*). Ideally, the access_token is sent as a part of the "Authorization" header. Server uses request filters (if you are using JAX-RS, you can use something like ContainerFilterRequest to add filters to specific url patterns and intercept them) to filter EACH request and parse out the Authorization header value. You will get the access_token from the header and from the access_token you can get the clientId that you mapped in step 1). You can do other authorization logic in the security filter and if everything goes through, you can use this information to LOG that clientId and the request that the client made.
This way you can kill 2 birds with one stone : Implement a security layer & log the information about customers (what calls they are making, how many time etc. etc.). In case you don't want to implement security filter just yet (as you mentioned it might be in the future), for now, the clients can just pass on the "clientId" (base64encoded or not, upto you) as a part of "Authorization" header. If all the calls are from a "trusted" network, it should be ok, although not as secure. This way, when you ACTUALLY implement a JWT and Oauth based security layer, all you have to do is change your ContainerFilterRequest logic to parse out access_token instead of client id (as mentioned in step # 2).
I hope this helps ! For more information on security filters you can have a look at this answer: Basic Authentication of a resource in Dropwizard. It says dropwizard, but it mostly talks about JAX-RS.
To implement full AuthN/AuthZ layer for consumer tracking would be an overkill for now.
We thought to use either to Authorzation header to pass custom client_id token:
Authorization: Custom <Client_Id>
or to use some limited version of JWT (no signatures as there no intent to validate them)
as access token
Authorization: JWT <JWT>
Where JWT could be:
{"alg":"none","typ":"JWT"}
{
"iss":"Client_ID",
"aud": REST Service URI,
"iat":1328550785
}
I do not see description of access_token format in the specification https://datatracker.ietf.org/doc/html/rfc6749#section-1.4
Are there any contraints to use JWT as access token?