How is a slack webhook safe? - security

I'm setting up slack alerts on a project I'm working on.
To use slack's Incoming web hook, all you have to do is do a POST request to a slack url. I don't see any security on it. How is this secure? Wouldn't someone be able to post messages if he gets hold of this url, given that the url is public even in https connections ?

The docs you linked say:
Keep it secret, keep it safe. Your webhook URL contains a secret. Don't share it online, including via public version control repositories. Slack actively searches out and revokes leaked secrets.
That is, you should keep the webhook URL as secret as any secret (database passwords, ...) in your app.

Related

jwt: Why is my token shown in Chrome DevTools?

I have a API in Express.js that will create blog posts and add them to my database. When I make a request from my React app inside of DevTools it will show my JWT. I am worried that when my site goes live people can see my token and make a request from their site to add unwanted posts. Please tell me what is going on and how I can prevent the security error.
When you send a request with a token in the header it will look like this in the header pane in Developer Tools:
I assume that's what you are wondering whether is safe or not.
The connection between the React app and the API is unencrypted when you are using ordinary HTTP. That makes a replay attack possible – an ISP or another server between the front-end and the API can read the token and pretend to be you later on with the read token.
The most important solution to that is to use HTTPS, which is encrypted HTTP. Potential attackers are unable to sniff and steal the tokens when you are using HTTPS. When you are dealing with usernames, passwords, etc., you should always use HTTPS.
HTTPS is free to use and not very hard to set up. See here for more details. There is also an interesting discussion here that you might want to read.
it's possible to see the JWT on the Chrome Dev tools because you are sending it as authorization header when creating a new blog post on your API, and you are making this request directly from the React application.
If the JWT is sensitive it should never be available on the front-end, you must have a server acting like a proxy, it should receive the request from the React application and then forward the request with JWT as the authorization header to your API.
Doing that you would avoid leaking the JWT, but it would still possible for someone to make requests to your proxy, which will be forwarded to your API.
If you want that only your react application be able to perform requests to your proxy, you could create a middleware which verifies the IP address of the incoming request (more details here), if it matches with your React app address then you accept the request, otherwise, you return a non-authorized error.
If you want only specific people to be able to create blog posts, then you should put authentication on the react application.

Authenticating WebSocket Connections

This may seem like a pretty noobish question, but I just recently got into Node.js and am needed to make sure that the same kind of Authentication that occurs in my Laravel App happens in Node.js.
Clearly, I need to use an API, but I am confused about how to do it in a manner that is secure. I have looked into this article:
https://www.ida.liu.se/~TDP024/labs/hmacarticle.pdf
And have looked through their algorithm into building an API. But I do not understand how it would be secure.
According to the post, you store a public and private key in a Database. The public key can be seen by everyone but the private key is, well, private. However, when sending it to the server, you send a hashed version along with other data, of the private to the server.
This sounds all well and fine. However, does that not mean that the public key and the hash is public, thus the private key is exposed as well?
For example lets say I try to establish the following connection
ws://example.com/pull?public=A89-3NJ2-KAN-NKSN1&hash=QmFzZTY0IHRoZSBoZWxsIG91dCBvZiBtZSBiYWJ5Li4uLi4u
What stops another user from just sharing this link giving an unrelated user access to it?
The article you linked to describes how to authenticate one single request, not an entire session. That is, the user sends the public api_key along with some request data that describes the specific request for the API (like, { "action":"latest_price", "symbol":"GOOG"} for a stock market API).
To authenticate, the user also uses a shared API-access secret key as an HMAC key to compute HMAC(secret, api_key+request). No one else can compute this if they don't know the secret. Only the user and the server should know secret, because it's basically the user's password to use the API.
The situation you describe is very different: you're using a WebSocket, so I assume you'll be sending requests interactively. If you want to authenticate the entire socket session, this approach doesn't make sense, since it's designed to authenticate a single request. You can apply this approach to individual requests inside the WebSocket connection.
For authenticating a new connection (i.e., "what logged-in user is opening this connection?") using auth cookies is appropriate, just as you would for a traditional HTTP connection.
Below, I'll assume that the purpose of the Web Socket is to send only one request (which really makes me wonder why it's a WebSocket), so that the request-level authentication makes sense.
What stops another user from just sharing this link giving an unrelated user access to it?
Nothing. Do you want someone else to submit a specifc request, while impersonating you? Then by all means, give them that link and tell them to use it.
The credentials in the link include an HMAC of the API request (plus your identity) that only you can generate, as the sole owner on your API secret key. If you give that HMAC to someone else, they can submit it and impersonate you for that specific request. However, they cannot create more requests, because they don't have your API secret to make more HMAC values for different requests.
In fact, if you didn't want that request to be submitted, you should not have used your secret to create the authenticating HMAC in the first place! Why did your authenticate a request that you didn't intend to be submitted?
Have a look at this
Essentially
make a "websocket preauth" request to the backend from the browser using the site's normal auth
backend returns a CSRF token in the response body and sets a "websocket auth" cookie with SameSite=Strict in the response headers
attempt to establish a websocket connection with the backend, with the addition of the CSRF token in a query parameter
the backend checks
that the websocket auth cookie and CSRF token are valid
that the value of the Origin header matches an approved domain
the backend sends a response and upgrades the connection to use websockets

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).

How to authenticate requests using ServiceStack, own user repository, and device ids?

I'm building a mobile app and a ServiceStack web service back-end. The Authentication stuff in ServiceStack looks great but easy to get lost in its flexibility - guidance much appreciated. I'll be using my own db tables for storing users etc within the web service. I'd like to have a registration process and subsequent authentication something like this:
the user initially provides just an email address, my web service then emails a registration key to the user
the user enters the key. The app sends to the web service for registration: email, key & a unique device identifier.
the web service verifies the key and stores the email & device id. It responds back with an auth token that the app will use for later authentication.
Then subsequent web service requests would provide the device id and auth token (or a hash created with it). The app is not very chatty so I'm tempted to send the authentication details on each web request.
Question 1: Should I hook into ServiceStack's registration API or just add a couple of custom web service calls? e.g. without using ServiceStack's registration I would:
post to a registration web service with the email address and device id. My web service would send the registration email with a key and add a record to the user db table.
when the user enters the key it would again post to the registration web service, this time also with the key. My web service would validate the key and update the user table marking the user as registered, creating and recording the auth token & returning it to the caller
subsequent requests would be sent using http basic auth with the device id as username and the auth token as password. The service is not very chatty so creds will be sent with each request.
I'll implement a CredentialsAuthProvider that'll get the creds with httpRequest.GetBasicAuthUserAndPassword() and validate them against the db data.
But it feels like I should use registration built in to ServiceStack.
Question 2: What's wrong with passing the authentication details with each request? This would make it easier for composing my app requests but it doesn't seem 'done' based on the ServiceStack examples. Presumably that's because it's inefficient if you have lots of requests to need to re-authenticate every call - any other reasons? My app will only make a single web request at most every few minutes so it seems simpler to avoid having sessions and just re-auth each request.
Question 3: Am I on the right track subclassing CredentialsAuthProvider?
Question 4: Is there any point using the auth token to generate a hash instead of sending the auth token each time? All communication will be over https.
Answer1: It will be OK. if you give multiple call as per requirement. Normally authentication works based on cookie, now you can store it on client and/or on server and match the user with it. Again here if you are using device you, can always use device instead of user to map and authenticate user. Based on your requirement.
I will prefer to use provider as it hides many details which you need to do manually instead. You are on right track. There are many blogs specifically for authentication and how to create custom authentication with service stack. If you like let me know I have book marked some will give it you. Best way to search latest one is checkout twitter account of Servicestack.
Answer2: This is again, I say as per requirement. Now if your user will be in WIFI zone only. (Mostly true for business users), then there is not limit for calls. Just give a API call and do the authentication in background. Simple JSON token will not hurt, It is few bytes only. But again if you have big user base who is not using good internet connection then it will be better to store authentication detail on device and check against that. Just to save a network call. In any case network call is resource heavy.
Answer3: Yes you are on a right track. Still check out blog entries for more details. I don't remember the code snippet and how it works with last update so I am not putting up code here.
Answer4: This is answer is little complicated. Passing data over https and saving user from Identity fraud is little different thing. Now, if you are not generating auth token (hash based value) then you can pass user also over the http or https. Now, this can be used by another user to mock first user and send data. Even data is being passed through https but still data is getting mocked. Hashed based value is used to avoid this situation. And also there are couple of other business use cases can be covered using auth token.
Please let me know if I have understand you questions correctly and answered them?? or If any further details is required??

Is using a long string in a GET variable a secure way of identifying a user?

I am making a Twilio app. Twilio can send a request to the server after a call is over, but it isn't able to be associated with the logged in user of my website because Twilio is making an independent request. If I were to tell Twilio to post something at
example.com/response.html?token=ba38pgab38g4agdusoehle8qihxs&data=somedata
and then use this token as a way of verifying that this Twilio request is associated with a user, is that secure?
I have seen this technique used before on password reset forms. An email will contain a link, and the user's identity is confirmed only using the token.
Is doing this in my Twilio app secure? Are there any gotchas to note?
It's as secure as any other request to your server from a remote HTTP client (like a browser). If you want to make sure that no one between Twilio's servers and yours can read the request, you should use HTTPS/SSL.
For this use case, it's probably better to associate the CallSid value that's sent with every request to your server with the user in your system. When the StatusCallback for a completed call fires, look up the user associated with that call and act accordingly.
A few of the browser-based single sign on protocols like OpenID and SAML use a similar technique to track state when redirecting between the site you're trying to authenticate to and the site doing the authentication. I think the technique is good enough for what you want to achieve.
I'm not familiar with Twilio, but I'd be careful about using to identify a user though. Generating a unique code (aka nonce) for every request and having Twilio pass that nonce back in the response would be more secure, as it only identifies a particular request. It might be overkill though.

Resources