Slack & Salesforce - Rest API - Outgoing webhook - salesforce

I am trying to connect to Salesforce Apex using POST. Slack has this pluggin, Outgoing Webhook which sends to a URL a POST request.
I have already created an APEX class to handle the request,
#RestResource(urlMapping='/test/accounts/*')
global with sharing class REST_slackAccount {
#HttpGet
global static void doGet() {
System.debug('Connected');
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
//accountId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
System.debug('Connected');
}
}
I am getting nothing from Salesforce when i trigger the request from Slack. What am i doing wrong.
I have already created a remote site settings.
The URL i used in Slack to make the POST request is:
https://test.salesforce.com/services//test/accounts/
Thank you.

It looks like that controller is only handling GET requests but Slack is doing a POST.

Related

Can I use SSO credentials to hit my Subscribed org Web Service Class in Salesforce?

I have implemented SSO among two ORGS. I have made a web services class in my Subscribed Org. Can I hit that web service from my Identity provider Org using rest callout? I tried it by making a http get request which for which I use following URL pattern (Subscribed Org Url + Urlmap to Web service class) as a response I got 302 status with updated URL, Too handle this
I used following code.
while (response.getStatusCode() == 302) {
request.setEndpoint(response.getHeader('Location'));
System.debug('END Location isi '+response.getHeader('Location'));
response = new Http().send(request);
}
I was hitting this point https://cloudce-13a-dev-ed.lightning.force.com/Case/abc
but it redirected to https://cloudce-13a-dev-ed.my.salesforce.com/Case
But nothing happens.

Alexa, Unable to link your skill

I am creating custom skill in Alexa which uses account linking. I have created my own authentication server using OAuth2 php library and I have configured the authorization url and token urls in skill configuration.
When I try account linking from Alexa mobile app, I get error 'unable to link your skill'. following is my work progress.
Alexa app is able to open my authentication url.
I am able authorize and provide authorization code with redirect uri.
Alexa is requesting for access token using authorization code previously provided.
I am able validate authorization code and response back with access token and refresh token.
Alexa fails in this step to link with my skill. It say's 'Unable to link your skill'.
I have gone through my forums about the same, but couldn't find what exactly the issue is. Could any one please help me out in this regard.
I was facing the same issue too , the problem was solved by selecting "credentials in request body" (default being Http basic) for "Client Authentication Scheme", since the access token in my case was sent in the body of the message. Check how the authentication token is sent by your server.
If your redirect link is currently:
https://layla.amazon.com/api/skill/link/xxxxxxxxxxxxxx?code=xxxxxxxxx&state=xxxxx
You need to change the ? to a #
e.g.
https://layla.amazon.com/api/skill/link/xxxxxxxxxxxxxx#code=xxxxxxxxx&state=xxxxx
Thought this might help anyone wondering how the Alexa service is posting to their OAuth endpoint since it's pretty opaque and undocumented. The redirect to the Alexa service initiates a POST request to the defined OAuth endpoint with the post body in x-www-form-urlencoded format not JSON. So the POST looks like this.
​
POST /authentication/1/oauth HTTP/1.1 url.Values{} grant_type=authorization_code&code=XXXXXXXXXXXXXXXXXXXXXXXXX&redirect_uri=https%253A%252F%252Fpitangui.amazon.com%252Fapi%252Fskill%252Flink%252FM9BEOG3DM65SQ&client_id=XXXXXXXXXXXXXXXXXXXXXX
If your endpoint isn't parsing this data or expecting some format that can be unmarshaled easily then it is probably failing with a 406 response.
In my case the problem was with the Client secret,
In google developer console add your skill redirect URIs
and recheck the client secret you provide in the alexa skill Authorization grant type
My issue was with the final AccessToken call. I was assuming it was using a GET request, so I only catered for this in my function. It is actually creating an access token. So it's using a POST.
After I updated my function to use a post and return the AccessToken in JSON format it all works fine.
Maybe the following steps will help you identify the problem:
Add console.log('LOGS', response) to your Lambda function.
Activate the skill and login in the Alexa app
Go back to your Lambda function and check the last logs for the LOGS entry.
If you find that the Lambda function is invoked than the problem is not from your OAuth server, but you may need to handle the "AcceptGrant directive" in your Lambda function as it is motioned here: https://developer.amazon.com/en-US/docs/alexa/device-apis/alexa-authorization.html#directives
adjust your Lambda function to:
exports.handler = function (request, context) {
if (request.directive.header.namespace === 'Alexa.Authorization' && request.directive.header.name === 'AcceptGrant') {
log("DEBUG:", "Authorization request", JSON.stringify(request));
handleAcceptGrant(request, context);
}
function handleAcceptGrant(request, context) {
var response = {
event: {
header: {
"namespace": "Alexa.Authorization",
"name": "AcceptGrant.Response",
"messageId": request.directive.header.messageId,
"payloadVersion": "3"
},
payload: {}
}
};
log("DEBUG", "Alexa.Authorization ", JSON.stringify(response));
context.succeed(response);
}
If the problem is with the AcceptGrant then The account linking should be now successful.

GAE - why Post request has parameters exposed in URL?

I have simple post request to cloud endpoint
#ApiMethod(name = "insertEmployee", httpMethod = HttpMethod.POST)
public Employee insertEmployee(#Named("phoneNumber") Long phoneNumber,
#Named("emailId") String emailId) { ... }
which accepts request of form
POST http://localhost:8888/_ah/api/employeeendpoint/v1/employee/87900850/q%40m.com
Is there something wrong with API design or url is wrong?
i have used REST client from browser to query localhost as well as deployment.

Responding with data to a Slack url in Express

I have the following route in my Node backend with express middleware. My app uses the Slack backslash api to post a link to a user's channel. When user clicks it opens a form on an angular app hosted on heroku.
What I am looking to do is update the Slack user when the form get submitted.
So the question, how can I send a post request to slack url when the route below gets triggered(obviously the res is pointing to the /update). I've researched quite a bit and tried rewriting headers and using low level http methods, but I have a feeling there is a better solution to this. Many thanks for your help.
app.post("/update", function(req,res,next) {
res url -> http://slackapi/12345/
res.json({"text":"hello":}
})
res is not supposed to be sent to slack, this is the response to whoever contacted you. you need to send a different request to slack, and return whatever you want with res.
You can use request module to generate a http request to slack.
var request = require('request');
app.post("/update", function(req,res,next) {
request('http://slackapi/12345/', function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
res.json({"text":"some answer to the requester"});
} else {
res.json({"text":"notify requester sending to slack falied"});
}
});
});

AngularJS: Sending Authentication Headers over Websocket

I am having difficulty authenticating requests to a WebSocket API.
The Site I am working with (www.bitmex.com) provides a REST API and a WebSocket API.
Both of their API's allow authentication with an API Key.
Authentication Requirements
The API provides the following documentation for authentication with API Keys:
Authentication is done by sending the following HTTP headers:
api-expires: a UNIX timestamp in the future (eg: 5 seconds).
api-key: Your public API key. This the id param returned when you create an API Key via the API.
api-signature: A signature of the request you are making. It is calculated as hex(HMAC_SHA256(verb + url + nonce + data)).
REST API
I've created a NodeJS module for sending requests to the REST API, I've defined the following headers
headers = {
"User-Agent": "BitMEX NodeJS API Client",
"api-expires": expires,
"api-key": this.api_key,
"api-signature": this.signMessage(verb, reqUrl, expires, params)
};
where the signMessage function looks like:
BitMEX.prototype.signMessage = function signMessage(verb, url, nonce, data) {
if (!data || _.isEmpty(data)) data = '';
else if(_.isObject(data)) data = formatParameters(data);
return crypto.createHmac('sha256', this.secret).update(verb + url + nonce + data).digest('hex');
};
This works great for the REST API and does everything I need it to in the backend of my application.
WebSocket API
I am trying to use WebSocket get realtime data and display it in a browser based interface.
The documentation on the site states:
To use an API Key with websockets, you must sign the initial upgrade request in the same manner you would sign other REST calls.
I've been implementing this in AngularJS using the ng-websocket module.
exchange.dataStream = $websocket('wss://testnet.bitmex.com/realtime');
exchange.dataStream.onMessage(function incoming (message) {
console.log("BitMEX: WS MESSAGE RECEIVED: " + message.data);
// .. handle data here ...
});
exchange.dataStream.send({"op":"getAccount"});
The problem that I've run into is I can't find anyway to send the headers using ng-websocket that are needed for authentication.
If I am presently logged in to BitMEX from another tab in my browser, this will connect, get the data, and work as expected.
However, if I am not currently logged in to the site, it will throw the following error:
BitMEX: WS MESSAGE RECEIVED: {"status":401,"error":"Not authenticated.","meta":{},"request":{"op":"getAccount"}}
There is a python example provided here: https://github.com/BitMEX/market-maker/blob/master/test/websocket-apikey-auth-test.py that goes through the Authentication process,
but I haven't found a way to accomplish this in AngularJS.
Summary
#1) When logged in to BitMEX, and the Websocket is working, is Chrome somehow using the website's cookies to authenticate the websocket requests?
Looking at an overview of websockets here: http://enterprisewebbook.com/ch8_websockets.html
The initial handshake upgrades the connection from "HTTP" to the WebSocket protocol,
#2) Because this initial connection is over HTTP, is there any way to attach the headers required to this initial HTTP request?
If you read the Python example, the first thing it sends is {"op": "authKey", "args": [API_KEY, nonce, signature]} then it sends {"op": "getAccount"}
Python example line #44 and line #51
How Chrome does it is another question.

Resources