Hi, Currently we are working on a web application and we are using JWT for authentication once user login successfully for the respective request.
My question is If some how the secret key for generating signature is out so server to ensure security the secret key need to be updated and server need to be down and user must be asked to login again.
Is there is any better solution in such condition?
Are you asking about what to do if the private key is compromised? Yes, then you need to update to a new private key and invalidate everybody's sessions. There is no better solution because you cannot distinguish between a validly generated session and a maliciously generated session.
Related
I'm creating a REST API to store some information about some items.
It is nothing highly sensitive or anything but I still want to properly secure it. Also in regards of maybe having to secure something else in the future.
To sign the users in I'm using OIDC with Google and Azure to retrieve user information from the user information endpoint. After that I want to store the user in a database along with their permissions. For them to access the API I want to generate and sign a JWT Access Token and Refresh Token. So far so good.
I want the acces to the API to be stateless (with the Access Token) for scalability. I'm not so much worried about the sign in process being stateless. The refreshing of Access Tokens via the Refresh Token also doesn't have to be stateless, but it would be nice to have.
I was reading through some other questions and articles online regarding XSS and CSRF. To me it all boiled down to two things:
Don't use local or session storage to prevent XSS-Attacks grabbing tokens stored there. Solution seemed to be to use cookies (http only cookies, samesite).
Don't use cookies as to prevent CSRF.
I'm now kind of stuck because the two options seem to recommend not using either.
I thought about how this might be solvable and was reading through OWASP recommendations mentioning generating a fingerprint during sign in and storing it in the JWT as user context.
In my mind I have the following process.
Sign the user in using OIDC and receive information about the user from the user endpoint.
Look up the user in the database and get their permissions.
Create a unique fingerprint for the user.
Store the fingerprint in a hardened cookie (http only, secure, samesite).
Create a JWT Access Token using the users id, permissions and an encrypted string of the fingerprint.
Create a JWT Refresh Token using the users id, permissions and an encrypted string of the fingerprint.
Sign both JWTs.
Return the Tokens to the client with the hardened cookie set.
Now if the user wants to access a protected resource he sets the Authorization Header with the Access Token and sends the request, which will then also include the hardened cookie. The server can decrypt the fingerprint from the Access Token and compare it to the fingerprint from the cookie.
If the user wants to use the Refresh Token to get an expired Access Token the fingerprint would also be validated before issuing a new Access Token.
Access Tokens would be short lived e.g. 15 minutes. Refresh Tokens would be long lived e.g. 1 day.
In my mind this solves both problems:
Leaking of the tokens would be useless without also having the fingerprint from the cookie or the cookie itself.
Leaking the cookie via something like CSRF would be useless as the Tokens would not be available.
Only if an attacker would simultaneously get hold of both he would be able to have access.
My questions are:
Am I overlooking something?
What would be a good way to generate this fingerprint? Use the "sub" from the user endpoint?
Thanks for your help already!
I want to use JWT in my application.
Now I'm wondering if it is secure to use the users password in combination with a private secret as a key to sign my tokens. This way, tokens get invalidated if a user changes his/her password.
But maybe it makes my private secret vulnerable?
Thanks for your thoughts on that!
The secret is a preshared string exchanged between the client and the server.
So in your case:
SecretString= PresharedSecret + ClientPassword
So, everytime the client passes a JWT token, you would need to retrieve the password from the database or have some way of preloading it and a check in case of password changes for validating the token.
This might lead to the following scenarios:
Everytime the client forgets his password, you might need to make database calls that can be expensive
It would enhance security in one way, as anyone who changes the password will not be able to communicate with the server with knowledge of the previous SecretString.
A new preshared secret will need to be decided.. and validated with the new registered password.
Overall, it does increase security. However, it depends on the purpose or the usage of the infrastructure. If it is a system in which users frequently forget passwords.. this might not be a great option.
The usual thing is to sign all the tokens with the same key. Simplifies the management and avoids querying the database in each request.
Signing with a key+user password is feasible and has the advantage of allowing to revoke tokens (with the commented drawbacks).
Ensure that your signing key is enough secure deriving it from user's password and has the recommended length of the selected signature algorithm. Do not store or use user's password directly.
Whether it is cookie signing, super user username and password for the database, or JWT token signing, on the server side there are secret keys to secure the action.
However this key is likely just a plain string on the server code. I have been wondering is there any more procedure to protect these key strings on the server side? Concerns about this, for example, if the attacker managed to get an access to the server's ssh then he could easily get the key. Or should I assume that I have already lose everything once an attacker can access the server?
(This leads me to assume that putting secrets directly in the code is what everyone is doing and is the common practice.)
I would like to implement authentication for a web app api using a similar technique to the AWS Signature Process. The server will render html for user web browser clients. The app will also return json for non-browser clients (iphone, android, blackberry, ipad, etc.) I am trying to write authentication code that will allow a single user to be signed (remembered) in to the app from multiple clients. Logging out from any one client should not revoke the token/cookie for all the other clients.
When a user sign up or logs in, how does a client (native mobile client or web browser especially) get the private/secret key? My understanding is the key should not be sent over a network? Can it just be sent over ssl?
For browser clients is the private key stored in a cookie or in some other form of local storage?? I.e. for generic api token authentication would the token be stored in a cookie on the browser and in a db on the phone
When the client is a browser, how does it sign a request signature with private key? i.e. generate a hash of the id + private key + request. For native mobile clients or server to server communication I believe there are libraries that can be used to generate a signed request. When the request originates from a browser how does this work?
If a user is required to be remembered on multiple clients (tablet, iphone, work computer, home laptop, etc.) would the user need to have a set of private keys/tokens for each client?
I would have used Devise with Rails but it requires you to write your own token authentication code.
I am also looking at OAuth, which questions 2 and 4 both apply to, but would really like to investigate the AWS method.
You start with a solution (HMAC) but I do not think your "problem" fits your solution :).
I'll try to answer this to the best of my knowledge.
To my understanding ,a private key would be derived of a public key that is shared. Or you could share a private key, but only if authentication is already established (in other words: you already know for sure who you are talking to) and the connection is secured (encrypted). You still will be vulnerable to man in the middle attacks though.
I'm not sure. A cookie is not secure. Steal the cookie, steal the private key. My preference would be a locally stored key(file or storage), encrypted by a password.
You would have to devise some sort of a client side library (in javascript or something like it).
Yes.
Why share keys when you could share a token, like oAuth implements. The token is generated by your application and is valid for a limited time. This way you share access, but not the means to aquire access to your application. You login with username and password (or keyfile) and you get a token that grants you access untill the token is revoked.
I'm working on a web application which involves connecting to Gmail on behalf of a user to check for new messages. Is there a way to securely store the user's credentials so that they can still be recovered for the login, or is there some way to obtain a token for Gmail to use in connections?
EDIT: The application is meant to be used mostly with mobile users, so they won't be logging into the site frequently. Thus, storing information in a cookie isn't viable.
If you logged into GMail's web interface it gives you a token in the form of a cookie. If yYou could use that token and the web interface then you could access their email without storing their credentials. Of course that isn't IMAP access, and it expires (as a good token should).
Alternatively you could encrypt their credentials with a value you store as a cookie on their computer. Then when they access your site you can check their mail without ever storing the encrypted credentials with the key to decrypt it.
Neither is an ideal solution, but hopefully they get you moving in the right direction.