Is sending JWT in a query string via email secure? - security

I'm implementing a simple passwordless auth system.
The Auth Server will generate a JWT (based on user's email) and send a link to the user's email in the format http://www.CLIENT-WEBSITE.com/?jwt=aaaa.bbbb.cccc.
The Client website would then store that JWT in local storage and send it in the Auth Header (bearer scheme) in all subsequent requests to the protected API Server to access it. It also immediately redirect to the Client's homepage so if the user chooses to bookmark the page they don't bookmark the JWT in the URL.
Is this a secure implementation? And if it isn't, what would be a better way to send the JWT from the Auth Server to the Client via email?

Since the email is sent using a SMTP server that you probably do not own and the communication channel could not be encrypted, the general answer is NO, because the message can be intercepted.
If you require a TLS channel to the SMTP and the mail, and you trust in the mail server to accept only TLS to download messages, then the answer could be MAY BE, depending on the IT infraestructure holding the servers.
If the message is encrypted using user's public key, YES the message is secured but you probably do not have that public key
Sending a JWT by mail is risky, I suggest to use a double factor system added to the email link. For example something the user knows like a password or a private data, o something the user has, for example a phone line number ( sending a sms) or a digital certificate(cryptographic key pair generated on client side). If the double factor verification is correct, then issue the JWT
EDITED - added use case
From your comments, you are in the MAY BE scenario. Managing SMTP and email server you can ensure TLS encryption protects transmission of message between servers until the message is delivered to client.
After this you lose control. This means that the user can download the email, forward it, or just store in its machine. The JWT is self-contained and it is valid until expiration time, so anyone in possesion of the token has the keys of the home.
The format of the link is not important but I would change http to https
You have to assess if the risk level is acceptable or to issue the JWT you need to ensure identity adding a second factor check like the one I propose. In the end we must reach a compromise between security and usability

Related

How to secure webhook identity

I am developing a service where customer can register their webhook URL and I will be sending updates on the registered URLs. For the sake of security, I want to let the client (receiver) identify that its me(server) who is sending them the request.
Facebook and Github both sends a X-Hub-Signature containing the hash of the payload prefixed with a secret key.
I can follow the same strategy. But what if I simply use jwt:
On registering the webhook I share a secret key with the client.
Then in each webhook request I will be sending a jwt computed using the same secret key.
I don't know much about cryptography, but the jwt approach seems more efficient as I don't have to compute the signature again and again because I am not using the payload in the signature.
But then why both Facebook and GitHub follow the other approach?
The content on this site may be out of date. For the most accurate and up-to-date content, visit
Using a MAC (Message Authentication Code) allows one to authenticate a message, as implied by the name. Sending a secret with every message is not wise, as this is likely to result in the secret being compromised. An attacker might intercept one of the messages and then start issuing spoofed messages.
Another thing which you might want to consider is replay attacks. What if an attacker intercepts a message and sends the same message later?
Edit: Using JWT is fine, as it includes a MAC, but you must make sure that the payload is authenticated (i.e. included in the computation of the MAC).

Restricting traffic to server from only my mobile application

I have a requirement to secure my JAX-RS resources and only accept requests that originate from authorized mobile applications. Is this possible? How can this be done?
All of my resources are protected already with user authentication, the goal here is to reduce user ID fishing attempts. I know one solution would be to keep the response error with an invalid user ID generic, but the application is very large and at the moment this isn't possible.
One idea I came up with is to use JWT tokens signed with a shared secret. Then I could add an Authorization filter on the server to check the signature. If it doesn't validate then discard the request. Does this sound like a viable option?
My concern is the security of the shared secret on a mobile device, could it be compromised with a rooted device?
Using tokens is the preferred way. But the secret key is not shared. Only the server has access to it. That secret key is used to generate the message authentication code(MAC) of the JWT. Since secret key is only known by the server, no one else can generate a JWT with a valid signature. Secret may be persisted or application scoped.
Once a client is authenticated using credentials, server must send a signed JWT to the client.
That JWT must contains necessary information to identify the client and state(if necessary).
Then client send that token in a header field along with all the other requests.
Server validates the JWT using secret key and process the request.
Even though client can change the JWT body, he cannot get it verified. That's the whole point of using a signature.

security - how to secure api key in HTTP GET request

I'm new to cryptography and I'm trying to prevent against man-in-the-middle-attack in a web service I'm developing. The way the web service work is that a user registers on the service using his email address and password and creates an application. Each application is given an application id and an application key. The application id is public (that's how the public communicates with that application) but the application key is private. The user credits his application by loading a pin (a 16 digit numeric string). Loading the pin is done via a HTTP Get request.
Now here is my question: how can the user do a HTTP GET request with his application id (the way the server identifies the application) and his application key (the way the server authenticates him) without compromising his application key?
Because our server has SSL (and I read that SSL protects against man-in-the-middle-attack), I was thinking about simply having users submit their application id and application key as parameters in the GET request, but after reading around, I decided this may not be secure. This is also because after doing the HTTP GET request to load the pin, the user may configure his account that we submit the server response via another HTTP GET request to a URL of his choice. And since we want to do an echo back of his application id and application key so he can authenticate that the request was really from us, I was worried his key might be compromised.
So I decided we should have the user do a md5 hash of his app id and app key to provide a hashed parameter and submit that instead of his app key in the GET request. Then on our server, since we already know the user's app id and app key, we can simply do an md5 hash of both and compare it with the hash parameter the user submitted. But then I also thought that may be insecure because if someone intercepts the hash parameter, the attacker can use that same hash parameter to submit several requests since the app id and app key is static. So in the long run, the hash parameter is no different from the app key.
Now I'm thinking, we should have the user do a md5 hash of his app id, his app key and the pin he wants to load to get the hash parameter. This way, since the pin is always different each time, even if an attacker intercepts a request, the authentication process would not be compromised for other requests because the attacker would not be able to reuse that hash with other requests.
For example, if a user has the following credentials:
1. app_id: 1234
2. app_key: bghuTHY678KIjs78
And a user wants to load the pin: 1234567890123456
He generates the hash by doing an md5 hash of "1234:bghuTHY678KIjs78:1234567890123456". That gives him 210a4c92d85473af9d5f48b4ee182ddd. Then he does a HTTP Get request to the address below:
https://example.com/process?app_id=1234&pin=123456789012&hash=210a4c92d85473af9d5f48b4ee182ddd
Is this method secure? Or should I simply just have the users submit their app id and app key in the HTTP GET request since we have SSL?
The user secret should never be sent over the network. Instead, ask the user to sign his requests using his secret. HMAC is the relevant algorithm.
By the way, MD5 is obsolete and insecure for all crypto needs.
Use Secure Remote Password (SRP6a) and register a password verifier and salt for the 16 digit pin. The pin you never send to the server (you can store it in browser local storage for convenience of the user). Then authenticate the client using SRP6a which results in a strong shared secret session key for each successful authentication. Then use HMAC SHA256 to sign API calls using the session key. See the thinbus-srp JavaScript library and its demos of using SRP6a to authenticate resulting in a session key. See the JWS "HS256" (HMAC with SHA-256, 256+ bit secret) algorithm and any library implementing that as an example of signing a web API with a shared secure key.
The SRP6a authentication protocol is a secure zero-knowledge password-proof where the server does not know the password. The server issues a random challenge to the client which generates a password-proof based on the challenge. The server uses the verifier the client provided for their password to check the password-proof. If the 16 digit pin uses uppercase letters like a standard software license key it is infeasible to run a dictionary attack on the verifier. Use the modern browser webcrypto secure random number generator to generate the pin at the browser. Even you won't be able to obtain the password.
The overhead of using SRP6a to authenticate is that you need the client to first fetch the server challenge. The benefit for your use case is that if the client provides a good password-proof based on the challenge the both the client and server share a secure session key. No-one intercepting the traffic can know the session key. With that shared secret you can sign and verify every API call and verify the signature at the server. No-one intercepting any part of any exchange between you and the client end-to-end from registration through to usage can gain any advantage.

Font End secure authentication only allowed to come from a specific website

I have a private rest API. Each of our clients websites currently performs server side authentication over SSL to start an order with us. Each client has a unique client id so I can identify which client is making the request and reject any client id which doesn't exist in our system. Is there a way to do this securely from the front end of a clients website with javascript? I can't put the client id in the client code since any developer could look at the source code and figure out how to spoof requests from another site. I think checking referrer headers is not reliable as well? Would really like to know the best practice for situations like this.
Not sure if I understand your question correctly, but typically you would encode your client id as a claim in the security token issued when authenticating your users. As the security token is signed by the issuer, you can verify that the token is not modified when you receive the token on each request.
Obviously you will need to use the https protocol to prevent the token from being stolen. See here for more information.

Is there a secure way to connect to an IMAP server on behalf of a user?

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.

Resources