3

We have two applications App1 and App2. A user uses a browser to communication withe apps. App1 supports different auth. mechanisms (SSO, usr/pwd, etc.) but App2 doesn't have any access to auth data and doesn't support any auth. mechanism. So we need to provide an authorization mechanism for App2 to apply some access control. I thought of SSO and JWT for this issue. Meaning that:

  1. App1 plays the role of auth. server and whenever the user wants to connect to App2, s/he is redirected to App1 for authentication.
  2. After a successful authentication, a JWT token is generated by App1 (The token contains user_id and user_role).
  3. The token is set into the header and the user is redirected to App2.

Assuming that all the communications are done over HTTPS and PKI is used for signing the token, here are my questions:

  1. Is a simple signature verification by App2 is enough? Or there is a need that it sends the token to App1 for verification (there is a white list of public keys for App2) ?
  2. I'm considering to add an expiration date for 30 mins, how should I handle refresh token at the client-side ?
  3. Instead of generation refresh tokens, is it secure to say that the access token is one-time only and App2 creates a session on the server-side (using the data in the token)?

Thank you so much for your help :)

sgres
  • 129
  • 2
  • 8

2 Answers2

3

As a Developer

Unless your APP 1 is built to be federation service, you shouldn't be extending APP1 to act as a federation service. This is just bad software design.

If APP2 lacks authentication and authorizations, you should, logically just add that into the application. It can be a SSO method but make sure it's authenticating with a Service Designed to do Authentication/Authorizations.

If APP1 and APP2 have nothing to do with one another (which sounds like it) than DON'T CREATE A DEPENDENCY VIA AUTHENTICATION.

As a Security Professional

To Answer you questions:

  1. This depends on your risks and how important these applications are to the organization. You might want to re-read about JWT's. In order to verify a token, you need the secret, and in your design APP1 has it, and you either need to have it also on APP2 (exposing more risk) or rely on APP1 to verify the token at which point you need to ask yourself "Why would APP 1 care whether the token for APP 2 is valid?" The answer is because you built an unnecessary dependency for APP 1 to be responsible for APP 2's safety.
  2. By the nature of tokens, you don't handle them client side, if a token is not refreshed it expires, it's no good, you should be denying it. A refresh token is used for generating a new auth token once it's expiration is hit. A 30 min refresh token means that after 30min you need to fully re-authenticate. If that was your goal, than have no refresh and 30 min auth tokens.
  3. The purpose of a token system is to remove state from your application. If you are going to be doing sessions, than do sessions and ignore tokens. If you want to do One-Time-Passwords, for APP 2 Authentication, than do OTP, it's horrible to both because to you have all the risks of both and no good reason for both. I would read up on sessions vs token authentication.

My opinion of this based on your question -- It will be a security management, IT management, and Dev Management nightmare have an independent app relying on another independent app for authentication services.

I am sure there is more to the story, but if I was doing decision making on this, there would be a lot of "would you explain to me why this makes sense?" comments.

Shane Andrie
  • 3,780
  • 1
  • 13
  • 16
  • thanks for your answer, it clears my mind. So my conclusion is for small projects, it is unnecessary to have an AuthServer and a WebApi server separated. It makes sense and it reduces the unnecessary complexity. – Franva Apr 13 '19 at 14:17
1

This is a pretty common situation you find yourself in which is a good thing as it means the solution is well known, discussed and tested.

  1. Is a simple signature verification by App2 is enough? Or there is a need that it sends the token to App1 for verification (there is a white list of public keys for App2) ?

Correct, a "simple" signature verification is all that App2 needs to do to validate the token. This will guarantee a.) the token was dispensed by App1 and b.) the claims (key-value pairs) in the token have not been tampered with.

  1. I'm considering to add an expiration date for 30 mins, how should I handle refresh token at the client-side ?

This comes more down to personal preference, but I do not like refresh tokens. Refresh tokens imply a distant future expiry date (i.e. couple days or a week) and can be very damaging if they are stolen. Furthermore, in my experience, there is no truly good way to store a secret on the client side. Cookies are insecure and I do not believe client side DB's are much better. You could encrypt it with user password but that requires the user to re-type the password which defeats the purpose of the refresh token anyways, right? So I would avoid refresh tokens if possible.

  1. Instead of generation refresh tokens, is it secure to say that the access token is one-time only and App2 creates a session on the server-side (using the data in the token)?

I do not see any flaws in this plan, I think it is much more secure than relying on a refresh token. The only caveat here is to ensure there is an ability to void a access token on App1. For other words, if I authenticate against App1, get my token then come to App2, authenticate and get my session ID, I am happy. But, an attacker could steal my token from my browsers cookie. The attacker can use this token to go and get his own session with my credentials at App2 as long as the token is not yet expired. Therefore, App1 and App2 would have to be able to communicate in this scenario. App2 checks that App1 says the token has not been used yet. App2 uses it, then tells App1 it was used, please void the token so that it cannot be re-used in future requests to generate another session ID.

As you can see, that gets a lot more complicated. But, if you do not do that, you are not really using one-time tokens. An alternative would be you make the token expiry VERY short (i.e. five minutes or less), enough time for the user to be re-directed and authenticate with App2 and get their session ID for continued authentication. This might be the simpler route but it really is dependent on the level of security you wish to reach here.

Either way, the Session ID is a smart idea. It would likely reduce the load on your App2 server as it will not have to constantly re-check token signatures for every request.

dFrancisco
  • 2,691
  • 1
  • 13
  • 26
  • @dFracisco thank you for your complete answer, it help me a lot! – sgres Feb 02 '18 at 16:43
  • Regarding _I would avoid refresh tokens if possible._. What if your app is streaming very important info that cannot be interrupted by expired token? Like some vital data in a hospital during surgery. And token lives only 20 mins, not more. And app streams for 10 hours, no interruption allowed. You can't go without smart mechanism of refreshing token "on-the-fly". – Green May 30 '18 at 06:36