Slack API missing_scope for bot requests - slack-api

I am trying to set channel topics with a bot user token, but I'm getting the missing_scope error:
{
ok: false,
error: 'missing_scope',
needed: 'channels:write',
provided: 'identify,bot:basic'
}
It works if I provide the "OAuth Access Token" (instead of "Bot User OAuth Access Token") from https://api.slack.com/apps/:appId/oauth, but this is a poor solution because the message that gets printed in the channel says that the app installer set the channel topic, not the bot user.
But, the docs say that bots can call channels.setTopic with a bot token, and they don't need channels:write:
What gives? Are there different kinds of bot tokens? Am I doing something wrong? As far as I can tell, I cannot set additional permissions for my bot user.

It also says on the the same documentation page:
Only user tokens may use this method. Bot user tokens will not work.
And since it does indeed not work as you say I am guessing the mention of the bot token in the above table is a documentation mistake.
If you want to be 100% sure I would advise to ask the Slack team directly.

Related

Authorization denied for bot when attempting to create conversation via API

I'm trying to develop a bot to be used exclusively for proactive messaging (since unfortunately, it appears Connectors do not support direct messaging). I stood up a web service, and was able to receive the payload from Teams when I sent a message to the bot.
I'm now trying to send a proactive message from the bot back to my user, as described here. Per the instructions, I am POSTing the following payload to <serviceUrl>/v3/conversations. (Values in brackets are interpolated from the payload I received from Teams)
{
"bot": {
"id": <recipient.id>,
"name": <recipient.name>
},
"isGroup": false,
"members": [
{
"id": <from.id>,
"name": <from.name>
}
],
"tenantId": <channelData.tenant.id>,
"topicName": "News Alert"
}
I also included a Bearer token that I got by calling https://login.microsoftonline.com/<channelData.tenant.id>/oauth2/v2.0/token. Yet, whenever I try to create the conversation, it fails with an error that "Authorization has been denied for this request." As far as I can tell, the token should be valid, so I'm not sure what else could be going on here. I saw something about trusting the service URL, but I'm not sure how I would do that since I'm not using the Bot SDK. Perhaps I'm going about this wrong and should be trying to create an Activity rather than a Conversation?
There are basically two steps in sending pro-active messages. The first step is just a once-off - it's getting the unique ID of the conversation between the bot and the user. It's the paragraph you're linking to in your original question, and it's the payload sample you're showing. Once you've got that conversation id, you'd then proceed to sending messages at any time in the future (that's this paragraph).
However, in Teams, the first part is handled differently. Rather than calling the bot framework conversation endpoint (recall that bot framework is used for other things aside from Teams bots), you wait for the user to install the app, which includes your bot. When this is done, your bot will receive a conversationUpdate event. When this fires, you'll be sent a payload which includes the conversationId of the newly-created conversation. This replaces the call you're currently making.
You need to save the conversationId, and the serviceUrl (which will be similar too 'https://smba.trafficmanager.net/apis', but unique for Teams, and will be the 'base' of the URL you'll call later).
Importantly, it is possible to "pre-install" an app for a user, using the Graph API. See Install app for user.
That should help with what you're missing. However, as an 'fyi', you can use libraries for this instead of making the call directly yourself. In dotnet, for instance, you can reference Microsoft.Bot.Connector.ConnectorClient (in Microsoft.Bot.Connector), which has a Conversations.SendToConversationAsync(..) method.
I think I've figured out the problem. I sent my token request to https://login.microsoftonline.com/<channelData.tenant.id>/oauth2/v2.0/token, which was successful and gave me a token back. However, the instructions outlined here say not to use <channelData.tenant.id>, but instead just the hardcoded string botframework.com. After requesting the token that way, my requests appear to be working.

Slack api conversations.history returns error: not_in_channel

I'm starting out with the Slack API and trying to just get a list of messages.
Here are my steps:
Created a Slack app and gave it channels:read and channels:history scope (also re-installed it)
Queried the list of channels with conversations.list (this worked fine)
From the output of conversations.list, I found a channel that I use and copied the id
Used the conversations.history api with the channelid from step 3
Result:
{ "ok": false, "error": "not_in_channel" }
I'm not at all sure what is happening here. I definitely have messages in the channel, and the documentation page for that api does not say anything about this "not_in_channel" error code.
What am I doing wrong?
After a long time of investigations (~2 hours), I found an easy approach. For Caleb's answer, I didn't understand how to invite a Bot to the channel. Hence, I am posting this answer.
Go to your Slack Channel and type the following as a message.
/invite #BOT_NAME
Eg: If your Bot name is SRE Incident Manager the command would be as follows.
/invite #sre_incident_manager
As soon as you start typing #, Slack will automatically suggest. So it becomes easy. For this, the Bot needs to be added to your Slack Workspace.
PS: Original answer.
The error not_in_channel has the exact meaning, your custom Slack app should be added to the channel.
Exact solution 1
To resolve the error, in the Web Slack interface:
Open channel settings
Click on the Integrations tab
Click Add apps and find your custom app.
Slack app might have different interface, see Iryna Vernik's answer.
Alternative solution 2
Give access to the bot to all channels by adding workspace wide scope, for example, chat:write.public. Depends on your needs and security requirements.
Alternative solution 3
To access the channel chat from API specify Incoming webhook. Slack will generate a unique URL with the token per each channel. Only convenient for a few channels.
This error arises when you are using the bot oauth token and the bot is not invited to the channel. To solve this you need to
Invite the bot(slack app) to join the channel.
Use the OAuth Access Token instead
To add Bot to your channel you need to write /invite #Bot_name in the slack channel
I also didn't understand how to invite a Bot to the channel. Way that was proposed by Caleb and Keet was not clear for me or not working. From my side, 'invite' work after
open channel
in Details tab, choose a 'More'clause
in dropdown menu, chouse an 'add app'
in pop-up look for you app (bot)
Also i was use Bot User OAuth Access Token, because i need this functionality in private channel (additionaly, you should add for bot groups:history scope)
FOr me, instead of invite a user/bot, I invite the app.
I'm getting started with the Slack API as well, and I've come to realize that not_in_channel simply means that the user/bot you are using the token for hasn't joined that particular channel you're trying to perform an action on.
Think of it this way: if you're using Slack on the web-browser or web-app, you wouldn't be able to post a message on a channel you haven't either joined or was invited to.
☝️ You'll also never run into this issue through the Slack UI/UX because you're not even able to access the channels UNTIL you are invited or join it.
Click to see png example of a slack message stating my bot being added to a channel
However, because we're using the API we can essentially skip some steps, and in this case we skipped the step where a user/bot has joined the channel before doing the action we're trying to perform (writing a message, grabbing information, etc).
💪 How to address this
There's probably plenty of ways to do it that I'm not versed in, but if you're just concerned about a specific channel or two without the concern of scaling to x channels I'll list the way that worked for me.
📇 /invite Slash Command
As others have mentioned, putting /invite in the message box lets you use Slack's slash command shortcut to add users. What's important is this way also allows us to invite bots to the channel.
Putting "#" triggers Slack to start auto-suggesting, which is why it then becomes easy to find your bot name in the list.
Click here to see screenshot example of the /invite command with #bot_name_here
Hope this helps answer people's question on why it's happening, and thank you to the original posts that got me out of my initial mess. 🙏
As all others said, you need to join each channel.
The bot can join channel programmatically by using API below:
https://api.slack.com/methods/conversations.join
Don't forget to add permission of conversations.join

Is it not possible anymore to use chat:write:bot scope for Slack apps

I want my app to chat.postMessages to Slack, using the icon_emoji and username parameters so that I sometimes change the icon and name displayed.
From the doc of the method, it seems I have to set as_user to false. But when I do so, I'm getting a missing_scope error: I need scope chat:write:bot. (Same error whether I use my OAuth access token or my OAuth bot user access token)
But from this page I got that they are disappearing? So are the parameters I want to use (icon_emoji and username) going to disappear as well?
No, as of Dec 19 2019, you cannot use icon_emoji, etc
I ran into the same issue, and so I opened a support ticket with Slack. After a few messages back and forth, I got confirmation that this is likely a bug:
With your help I was able to replicate the issue. I suspect this is a bug but I've escalated it to the Granular Bot Token team for a second opinion. As soon as I have more details I will let you know.
Edit:
I've received another update, which I've trimmed down to the essentials:
When building the Granular Bot Token model our team really wanted to use this as an opportunity to slowly deprecate certain API behaviour. The as_user parameter is one of them. See the following comment from (https://api.slack.com/authentication/quickstart).
One effect worth noting: chat.postMessage and other chat.* methods no longer mess around with the as_user parameter. You're granted a single chat:write scope (no :user or :bot is appended). If you call the chat.postMessage method with your bot token, you post as the bot. If you've obtained a user token through the new install flow, and you call the method with your user token, you post as the user.
So in regards to the action you are wanting to take, I'm afraid it's not possible with Granular Bot Token. We also recognized that the error this is throwing is completely unhelpful and confusing for developers. For this, we've created a bug to fix the error that's returned when Granular Bot tokens try to make restricted API calls.
I've requested clarification on whether it is just the as_user part that is deprecated, or the icon_emoji part as well.
Edit 2 (Dec 19, 2019 13:38 EST):
One, probably final, update:
The option for app to change information such as username, avatar and icon via the API is up for debate as well. Currently with Granular Bot Tokens you can only update that information via your API management page.
Which is really unfortunate.
I had to add a Scope to "Bot Token Scopes" with the value of "chat:write.customize".
https://api.slack.com/scopes/chat:write.customize
then I had to re-install my app. And it worked like I expected.
Note: I tried this as it was a suggestion from a comment. but it worked so i am adding it as an answer.

Slack API Opening a New DM (Scopes and Permissions)

I am attempting to open a DM (Direct Message) with an arbitrary user using the im.open Slack API call. I am sending it a user's user_id that I obtain through their clicking of a consent button in order to begin a series of questions. I am sending data to the Slack API successfully along with receiving data. I am getting the following response...
{
"ok": false,
"error": "missing_scope",
"needed": "im:write",
"provided": "identify,incoming-webhook,chat:write:user,files:write:user",
}
I have went into the application's page and changed the scope of the app (I am not the owner, but have been given collaborator permissions by my team lead (the owner)). These are the current permissions...
I apologize for the poor quality of the image. The scopes are as follows...
identify
incoming-webhook
chat:write:user
files:write:user
im:write
After this change, I am still getting the same response from the Slack API. The following is what I am sending them (it's my user_id, and I don't mind).
{
"user": "U94155Z43"
}
Any help is appreciated. Thanks.
I needed to use the bot token "xoxb" instead of the user token "xoxp" which I had used for all other slack api calls.

Can't access Microsoft Graph users calendars 403

I have seen other posts that are very similar, but I don't find a real answer. Some say "it is coming", those are old.
I am authenticating with the Admin credentials to our O365 and trying to pull calendar information. The Scope has Calendars.ReadWrite (which falls under App-Only and Delegate as far as scopes), but it always returns a 403. ErrorAccessDenied, "Access is denied. Check credentials and try again"
The Graph doc for calendar views shows it can send in users/{id} in the request, and the id's came back when I listed all the users. Of course if I use mine, it works.
If there really is an App-Only scope vs a Delegate scope for this same scope name, how do you specify that?
Is there something I have to specify in O365 for my admin user so it has rights? I can delete or create any user with that account in O365, so it appears it should have what it needs.
Thanks
So, App-Only has a slightly different flow.
First, instead of authenticating the user at "https://login.microsoftonline.com/common/oauth2/v2.0/authorize", you authenticate them at "https://login.microsoftonline.com/common/adminconsent".
Second, you pass in the same parameters minus "scope". Scope is determined by your Application Permissions defined in you application that you registered at apps.dev.microsoft.com.
Third, when you receive your callback you will not have a "code" to use to go and retrieve your Access and Refresh tokens. Instead, you will receive a "tenant" property and an "admin_consent" property. "admin_consent" will tell you whether you have the rights or not.
Fourth, when requesting your access token, you will not supply the "scope" or "code" parameters, but you will provide a "resource" parameter, with the value "https://graph.microsoft.com".
Lastly, the URL you contact to get the token will change from "https://login.microsoftonline.com/common/oauth2/v2.0/token" to "https://login.microsoftonline.com/{tenant}/oauth2/token", where {tenant} will be the value returned.
Please note that in the URL that "v2.0" is missing. That isn't a typo. If you do not remove that from the path you will get errors about an invalid or missing "scope" parameter.
Once it successfully returns your Access and Refresh token, the flow seems to follow normal delegated access.
Here are a couple of links that Microsoft gave me, with their guidance to help figure this out.
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-scopes#using-the-admin-consent-endpoint
https://developer.microsoft.com/en-us/graph/docs/authorization/app_only
(Big Thanks to Jeff at Microsoft)
Latest doc is here: https://learn.microsoft.com/en-us/graph/auth-v2-service
I followed it and I was able to read/write other's calendar with permission Calendars.ReadWrite.

Resources